### README (README.md) # Spring AI [](https://github.com/spring-projects/spring-ai/actions/workflows/continuous-integration.yml) [](https://central.sonatype.com/artifact/org.springframework.ai/spring-ai-model) The Spring AI project provides a Spring-friendly API and abstractions for developing AI applications. Its goal is to apply Spring ecosystem design principles, such as portability and modular design, to the AI domain and promote using strongly-typed data structures and APIs as the building blocks of an application. At its core, Spring AI addresses the fundamental challenge of AI integration: connecting your enterprise __Data__ and __APIs__ with the __AI Models__. ## Getting Started The [reference documentation](https://docs.spring.io/spring-ai/reference/) includes a [Getting Started](https://docs.spring.io/spring-ai/reference/getting-started.html) guide. Spring Boot Version Compatibility: * **Spring AI 2.x.x** ([main](https://github.com/spring-projects/spring-ai/tree/main) branch) - Spring Boot `4.x` * **Spring AI 1.1.x** ([1.1.x](https://github.com/spring-projects/spring-ai/tree/1.1.x) branch) - Spring Boot `3.5.x` ## Project Resources * [Reference documentation](https://docs.spring.io/spring-ai/reference/) * [Javadoc](https://docs.spring.io/spring-ai/docs/current/api/) * [Upgrade notes](https://docs.spring.io/spring-ai/reference/upgrade-notes.html) * [Awesome Spring AI](https://github.com/spring-ai-community/awesome-spring-ai) - A curated list of awesome resources, tools, tutorials, and projects for building generative AI applications using Spring AI * [Spring AI Examples](https://github.com/spring-projects/spring-ai-examples) - Contains example projects that explain specific features in more detail. * [Spring AI Community](https://github.com/spring-ai-community) - A community-driven organization for building Spring-based integrations with AI models, agents, vector databases, and more. ## Contributing We welcome contributions of all kinds! Please read our [contribution guidelines](CONTRIBUTING.md) before submitting a pull request or an issue. ## Features This is a high level feature overview. * Support for all major [AI Model providers](https://docs.spring.io/spring-ai/reference/api/index.html) such as Anthropic, OpenAI, Amazon Bedrock, Google, Ollama, Mistral AI, DeepSeek, and more. Supported model types include: - [Chat](https://docs.spring.io/spring-ai/reference/api/chatmodel.html) - [Embedding](https://docs.spring.io/spring-ai/reference/api/embeddings.html) - [Text to Image](https://docs.spring.io/spring-ai/reference/api/imageclient.html) - [Audio Transcription](https://docs.spring.io/spring-ai/reference/api/audio/transcriptions.html) - [Text to Speech](https://docs.spring.io/spring-ai/reference/api/audio/speech.html) - [Moderation](https://docs.spring.io/spring-ai/reference/api/index.html#api/moderation) * Portable API support across AI providers for both synchronous and streaming options. Access to [model-specific features](https://docs.spring.io/spring-ai/reference/api/chatmodel.html#_chat_options) is also available. * [Structured Outputs](https://docs.spring.io/spring-ai/reference/api/structured-output-converter.html) - Mapping of AI Model output to POJOs. * Support for all major [Vector Store providers](https://docs.spring.io/spring-ai/reference/api/vectordbs.html) such as *Amazon Bedrock Knowledge Base, Amazon S3, Apache Cassandra, Azure Vector Search, Chroma, Couchbase, Elasticsearch, GemFire, MariaDB, Milvus, MongoDB Atlas, Neo4j, OpenSearch, Oracle, PostgreSQL/PGVector, Pinecone, Qdrant, Redis, Typesense, and Weaviate*. * Portable API across Vector Store providers, including a novel SQL-like [metadata filter API](https://docs.spring.io/spring-ai/reference/api/vectordbs.html#metadata-filters). * [Tool Calling](https://docs.spring.io/spring-ai/reference/api/tools.html) - Permits the model to request the execution of client-side tools and functions, thereby accessing necessary real-time information as required. * [Observability](https://docs.spring.io/spring-ai/reference/observability/index.html) - Provides insights into AI-related operations. * Document injection [ETL framework](https://docs.spring.io/spring-ai/reference/api/etl-pipeline.html) for Data Engineering. * [AI Model Evaluation](https://docs.spring.io/spring-ai/reference/api/testing.html) - Utilities to help evaluate generated content and protect against hallucinated response. * [ChatClient API](https://docs.spring.io/spring-ai/reference/api/chatclient.html) - Fluent API for communicating with AI Chat Models, idiomatically similar to the WebClient and RestClient APIs. * [Advisors API](https://docs.spring.io/spring-ai/reference/api/advisors.html) - Encapsulates recurring Generative AI patterns, transforms data sent to and from Language Models (LLMs), and provides portability across various models and use cases. * [MCP (Model Context Protocol)](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-overview.html) - First-class support via Boot Starters and MCP Java Annotations for building AI applications that consume MCP servers or expose Spring-based services to the AI ecosystem, with STDIO, SSE, and Streamable-HTTP transport support. * Support for [Chat Conversation Memory](https://docs.spring.io/spring-ai/reference/api/chatclient.html#_chat_memory) with pluggable persistent backends (JDBC, Cassandra, MongoDB, Neo4j, Redis) and [Retrieval Augmented Generation (RAG)](https://docs.spring.io/spring-ai/reference/api/chatclient.html#_retrieval_augmented_generation). * Spring Boot Auto Configuration and Starters for all AI Models and Vector Stores - use [start.spring.io](https://start.spring.io/) to select the Model or Vector Store of choice. ## Building from source You don’t need to build from source to use Spring AI. If you want to try out the latest and greatest, Spring AI can be built and published to your local Maven repository: ```shell ./mvnw clean install ``` This command builds all modules, runs unit tests, and publishes artifacts to your local Maven repository. Please read our [contribution guidelines](CONTRIBUTING.md) for more details. --- ### AGENTS (AGENTS.md) Follow [CONTRIBUTING.md](CONTRIBUTING.md) for code style, commit messages, pull requests and to learn the most useful build commands. --- ### CLAUDE (CLAUDE.md) Follow @CONTRIBUTING.md for code style, commit messages, pull requests and to learn the most useful build commands. --- ### CONTRIBUTING (CONTRIBUTING.md) # Contributing to Spring AI Spring AI is released under the Apache 2.0 license. If you would like to contribute something, or want to hack on the code, this document should help you get started. ## Code of Conduct This project adheres to the Contributor Covenant [code of conduct](https://github.com/spring-projects/spring-ai#coc-ov-file). By participating, you are expected to uphold this code. Please report unacceptable behavior to code-of-conduct@spring.io. **We accept contributions created with the help of AI coding agents, but they must be carefully reviewed by a human who remains accountable for the quality of the contribution.** Contributions submitted by GitHub accounts controlled by autonomous AI bots are forbidden and will result in permanent bans. ## Reporting Security Vulnerabilities If you think you have found a security vulnerability in Spring AI please **DO NOT** disclose it publicly until we've had a chance to fix it. Please don't report security vulnerabilities using GitHub issues or pull requests, instead head over to https://spring.io/security-policy and learn how to disclose them responsibly. ## Ask questions If you have a question, check Stack Overflow using [this list of tags](https://stackoverflow.com/questions/tagged/spring-ai) or [Spring AI discussions](https://github.com/spring-projects/spring-ai/discussions). Find an existing discussion, or start a new one if necessary. ## How to contribute ### Search first Is there already an existing [issue](https://github.com/spring-projects/spring-ai/issues) or a [pull request](https://github.com/spring-projects/spring-ai/pulls) that addresses your concern? Search to see if you can find something similar before creating a new one. ### Submit an issue If you are reporting a bug, please help to speed up problem diagnosis by providing as much information as possible. Ideally, that would include a small sample project that reproduces the problem, shared with a link to a related source repository or attached as an archive with instructions on how to reproduce. You can also submit an enhancement or a new feature proposal. The issue title is used to generate the changelog so please use a short and descriptive text with types or filenames enclosed in backticks. ### Submit a pull request Should you create an issue first? No, just create the pull request and use the description to provide context and motivation, as you would for an issue. You only have to create an issue if you want to start a discussion first. Please don't submit pull requests: * With GitHub accounts managed by autonomous AI bots * For already assigned issues (as the assignee is or plans to work on it) * For straightforward or polish-style changes The pull request title is used to generate the changelog so please use a short and descriptive text with types or filenames enclosed in backticks. If your pull request is related to an issue, please mention the related issue with its number in the PR description (not in the title), for example "Fixes #123". Before submitting a pull request: * Add new tests that exercise the code you have added or modified * Run the build and tests locally with `./mvnw clean package` * If possible run integration tests related to the part you modify (see related documentation below) * Any code needs to be carefully reviewed by a human, especially when generated by a coding agent ## Commit message A commit message should include a short title (if possible less than 50 characters) starting with an uppercase verb. The title should *not* include prefixes like `fix:`, `feat:` or `docs:` or the issue/PR number. - ✅ Add Contribution Guidelines - ❌ GH-123: Add Contribution Guidelines - ❌ docs: Add Contribution Guidelines - ❌ Add Contribution Guidelines (#123) The commit description should be wrapped at approximately 72 characters. Commit messages should allow discoverability of related issues and PRs [by linking them](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword) after the description with for example `Closes #123` if the issue number is 123. That allows bi-directional navigation from the commit to the issue/PR, but also in the other way around as related mentions are added by GitHub. All commits must include a __Signed-off-by__ trailer at the end of each commit message to indicate that the contributor agrees to the Developer Certificate of Origin. For additional details, please refer to the blog post [Hello DCO, Goodbye CLA: Simplifying Contributions to Spring](https://spring.io/blog/2025/01/06/hello-dco-goodbye-cla-simplifying-contributions-to-spring). Please find below the example of a typical commit message: ```text Add Contribution Guidelines This commit adds CONTRIBUTING.md describing the Contribution procedure, mentions Contribution Guidelines in the README.md and mentions CODE_OF_CONDUCT in the README.md. Fixes #123 Signed-off-by: Firstname Lastname ``` If you want to only reference some issue or PR without closing it, you can use `See #123`. Annotations should be enclosed in backticks to avoid mentioning potential related GitHub users. If the commit has both an issue and a PR associated, the Spring AI committer merging the PR should reference both the issue and the PR and ensure the title does not contain the number of the PR, for example with an issue #123 and a PR #456: ```text Add Contribution Guidelines ... Fixes #123 Closes #456 Signed-off-by: Firstname Lastname ``` ## Source code style Spring AI source code style follows the checkstyle guidelines used by the [core Spring Framework project](https://github.com/spring-projects/spring-framework/wiki/Code-Style) with some exceptions. See also related [IntelliJ IDEA Editor Settings](https://github.com/spring-projects/spring-framework/blob/main/src/idea/spring-framework.xml). The code is formatted using the [java-format plugin](https://github.com/spring-io/spring-javaformat) as part of the build. Correct formatting is enforced by CI. To format the code specifically: ```shell ./mvnw process-sources ``` Note that this will not format the import order which is documented below. ### Formatting Please carefully follow the whitespace and formatting conventions already present in the framework. * UTF-8 encoding * Tabs, not spaces * Unix (LF), not DOS (CRLF) line endings * Eliminate all trailing whitespace * Wrap Javadoc at 90 characters * Aim to wrap code at 120 characters, but favor readability over wrapping * Preserve existing formatting; i.e. do not reformat code for its own sake * For plain text documents like `.adoc` or `.md`, one sentence per line The import statements are structured as follows: * import `java.*` * blank line * import `javax.*` * import `jakarta.*` * blank line * import all other imports * blank line * import `org.springframework.*` * blank line * import static all other imports Static imports should not be used in production code, but they should be used in test code, especially for things like `import static org.assertj.core.api.Assertions.assertThat;`. Although static imports are generally forbidden in production code, the following are use cases for which static imports are permissible. * constants (including enum constants): such as those in `java.nio.charset.StandardCharsets` or `org.springframework.core.annotation.MergedAnnotations.SearchStrategy` * static factory methods for third-party DSLs: such as the methods in `org.junit.platform.engine.discovery.DiscoverySelectors` when used with the JUnit Platform `Launcher` API Wildcard imports such as `import java.util.*` or `import static org.assertj.core.api.Assertions.*` are forbidden, even in test code. ### Source file structure A source file consists of the following, in this exact order: * License * Package statement * Import statements * Exactly one top-level class Exactly one blank line separates each of the above sections. #### License ```java /* * Copyright 2023-present 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. */ ``` #### `@since` tags Use `@since` tags for newly-added public API types and methods e.g. ```java /** * ... * * @since 2.0.0 */ ``` ### Working with the code #### Building from source The project can be built from the root directory using the standard Maven command: ```shell ./mvnw clean package ``` ##### JDK The project targets and builds artifacts compatible with Java 17+, and requires a JDK with support for the [`-XDaddTypeAnnotationsToSymbol` javac argument](https://bugs.openjdk.org/browse/JDK-8373586), like Liberica 17.0.19+, for nullability checks. The recommended JDK is specified in the `.sdkmanrc` file, which can be installed and configured with the [SDKMAN!](https://sdkman.io/) tool: - `sdk env install` to install the related JDK locally - `sdk env` to use the related JDK **NOTE:** Make sure to use a JDK with the same architecture as your processor, not an emulated one (for example with Rosetta on Mac) as Spring AI requires components that depend on your specific CPU architecture (PyTorch for example). If you are unsure if you have the correct JDK distribution for your CPU, run the command `java -XshowSettings:properties -version 2>&1 | grep os.arch` to validate that it matches your machine. ##### Maven build-cache extension The [Maven build-cache extension](https://maven.apache.org/extensions/maven-build-cache-extension/) is enabled by default to speedup builds. If you suspect the build cache is in an invalid state (build broken for no identified reason), try to run the build while disabling the build cache, for example with: ```shell ./mvnw -Dmaven.build.cache.enabled=false clean package ``` If the build passes without the cache, please [file an issue](https://github.com/spring-projects/spring-ai/issues) describing with as much detail as possible how that happened, and remove the local cache as a workaround: ```shell rm -rf ~/.m2/build-cache/ ``` #### Integration Tests There are many integration tests, so it often isn't realistic to run them all at once. Note that you should set API key environment variables for model providers before running. If the API key isn't set for a specific model provider, the integration test is skipped. To run the integration test for a specific module: ```shell ./mvnw -am -pl spring-ai-spring-boot-testcontainers -Pintegration-tests verify ``` To run a specific integration test allowing for up to two attempts to succeed (this is useful when a hosted service is not reliable or times out): ```shell ./mvnw -am -pl vector-stores/spring-ai-pgvector-store -Pintegration-tests -Dfailsafe.failIfNoSpecifiedTests=false -Dfailsafe.rerunFailingTestsCount=2 -Dit.test=PgVectorStoreIT verify ``` A quick pass through the most important pathways that runs integration tests can be done with the profile `-Pci-fast-integration-tests` and is used in the main CI build of this project. Full integration tests are done regularly in the [Spring AI Integration Tests](https://github.com/spring-projects/spring-ai-integration-tests) repository. #### Javadocs To check javadocs using the [javadoc:javadoc](https://maven.apache.org/plugins/maven-javadoc-plugin/): ```shell ./mvnw javadoc:javadoc ``` #### Reference documentation To build the docs: ```shell ./mvnw -pl spring-ai-docs antora ``` The generated documentation is available at `spring-ai-docs/target/antora/site/index.html`. --- ### LICENSE (LICENSE.txt) Apache License Version 2.0, January 2004 https://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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. --- ### Auto Configurations/Mcp/Spring Ai Autoconfigure Mcp Client Common/Src/Test/Resources/Test Config.Json (auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-common/src/test/resources/test-config.json) { "name": "test-config", "description": "Test JSON file in root test resources folder", "version": "1.0.0", "properties": { "testProperty1": "value1" } } --- ### Auto Configurations/Mcp/Spring Ai Autoconfigure Mcp Client Common/Src/Test/Resources/Nested/Nested Config.Json (auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-common/src/test/resources/nested/nested-config.json) { "name": "nested-config", "description": "Test JSON file in nested subfolder of test resources", "version": "1.0.0", "nestedProperties": { "nestedProperty1": "nestedValue1" } } --- ### Auto Configurations/Mcp/Spring Ai Autoconfigure Mcp Client Httpclient/Src/Test/Resources/Test Config.Json (auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-httpclient/src/test/resources/test-config.json) { "name": "test-config", "description": "Test JSON file in root test resources folder", "version": "1.0.0", "properties": { "testProperty1": "value1" } } --- ### Auto Configurations/Mcp/Spring Ai Autoconfigure Mcp Client Httpclient/Src/Test/Resources/Nested/Nested Config.Json (auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-httpclient/src/test/resources/nested/nested-config.json) { "name": "nested-config", "description": "Test JSON file in nested subfolder of test resources", "version": "1.0.0", "nestedProperties": { "nestedProperty1": "nestedValue1" } } --- ### Auto Configurations/Mcp/Spring Ai Autoconfigure Mcp Client Webflux/Src/Test/Resources/Test Config.Json (auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-webflux/src/test/resources/test-config.json) { "name": "test-config", "description": "Test JSON file in root test resources folder", "version": "1.0.0", "properties": { "testProperty1": "value1" } } --- ### Auto Configurations/Mcp/Spring Ai Autoconfigure Mcp Client Webflux/Src/Test/Resources/Nested/Nested Config.Json (auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-webflux/src/test/resources/nested/nested-config.json) { "name": "nested-config", "description": "Test JSON file in nested subfolder of test resources", "version": "1.0.0", "nestedProperties": { "nestedProperty1": "nestedValue1" } } --- ### Auto Configurations/Models/Chat/Client/Spring Ai Autoconfigure Model Chat Client/Src/Main/Resources/META INF/Additional Spring Configuration Metadata.Json (auto-configurations/models/chat/client/spring-ai-autoconfigure-model-chat-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json) { "properties": [ { "name": "spring.ai.model.chat", "type": "java.lang.String", "description": "The primary ChatModel to autoconfigure. If not set, each ChatModel auto-configuration is enabled by default.", "defaultValue": "" }, { "name": "spring.ai.model.embedding", "type": "java.lang.String", "description": "The primary EmbeddingModel to autoconfigure. If not set, each EmbeddingModel auto-configuration is enabled by default.", "defaultValue": "" }, { "name": "spring.ai.model.embedding.text", "type": "java.lang.String", "description": "The primary EmbeddingModel for text embeddings to autoconfigure. If not set, each text EmbeddingModel auto-configuration is enabled by default.", "defaultValue": "" }, { "name": "spring.ai.model.embedding.multimodal", "type": "java.lang.String", "description": "The primary EmbeddingModel for multimodal embeddings to autoconfigure. If not set, each multimodal EmbeddingModel auto-configuration is enabled by default.", "defaultValue": "" }, { "name": "spring.ai.model.image", "type": "java.lang.String", "description": "The primary ImageModel to autoconfigure. If not set, each ImageModel auto-configuration is enabled by default.", "defaultValue": "" }, { "name": "spring.ai.model.audio.transcription", "type": "java.lang.String", "description": "The primary TranscriptionModel to autoconfigure. If not set, each TranscriptionModel auto-configuration is enabled by default.", "defaultValue": "" }, { "name": "spring.ai.model.audio.speech", "type": "java.lang.String", "description": "The primary SpeechModel to autoconfigure. If not set, each SpeechModel auto-configuration is enabled by default.", "defaultValue": "" }, { "name": "spring.ai.model.moderation", "type": "java.lang.String", "description": "The primary ModerationModel to autoconfigure. If not set, each ModerationModel auto-configuration is enabled by default.", "defaultValue": "" } ] } --- ### Auto Configurations/Models/Spring Ai Autoconfigure Model Google Genai/MIGRATION GUIDE (auto-configurations/models/spring-ai-autoconfigure-model-google-genai/MIGRATION_GUIDE.md) # Migration Guide: Spring AI Google GenAI Autoconfiguration ## Overview This guide helps you migrate from the old Vertex AI-based autoconfiguration to the new Google GenAI SDK-based autoconfiguration. ## Starter Dependencies Spring AI provides separate starters for Google GenAI functionality: ### Chat Functionality ```xml org.springframework.ai spring-ai-starter-model-google-genai 1.1.0-SNAPSHOT ``` ### Embedding Functionality ```xml org.springframework.ai spring-ai-starter-model-google-genai-embedding 1.1.0-SNAPSHOT ``` **Note**: If you need both chat and embedding capabilities, include both starters in your project. The starters are designed to be used independently or together based on your requirements. ## Key Changes ### 1. Property Namespace Changes Old properties: ```properties spring.ai.vertex.ai.gemini.project-id=my-project spring.ai.vertex.ai.gemini.location=us-central1 spring.ai.vertex.ai.gemini.chat.options.model=gemini-pro spring.ai.vertex.ai.embedding.text.options.model=textembedding-gecko ``` New properties: ```properties # For Vertex AI mode spring.ai.google.genai.project-id=my-project spring.ai.google.genai.location=us-central1 spring.ai.google.genai.chat.model=gemini-2.0-flash # For Gemini Developer API mode (new!) spring.ai.google.genai.api-key=your-api-key spring.ai.google.genai.chat.model=gemini-2.0-flash # Embedding properties spring.ai.google.genai.embedding.project-id=my-project spring.ai.google.genai.embedding.location=us-central1 spring.ai.google.genai.embedding.text.options.model=text-embedding-004 ``` ### 2. New Authentication Options The new SDK supports both: - **Vertex AI mode**: Using Google Cloud credentials (same as before) - **Gemini Developer API mode**: Using API keys (new!) ### 3. Removed Features - `transport` property is no longer needed - Multimodal embedding autoconfiguration has been removed (pending support in new SDK) ### 4. Bean Name Changes If you were autowiring beans by name: - `vertexAi` → `googleGenAiClient` - `vertexAiGeminiChat` → `googleGenAiChatModel` - `textEmbedding` → `googleGenAiTextEmbedding` ### 5. Class Changes If you were importing classes directly: - `com.google.cloud.vertexai.VertexAI` → `com.google.genai.Client` - `org.springframework.ai.vertexai.gemini.*` → `org.springframework.ai.google.genai.*` ## Migration Steps 1. Update your application properties: - Replace `spring.ai.vertex.ai.*` with `spring.ai.google.genai.*` - Remove any `transport` configuration 2. If using API key authentication: - Set `spring.ai.google.genai.api-key` property - Remove project-id and location for chat (not needed with API key) 3. Update any custom configurations or bean references 4. Test your application thoroughly ## Environment Variables ```bash export GOOGLE_CLOUD_PROJECT=my-project export GOOGLE_CLOUD_LOCATION=us-central1 ``` New (additional option): ```bash export GOOGLE_API_KEY=your-api-key ``` ## Backward Compatibility The old autoconfiguration module is still available but deprecated. We recommend migrating to the new module as soon as possible. --- ### Auto Configurations/Models/Spring Ai Autoconfigure Model Google Genai/Src/Test/Resources/Fake Credentials.Json (auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/resources/fake-credentials.json) { "type": "authorized_user", "client_id": "test-client-id.apps.googleusercontent.com", "client_secret": "test-client-secret", "refresh_token": "test-refresh-token" } --- ### Auto Configurations/Models/Spring Ai Autoconfigure Model Mistral Ai/Src/Main/Resources/META INF/Additional Spring Configuration Metadata.Json (auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/resources/META-INF/additional-spring-configuration-metadata.json) { "groups": [ { "name": "spring.ai.mistralai.chat.tool-choice", "type": "org.springframework.ai.mistralai.api.MistralAiApi$ChatCompletionRequest$ToolChoice", "sourceType": "org.springframework.ai.model.mistralai.autoconfigure.MistralAiChatProperties" } ], "properties": [], "hints": [] } --- ### Auto Configurations/Models/Spring Ai Autoconfigure Model Openai/Src/Main/Resources/META INF/Additional Spring Configuration Metadata.Json (auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/resources/META-INF/additional-spring-configuration-metadata.json) { "groups": [ { "name": "spring.ai.openai.chat.output-audio", "type": "org.springframework.ai.openai.OpenAiChatOptions$AudioParameters", "sourceType": "org.springframework.ai.openai.OpenAiChatOptions" } ], "properties": [ { "name": "spring.ai.openai.chat.output-audio.voice", "type": "org.springframework.ai.openai.OpenAiChatOptions$AudioParameters$Voice", "sourceType": "org.springframework.ai.openai.OpenAiChatOptions$AudioParameters" }, { "name": "spring.ai.openai.chat.output-audio.format", "type": "org.springframework.ai.openai.OpenAiChatOptions$AudioParameters$AudioResponseFormat", "sourceType": "org.springframework.ai.openai.OpenAiChatOptions$AudioParameters" } ], "hints": [] } --- ### Document Readers/Spring Ai Jsoup Document Reader/ README (document-readers/spring-ai-jsoup-document-reader/ README.md) # Spring AI JSoup Document Reader This module provides an HTML document reader for the Spring AI project. It leverages the [JSoup](https://jsoup.org/) library to parse HTML content and extract text and metadata, making it suitable for use in AI applications. ## Features * **Flexible Text Extraction:** * Extract all text from the `` of an HTML document. * Extract text from specific elements using CSS selectors. * Group text by element, creating a separate document for each selected element. * Combine text from multiple selected elements using a configurable separator. * **Metadata Extraction:** * Extract the document title. * Extract content from `` tags (e.g., description, keywords). You can specify which meta tags to extract. * Extract a list of all absolute URLs of links (``) within the document. * **Configurable:** * Specify the character encoding (defaults to UTF-8). * Customize the CSS selector for element selection. * Configure the separator string for joining text from multiple elements. * Choose whether to extract all text or use element-based extraction. * Enable/disable link URL extraction. * Add additional metadata using configuration. * **Resource-Based:** Works with Spring's `Resource` abstraction, allowing you to read HTML from files, classpath resources, URLs, and even in-memory byte arrays. --- #### How to Build: ```bash ./mvnw -pl document-readers/jsoup-reader clean install ``` --- ### Document Readers/Spring Ai Markdown Document Reader/Src/Test/Resources/Blockquote (document-readers/spring-ai-markdown-document-reader/src/test/resources/blockquote.md) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur diam eros, laoreet sit amet cursus vitae, varius sed nisi. Cras sit amet quam quis velit commodo porta consectetur id nisi. Phasellus tincidunt pulvinar augue. > Proin vel laoreet leo, sed luctus augue. Sed et ligula commodo, commodo lacus at, consequat turpis. Maecenas eget > sapien odio. Maecenas urna lectus, pellentesque in accumsan aliquam, congue eu libero. Ut rhoncus nec justo a > porttitor. Pellentesque auctor pharetra eros, viverra sodales lorem aliquet id. Curabitur semper nisi vel sem interdum > suscipit. --- ### Document Readers/Spring Ai Markdown Document Reader/Src/Test/Resources/Code (document-readers/spring-ai-markdown-document-reader/src/test/resources/code.md) This is a Java sample application: ```java package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } ``` Markdown also provides the possibility to `use inline code formatting throughout` the entire sentence. --- Another possibility is to set block code without specific highlighting: ``` ./mvnw spring-javaformat:apply ``` --- ### Document Readers/Spring Ai Markdown Document Reader/Src/Test/Resources/Horizontal Rules (document-readers/spring-ai-markdown-document-reader/src/test/resources/horizontal-rules.md) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec tincidunt velit non bibendum gravida. --- Cras accumsan tincidunt ornare. Donec hendrerit consequat tellus blandit accumsan. Aenean aliquam metus at arcu elementum dignissim. *** Nullam nisi dui, egestas nec sem nec, interdum lobortis enim. Pellentesque odio orci, faucibus eu luctus nec, venenatis et magna. * * * Vestibulum nec eros non felis fermentum posuere eget ac risus. Curabitur et fringilla massa. Cras facilisis nec nisl sit amet sagittis. ***** Aenean eu leo eu nibh tristique posuere quis quis massa. Nullam lacinia luctus sem ut vehicula. --------------------------------------- Aenean quis vulputate mi. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nam tincidunt nunc a tortor tincidunt, nec lobortis diam rhoncus. - - - Nulla facilisi. Phasellus eget tellus sed nibh ornare interdum eu eu mi. --- ### Document Readers/Spring Ai Markdown Document Reader/Src/Test/Resources/Lists (document-readers/spring-ai-markdown-document-reader/src/test/resources/lists.md) ## Ordered list 1. Lorem ipsum dolor sit *amet*, consectetur adipiscing elit. **Curabitur** diam eros, laoreet sit _amet_ cursus vitae, varius sed nisi. 2. Cras sit amet quam quis velit commodo porta consectetur id nisi. Phasellus tincidunt pulvinar augue. 3. Proin vel laoreet leo, sed luctus augue. Sed et ligula commodo, commodo lacus at, consequat turpis. Maecenas eget sapien odio. 1. Pellentesque auctor pharetra eros, viverra sodales lorem aliquet id. Curabitur semper nisi vel sem interdum suscipit. 2. Maecenas urna lectus, pellentesque in accumsan aliquam, congue eu libero. Ut rhoncus nec justo a porttitor. ## Unordered list * Aenean eu leo eu nibh tristique posuere quis quis massa. * Aenean imperdiet libero dui, nec malesuada dui maximus vel. Vestibulum sed dui condimentum, cursus libero in, dapibus tortor. * Etiam facilisis enim in egestas dictum. --- ### Document Readers/Spring Ai Markdown Document Reader/Src/Test/Resources/Only Headers (document-readers/spring-ai-markdown-document-reader/src/test/resources/only-headers.md) # Header 1a Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur diam eros, laoreet sit amet cursus vitae, varius sed nisi. Cras sit amet quam quis velit commodo porta consectetur id nisi. Phasellus tincidunt pulvinar augue. # Header 1b Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Etiam lobortis risus libero, sed sollicitudin risus cursus in. Morbi enim metus, ornare vel lacinia eget, venenatis vel nibh. ## Header 2b Proin vel laoreet leo, sed luctus augue. Sed et ligula commodo, commodo lacus at, consequat turpis. Maecenas eget sapien odio. Maecenas urna lectus, pellentesque in accumsan aliquam, congue eu libero. # Header 1c ## Header 2c Ut rhoncus nec justo a porttitor. Pellentesque auctor pharetra eros, viverra sodales lorem aliquet id. Curabitur semper nisi vel sem interdum suscipit. --- ### Document Readers/Spring Ai Markdown Document Reader/Src/Test/Resources/Simple (document-readers/spring-ai-markdown-document-reader/src/test/resources/simple.md) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec tincidunt velit non bibendum gravida. Cras accumsan tincidunt ornare. Donec hendrerit consequat tellus blandit accumsan. Aenean aliquam metus at arcu elementum dignissim. Nullam nisi dui, egestas nec sem nec, interdum lobortis enim. Pellentesque odio orci, faucibus eu luctus nec, venenatis et magna. Vestibulum nec eros non felis fermentum posuere eget ac risus. Aenean eu leo eu nibh tristique posuere quis quis massa.\ Nullam lacinia luctus sem ut vehicula. --- ### Document Readers/Spring Ai Markdown Document Reader/Src/Test/Resources/With Formatting (document-readers/spring-ai-markdown-document-reader/src/test/resources/with-formatting.md) # This is a fancy header name Lorem ipsum dolor sit amet, **consectetur adipiscing elit**. Donec tincidunt velit non bibendum gravida. Cras accumsan tincidunt ornare. Donec hendrerit consequat tellus *blandit* accumsan. Aenean aliquam metus at ***arcu elementum*** dignissim. ### Header 3 Aenean eu leo eu nibh tristique _posuere quis quis massa_. --- ### Document Readers/Spring Ai Markdown Document Reader/Src/Test/Resources/Dir Test 1/Blockquote (document-readers/spring-ai-markdown-document-reader/src/test/resources/dir-test-1/blockquote.md) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur diam eros, laoreet sit amet cursus vitae, varius sed nisi. Cras sit amet quam quis velit commodo porta consectetur id nisi. Phasellus tincidunt pulvinar augue. > Proin vel laoreet leo, sed luctus augue. Sed et ligula commodo, commodo lacus at, consequat turpis. Maecenas eget > sapien odio. Maecenas urna lectus, pellentesque in accumsan aliquam, congue eu libero. Ut rhoncus nec justo a > porttitor. Pellentesque auctor pharetra eros, viverra sodales lorem aliquet id. Curabitur semper nisi vel sem interdum > suscipit. --- ### Document Readers/Spring Ai Markdown Document Reader/Src/Test/Resources/Dir Test 1/Blockquote (document-readers/spring-ai-markdown-document-reader/src/test/resources/dir-test-1/blockquote.txt) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur diam eros, laoreet sit amet cursus vitae, varius sed nisi. Cras sit amet quam quis velit commodo porta consectetur id nisi. Phasellus tincidunt pulvinar augue. > Proin vel laoreet leo, sed luctus augue. Sed et ligula commodo, commodo lacus at, consequat turpis. Maecenas eget > sapien odio. Maecenas urna lectus, pellentesque in accumsan aliquam, congue eu libero. Ut rhoncus nec justo a > porttitor. Pellentesque auctor pharetra eros, viverra sodales lorem aliquet id. Curabitur semper nisi vel sem interdum > suscipit. --- ### Document Readers/Spring Ai Markdown Document Reader/Src/Test/Resources/Dir Test 2/Only Headers (document-readers/spring-ai-markdown-document-reader/src/test/resources/dir-test-2/only-headers.md) # Header 1a Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur diam eros, laoreet sit amet cursus vitae, varius sed nisi. Cras sit amet quam quis velit commodo porta consectetur id nisi. Phasellus tincidunt pulvinar augue. # Header 1b Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Etiam lobortis risus libero, sed sollicitudin risus cursus in. Morbi enim metus, ornare vel lacinia eget, venenatis vel nibh. ## Header 2b Proin vel laoreet leo, sed luctus augue. Sed et ligula commodo, commodo lacus at, consequat turpis. Maecenas eget sapien odio. Maecenas urna lectus, pellentesque in accumsan aliquam, congue eu libero. # Header 1c ## Header 2c Ut rhoncus nec justo a porttitor. Pellentesque auctor pharetra eros, viverra sodales lorem aliquet id. Curabitur semper nisi vel sem interdum suscipit. --- ### Document Readers/Spring Ai Markdown Document Reader/Src/Test/Resources/Dir Test 2/With Formatting (document-readers/spring-ai-markdown-document-reader/src/test/resources/dir-test-2/with-formatting.md) # This is a fancy header name Lorem ipsum dolor sit amet, **consectetur adipiscing elit**. Donec tincidunt velit non bibendum gravida. Cras accumsan tincidunt ornare. Donec hendrerit consequat tellus *blandit* accumsan. Aenean aliquam metus at ***arcu elementum*** dignissim. ### Header 3 Aenean eu leo eu nibh tristique _posuere quis quis massa_. --- ### Memory Repositories/Spring Ai Model Chat Memory Repository Jdbc/README (memory-repositories/spring-ai-model-chat-memory-repository-jdbc/README.md) [Chat Memory Documentation](https://docs.spring.io/spring-ai/reference/api/chatmemory.html) --- ### Memory Repositories/Spring Ai Model Chat Memory Repository Mongodb/README (memory-repositories/spring-ai-model-chat-memory-repository-mongodb/README.md) [Chat Memory Documentation](https://docs.spring.io/spring-ai/reference/api/chat-memory.html#_chat_memory) --- ### Memory Repositories/Spring Ai Model Chat Memory Repository Redis/Src/Test/Resources/Application Metadata Schema.Yml (memory-repositories/spring-ai-model-chat-memory-repository-redis/src/test/resources/application-metadata-schema.yml) spring: ai: chat: memory: redis: host: localhost port: 6379 index-name: chat-memory-with-schema # Define metadata fields with their types for proper indexing # This is compatible with RedisVL schema format metadata-fields: - name: priority type: tag # For exact match searches (high, medium, low) - name: category type: tag # For exact match searches - name: score type: numeric # For numeric range queries - name: confidence type: numeric # For numeric comparisons - name: model type: tag # For exact match on model names - name: description type: text # For full-text search --- ### Models/Spring Ai Anthropic/README (models/spring-ai-anthropic/README.md) # Anthropic Java SDK Integration This module integrates the official Anthropic Java SDK with Spring AI, providing access to Claude models through Anthropic's API. [Anthropic Java SDK GitHub repository](https://github.com/anthropics/anthropic-sdk-java) ## Authentication Configure your Anthropic API key either programmatically or via environment variable: ```java AnthropicChatOptions options = AnthropicChatOptions.builder() .apiKey("") .build(); ``` Or using the environment variable (automatically detected): ```bash export ANTHROPIC_API_KEY= ``` ## Features This module supports: - **Chat Completions** - Synchronous and streaming responses - **Tool Calling** - Function calling with automatic tool execution - **Streaming Tool Calling** - Tool calls in streaming mode with partial JSON accumulation - **Multi-Modal** - Images and PDF documents - **Extended Thinking** - Claude's thinking/reasoning feature with full streaming support - **Citations** - Document-grounded responses with source attribution - **Prompt Caching** - Reduce costs for repeated context with configurable strategies - **Structured Output** - JSON schema-constrained responses with effort control - **Per-Request HTTP Headers** - Custom headers per API call for tracking, beta features, and routing - **Observability** - Micrometer-based metrics and tracing ### Planned Features - **Amazon Bedrock** - Access Claude through AWS Bedrock - **Google Vertex AI** - Access Claude through Google Cloud ## Basic Usage ```java // Create chat model with default options AnthropicChatModel chatModel = new AnthropicChatModel( AnthropicChatOptions.builder() .model("claude-sonnet-4-20250514") .maxTokens(1024) .build() ); // Synchronous call ChatResponse response = chatModel.call(new Prompt("Hello, Claude!")); // Streaming call Flux stream = chatModel.stream(new Prompt("Tell me a story")); ``` ## Tool Calling ```java var options = AnthropicChatOptions.builder() .model("claude-sonnet-4-20250514") .toolCallbacks(FunctionToolCallback.builder("getWeather", new WeatherService()) .description("Get the current weather for a location") .inputType(WeatherRequest.class) .build()) .build(); ChatResponse response = chatModel.call(new Prompt("What's the weather in Paris?", options)); ``` ## Extended Thinking Enable Claude's reasoning feature to see step-by-step thinking before the final answer: ```java var options = AnthropicChatOptions.builder() .model("claude-sonnet-4-20250514") .temperature(1.0) // required when thinking is enabled .maxTokens(16000) .thinkingEnabled(10000L) // budget must be >= 1024 and < maxTokens .build(); ChatResponse response = chatModel.call(new Prompt("Solve this step by step...", options)); ``` Three thinking modes are available via convenience builders: - `thinkingEnabled(budgetTokens)` - Enable with a specific token budget - `thinkingAdaptive()` - Let Claude decide whether to think - `thinkingDisabled()` - Explicitly disable thinking Thinking is fully supported in both synchronous and streaming modes, including signature capture for thinking block verification. ## Citations Anthropic's Citations API allows Claude to reference specific parts of provided documents when generating responses. Three document types are supported: plain text, PDF, and custom content blocks. ```java // Create a citation document AnthropicCitationDocument document = AnthropicCitationDocument.builder() .plainText("The Eiffel Tower was completed in 1889 in Paris, France. " + "It stands 330 meters tall and was designed by Gustave Eiffel.") .title("Eiffel Tower Facts") .citationsEnabled(true) .build(); // Call the model with the document ChatResponse response = chatModel.call( new Prompt( "When was the Eiffel Tower built?", AnthropicChatOptions.builder() .model("claude-sonnet-4-20250514") .maxTokens(1024) .citationDocuments(document) .build() ) ); // Access citations from response metadata List citations = (List) response.getMetadata().get("citations"); for (Citation citation : citations) { System.out.println("Document: " + citation.getDocumentTitle()); System.out.println("Cited text: " + citation.getCitedText()); } ``` PDF and custom content block documents are also supported via `pdfFile()`, `pdf()`, and `customContent()` builders. ## Prompt Caching Prompt caching reduces costs and latency by caching repeated context (system prompts, tool definitions, conversation history) across API calls. Five caching strategies are available: | Strategy | Description | |----------|-------------| | `NONE` | No caching (default) | | `SYSTEM_ONLY` | Cache system message content | | `TOOLS_ONLY` | Cache tool definitions | | `SYSTEM_AND_TOOLS` | Cache both system messages and tool definitions | | `CONVERSATION_HISTORY` | Cache system messages, tools, and conversation messages | ```java // Cache system messages to reduce costs for repeated prompts var options = AnthropicChatOptions.builder() .model("claude-sonnet-4-20250514") .maxTokens(1024) .cacheOptions(AnthropicCacheOptions.builder() .strategy(AnthropicCacheStrategy.SYSTEM_AND_TOOLS) .build()) .build(); ChatResponse response = chatModel.call( new Prompt(List.of( new SystemMessage("You are an expert assistant with deep domain knowledge..."), new UserMessage("What is the capital of France?")), options)); // Access cache token usage via native SDK usage com.anthropic.models.messages.Usage sdkUsage = (com.anthropic.models.messages.Usage) response.getMetadata().getUsage().getNativeUsage(); long cacheCreation = sdkUsage.cacheCreationInputTokens().orElse(0L); long cacheRead = sdkUsage.cacheReadInputTokens().orElse(0L); ``` You can also configure TTL (5 minutes or 1 hour), minimum content length thresholds, and multi-block system caching for static vs. dynamic system message segments: ```java var options = AnthropicCacheOptions.builder() .strategy(AnthropicCacheStrategy.SYSTEM_ONLY) .messageTypeTtl(MessageType.SYSTEM, AnthropicCacheTtl.ONE_HOUR) .messageTypeMinContentLength(MessageType.SYSTEM, 100) .multiBlockSystemCaching(true) .build(); ``` ## Structured Output Structured output constrains Claude to produce responses conforming to a JSON schema. The SDK module also supports Anthropic's effort control for tuning response quality vs speed. > **Model Requirement:** Structured output and effort control require `claude-sonnet-4-6` or newer. Older models like `claude-sonnet-4-20250514` do not support these features. ### JSON Schema Output ```java var options = AnthropicChatOptions.builder() .model("claude-sonnet-4-6") .outputSchema(""" { "type": "object", "properties": { "name": {"type": "string"}, "capital": {"type": "string"}, "population": {"type": "integer"} }, "required": ["name", "capital"], "additionalProperties": false } """) .build(); ChatResponse response = chatModel.call(new Prompt("Tell me about France.", options)); // Response text will be valid JSON conforming to the schema ``` ### Effort Control Control how much compute Claude spends on its response. Lower effort means faster, cheaper responses; higher effort means more thorough reasoning. ```java var options = AnthropicChatOptions.builder() .model("claude-sonnet-4-6") .effort(OutputConfig.Effort.LOW) // LOW, MEDIUM, HIGH, or MAX .build(); ``` ### Combined Schema + Effort ```java var options = AnthropicChatOptions.builder() .model("claude-sonnet-4-6") .outputSchema("{\"type\":\"object\",\"properties\":{\"answer\":{\"type\":\"integer\"}},\"required\":[\"answer\"],\"additionalProperties\":false}") .effort(OutputConfig.Effort.HIGH) .build(); ``` ### Direct OutputConfig For full control, use the SDK's `OutputConfig` directly: ```java import com.anthropic.models.messages.OutputConfig; import com.anthropic.models.messages.JsonOutputFormat; import com.anthropic.core.JsonValue; var outputConfig = OutputConfig.builder() .effort(OutputConfig.Effort.HIGH) .format(JsonOutputFormat.builder() .schema(JsonOutputFormat.Schema.builder() .putAdditionalProperty("type", JsonValue.from("object")) .putAdditionalProperty("properties", JsonValue.from(Map.of( "name", Map.of("type", "string")))) .putAdditionalProperty("additionalProperties", JsonValue.from(false)) .build()) .build()) .build(); var options = AnthropicChatOptions.builder() .model("claude-sonnet-4-6") .outputConfig(outputConfig) .build(); ``` ## Per-Request HTTP Headers Add custom HTTP headers to individual API calls. Unlike `customHeaders` (which apply to all requests at the client level), `httpHeaders` are set per request. ```java var options = AnthropicChatOptions.builder() .httpHeaders(Map.of( "X-Request-Id", "req-12345", "X-Custom-Tracking", "my-value")) .build(); ChatResponse response = chatModel.call(new Prompt("Hello", options)); ``` ## Logging Enable SDK logging by setting the environment variable: ```bash export ANTHROPIC_LOG=debug ``` ## Documentation For comprehensive documentation, see: - [Spring AI Anthropic Reference Documentation](https://docs.spring.io/spring-ai/reference/api/chat/anthropic-chat.html) - [Anthropic API Documentation](https://docs.anthropic.com/) - [Anthropic Java SDK Documentation](https://github.com/anthropics/anthropic-sdk-java) --- ### Models/Spring Ai Anthropic/Src/Test/Resources/Prompts/Conversation History Cache Prompt (models/spring-ai-anthropic/src/test/resources/prompts/conversation-history-cache-prompt.txt) You are an experienced career counselor and professional development expert with over 15 years of experience helping technology professionals advance their careers in software engineering, data science, and emerging tech fields. Your expertise spans career transitions, skill development, industry trends, and strategic career planning. When providing career guidance, always consider these essential dimensions: 1. Current market trends and emerging technologies affecting career trajectories 2. Skills gap analysis and strategic upskilling recommendations for competitive advantage 3. Industry-specific compensation benchmarks and negotiation strategies 4. Professional networking approaches and personal brand development 5. Leadership development pathways and technical career progression options 6. Work-life balance considerations and remote work best practices 7. Interview preparation strategies and portfolio development guidance 8. Career transition planning including timing, risk mitigation, and bridge strategies 9. Performance evaluation optimization and promotion pathway planning 10. Entrepreneurial opportunities and freelancing vs full-time employment trade-offs ## Career Development Framework for Conversation History Caching ### Technical Skills Assessment and Development Provide comprehensive technical skill evaluation: - Current technology stack assessment with market relevance analysis - Emerging technology identification and learning prioritization strategies - Certification and formal education recommendations with ROI calculations - Hands-on project suggestions to demonstrate competency and build portfolios - Open source contribution strategies for visibility and community engagement - Technical writing and speaking opportunities for thought leadership development - Mentorship and reverse mentoring opportunities for skill exchange ### Career Progression Strategy Planning Develop strategic career advancement plans: - Individual contributor vs management track decision frameworks - Technical leadership roles and architectural responsibility progression - Cross-functional collaboration skills for broader organizational impact - Product management and business strategy understanding for technical leaders - Agile and project management methodologies for delivery excellence - Stakeholder communication and executive presentation skills development - International and remote work opportunities for global career expansion ### Industry and Market Analysis Analyze technology industry trends comprehensively: - Startup vs enterprise career path comparisons with risk-reward analysis - Industry sector analysis including fintech, healthcare, education, and government - Geographic market opportunities and cost of living considerations - Remote work impact on career opportunities and compensation structures - Freelancing and consulting market dynamics with rate optimization - Technology adoption cycles and their impact on career longevity - Economic factors affecting technology hiring and investment patterns ### Professional Development and Networking Guide strategic professional relationship building: - Conference attendance and speaking engagement strategies for visibility - Professional association participation and leadership opportunities - Alumni network activation and industry meetup engagement tactics - Social media presence optimization for professional brand building - Mentorship relationship development both as mentor and mentee - Cross-industry networking for diverse perspective and opportunity access - International professional relationships for global career opportunities ### Performance and Compensation Optimization Optimize career advancement and compensation: - Performance review preparation and goal-setting strategies for maximum impact - Compensation negotiation tactics with market research and timing considerations - Equity and stock option evaluation for startup and growth company positions - Benefits package optimization including health, retirement, and professional development - Professional development budget utilization for strategic skill building - Side project and passive income development for financial diversification - Career pivoting strategies with income protection and transition planning Always provide personalized, actionable advice based on individual circumstances and career goals. Consider market conditions, personal constraints, and long-term career sustainability. Focus on building transferable skills and maintaining adaptability in a rapidly changing technology landscape. This system prompt is specifically designed for testing conversation history caching strategies and contains sufficient tokens to trigger Anthropic's prompt caching mechanism with Claude Sonnet 4 (1024+ token threshold). --- ### Models/Spring Ai Anthropic/Src/Test/Resources/Prompts/Extended Ttl Cache Prompt (models/spring-ai-anthropic/src/test/resources/prompts/extended-ttl-cache-prompt.txt) You are a comprehensive mathematical assistant specializing in arithmetic, algebra, calculus, statistics, and advanced mathematical concepts. Your expertise spans elementary mathematics through graduate-level topics, with particular strength in problem-solving methodologies. When addressing mathematical problems, always consider these fundamental aspects: 1. Problem comprehension and identification of given information and unknowns 2. Selection of appropriate mathematical methods and solution strategies 3. Step-by-step solution development with clear logical progression 4. Verification of results through alternative methods or sanity checks 5. Interpretation of solutions in context with practical applications 6. Common error identification and prevention strategies 7. Conceptual understanding reinforcement through analogies and examples 8. Connections to broader mathematical principles and theorems 9. Computational accuracy and precision considerations 10. Communication of mathematical reasoning in accessible language ## Mathematical Problem-Solving Framework for Extended TTL Caching ### Arithmetic and Number Theory Provide comprehensive arithmetic analysis: - Basic operations with integers, fractions, and decimal number systems - Prime factorization and greatest common divisor calculations - Modular arithmetic applications in cryptography and computer science - Number base conversions between binary, octal, decimal, and hexadecimal systems - Rational and irrational number properties with proof techniques - Complex number operations including polar and rectangular forms - Mathematical induction proofs for number theory propositions ### Algebraic Problem Solving Develop algebraic solution strategies: - Linear equation systems using substitution, elimination, and matrix methods - Quadratic equation solutions with discriminant analysis and graphical interpretation - Polynomial factorization techniques including synthetic division and rational root theorem - Exponential and logarithmic equation solving with change of base formulas - Inequality solving with graphical representation and interval notation - Function composition and inverse function determination - Abstract algebra concepts including groups, rings, and fields ### Calculus and Analysis Analyze calculus problems comprehensively: - Limit evaluation using algebraic manipulation and L'Hôpital's rule - Derivative calculations with chain rule, product rule, and quotient rule applications - Integration techniques including substitution, parts, and partial fractions - Applications of derivatives in optimization and related rate problems - Definite integral applications in area, volume, and physics problems - Series convergence analysis with ratio, root, and integral tests - Multivariable calculus including partial derivatives and multiple integrals ### Statistical Analysis and Probability Examine statistical methods thoroughly: - Descriptive statistics including measures of central tendency and dispersion - Probability distributions with normal, binomial, and Poisson applications - Hypothesis testing with Type I and Type II error analysis - Confidence interval construction and interpretation - Regression analysis with correlation coefficient interpretation - Analysis of variance (ANOVA) for comparing multiple groups - Bayesian inference and conditional probability applications ### Applied Mathematics and Modeling Model real-world problems mathematically: - Linear programming with simplex method and graphical solutions - Differential equation modeling for population growth and decay - Game theory applications in economics and strategic decision making - Graph theory for network analysis and optimization problems - Numerical analysis methods for approximation and error estimation - Operations research techniques for resource allocation and scheduling - Financial mathematics including compound interest and annuity calculations Always provide clear explanations with multiple solution approaches where applicable. Include graphical representations and real-world applications to enhance understanding. Emphasize mathematical reasoning and proof techniques to develop analytical thinking skills. ### Additional Mathematical Problem-Solving Strategies for Extended TTL Testing #### Advanced Topics and Specialized Areas Explore comprehensive mathematical domains: - Abstract Algebra: Group theory, ring theory, field theory applications - Real Analysis: Measure theory, functional analysis, topology concepts - Complex Analysis: Analytic functions, contour integration, residue theory - Discrete Mathematics: Graph theory, combinatorics, number theory applications - Linear Algebra: Matrix decompositions, eigenvalue problems, vector spaces - Differential Geometry: Manifolds, curvature, tensor calculus applications - Optimization Theory: Linear programming, nonlinear optimization, convex analysis - Probability Theory: Stochastic processes, measure-theoretic probability, limit theorems - Mathematical Logic: Set theory, model theory, proof theory foundations #### Computational Mathematics and Numerical Methods Address computational aspects thoroughly: - Numerical Linear Algebra: LU decomposition, QR factorization, singular value decomposition - Numerical Integration: Gaussian quadrature, adaptive quadrature methods, Monte Carlo integration - Ordinary Differential Equations: Runge-Kutta methods, multistep methods, boundary value problems - Partial Differential Equations: Finite difference methods, finite element analysis, spectral methods - Interpolation and Approximation: Spline interpolation, Chebyshev polynomials, least squares approximation - Root Finding: Newton-Raphson method, bisection method, secant method applications - Optimization Algorithms: Gradient descent, Newton's method, simplex algorithm implementations #### Mathematical Modeling and Real-World Applications Connect theory to practical implementations: - Engineering Mathematics: Fourier analysis, Laplace transforms, control theory applications - Mathematical Biology: Population dynamics, epidemic modeling, biochemical reaction networks - Mathematical Physics: Quantum mechanics, relativity theory, statistical mechanics principles - Mathematical Economics: Game theory, optimization in economics, financial mathematics modeling - Actuarial Mathematics: Life insurance, annuities, pension fund calculations, risk assessment - Cryptography: Number theory applications, elliptic curve cryptography, hash functions - Signal Processing: Digital signal processing, wavelets, time-frequency analysis techniques This system prompt is specifically designed for testing extended TTL caching strategies and contains sufficient tokens to trigger Anthropic's prompt caching mechanism with Claude Sonnet 4 (1024+ token threshold). The expanded content ensures we exceed the minimum token requirement significantly to guarantee cache creation rather than relying on borderline token counts that might fail cache threshold requirements. --- ### Models/Spring Ai Anthropic/Src/Test/Resources/Prompts/System And Tools Cache Prompt (models/spring-ai-anthropic/src/test/resources/prompts/system-and-tools-cache-prompt.txt) You are a comprehensive weather analysis assistant specializing in meteorological data interpretation and outdoor activity recommendations. Your expertise encompasses understanding complex weather patterns, atmospheric conditions, and their impact on various outdoor activities. When analyzing weather data, always consider these critical factors: 1. Temperature variations throughout the day and their impact on comfort levels 2. Precipitation probability, intensity, and duration affecting outdoor plans 3. Wind speed and direction influencing perceived temperature and activity safety 4. Humidity levels affecting comfort and heat index calculations 5. UV index and sun exposure recommendations for health and safety 6. Atmospheric pressure changes indicating weather pattern shifts 7. Visibility conditions for driving and outdoor navigation 8. Air quality indices for respiratory health considerations 9. Seasonal patterns and historical weather trends for context 10. Local microclimate effects in urban vs rural environments ## Weather Analysis Framework for System and Tools Caching ### Temperature Analysis Provide detailed temperature assessments: - Current temperature readings with heat index or wind chill calculations - Daily temperature ranges including minimum and maximum predictions - Comfort zone analysis for different age groups and activity levels - Thermal comfort indices considering humidity, wind, and solar radiation - Clothing recommendations based on effective temperature measurements - Risk assessments for heat-related illnesses or cold exposure - Optimal timing recommendations for temperature-sensitive activities ### Precipitation Assessment Analyze precipitation patterns comprehensively: - Current precipitation type, intensity, and accumulation rates - Probability forecasts with confidence intervals and timing predictions - Impact assessments on outdoor activities, transportation, and infrastructure - Flood risk evaluations for low-lying areas and drainage systems - Snow and ice formation potential with safety implications - Seasonal precipitation trends and drought or flood pattern analysis - Agricultural and ecological impacts of current and forecast precipitation ### Wind Conditions Evaluation Assess wind impacts thoroughly: - Current wind speed, direction, and gust measurements - Wind chill calculations and perceived temperature effects - Safety considerations for high-wind activities and structural concerns - Maritime and aviation wind impact assessments - Dust and pollen dispersion patterns affected by wind conditions - Energy generation potential for wind-powered systems - Fire weather conditions and wildfire risk assessments ### Atmospheric Monitoring Monitor comprehensive atmospheric conditions: - Barometric pressure trends indicating weather system movements - Humidity levels with comfort and health impact assessments - Air quality measurements including particulate matter and pollutants - UV radiation levels with skin protection recommendations - Visibility assessments for transportation and outdoor activities - Lightning detection and severe weather warning systems - Climate change indicators and long-term trend analysis ### Activity Recommendations Provide specific outdoor activity guidance: - Walking, hiking, and running condition assessments with safety protocols - Sports and recreational activity suitability ratings - Gardening and agricultural work timing recommendations - Construction and outdoor work safety guidelines - Travel and transportation condition evaluations - Photography and outdoor event planning considerations - Emergency preparedness and severe weather response protocols ### Severe Weather Protocols Apply rigorous severe weather analysis procedures: - Thunderstorm development tracking with lightning frequency and storm cell motion - Tornado watch and warning interpretation with shelter-in-place guidance - Hurricane and tropical storm trajectory analysis with evacuation timing windows - Flash flood potential based on rainfall rates, soil saturation, and terrain - Winter storm classification covering snowfall accumulation, ice loading, and blizzard criteria - Heat wave and cold snap duration forecasting with public health advisory thresholds - Coastal storm surge estimation and tidal interaction effects on low-lying areas ### Data Quality and Confidence Communicate forecast reliability transparently: - Distinguish observed measurements from model-derived predictions - Report confidence intervals and forecast uncertainty for each variable - Note model disagreement between major numerical weather prediction systems - Flag data gaps from sensor outages or sparse observation networks - Explain how forecast skill degrades with lead time for each parameter - Reconcile conflicting indicators rather than averaging them uncritically - Provide ranges rather than single point estimates when uncertainty is high ### Regional and Seasonal Context Ground every assessment in local context: - Adjust thresholds for regional climate norms and acclimatization - Account for elevation, proximity to large bodies of water, and urban heat islands - Incorporate seasonal baselines so anomalies are interpreted correctly - Reference historical analogs for comparable weather setups - Consider prevailing wind regimes and orographic effects on precipitation - Factor in diurnal patterns specific to the location and time of year ### Communication and Response Structure Structure every response for clarity and usefulness: - Lead with the single most decision-relevant takeaway for the user's question - Follow with supporting detail organized from highest to lowest impact - Use concrete numbers with units rather than vague qualitative descriptions - Separate what is known now from what is forecast and how far out - Call out any safety-critical condition explicitly and early in the response - Offer a clear recommended action, not just a description of conditions - Close with the most relevant caveat or condition that would change the advice ### Outdoor Activity Risk Tiers Classify recommendations into consistent risk tiers: - Favorable conditions where the activity can proceed without special precautions - Marginal conditions requiring specific mitigations such as timing or equipment - Hazardous conditions where the activity should be postponed or relocated - Dangerous conditions where outdoor exposure itself is the primary risk - For each tier, name the dominant limiting factor driving the classification - Re-evaluate the tier whenever a key variable crosses a documented threshold Always provide specific, actionable recommendations with safety considerations paramount. Include quantitative data where available and explain the reasoning behind recommendations. Consider vulnerable populations including children, elderly, and individuals with health conditions. This system prompt is specifically designed for testing system and tools caching strategies and contains sufficient tokens to trigger Anthropic's prompt caching mechanism with current Claude Sonnet models (1024+ token threshold). --- ### Models/Spring Ai Anthropic/Src/Test/Resources/Prompts/System Only Cache Prompt (models/spring-ai-anthropic/src/test/resources/prompts/system-only-cache-prompt.txt) You are an expert software architect specializing in distributed systems and cloud-native applications. Your responses should be detailed, technically accurate, and include comprehensive best practices for scalability, reliability, maintainability, and cost-effectiveness in modern software systems. When discussing architecture patterns, always consider these critical aspects: 1. Scalability implications and potential bottlenecks across multiple dimensions including compute, storage, network, and database resources 2. Fault tolerance and error handling strategies including circuit breakers, bulkheads, timeouts, retries, and graceful degradation 3. Data consistency and transaction management including eventual consistency patterns, saga patterns, and distributed transaction challenges 4. Security considerations and access patterns including authentication, authorization, encryption at rest and in transit, and zero-trust principles 5. Monitoring and observability requirements including distributed tracing, structured logging, metrics collection, and alerting strategies 6. Performance optimization opportunities including caching strategies, CDN usage, database indexing, and query optimization 7. Cost optimization strategies including resource rightsizing, reserved capacity planning, and multi-cloud cost management 8. Team structure and Conway's Law implications including microservice boundaries, team autonomy, and communication patterns 9. DevOps and deployment strategies including CI/CD pipelines, infrastructure as code, and automated testing approaches 10. Compliance and governance requirements including data privacy regulations, audit trails, and regulatory compliance frameworks ## Detailed Architecture Guidelines for System-Only Caching ### Microservices Design Patterns When designing microservices, implement these essential patterns: - API Gateway pattern for centralized request routing and cross-cutting concerns - Service mesh for inter-service communication, security, and observability - Event sourcing for maintaining audit trails and enabling event-driven architectures - CQRS (Command Query Responsibility Segregation) for optimal read/write performance - Bulkhead pattern to isolate critical resources and prevent cascade failures - Circuit breaker pattern with exponential backoff for external service resilience - Saga pattern for distributed transaction management across service boundaries ### Data Management Strategies Implement robust data management approaches: - Database per service pattern to ensure data encapsulation and service autonomy - Event-driven data synchronization using message queues and event streams - Polyglot persistence choosing optimal data stores for specific use cases - Read replicas and sharding strategies for horizontal scaling - Data versioning and schema evolution strategies for backward compatibility - Distributed caching with Redis or similar for improved performance - Data governance frameworks ensuring data quality, lineage, and compliance ### Security Best Practices Implement defense-in-depth security measures: - OAuth 2.0 and OpenID Connect for authentication and authorization - JWT tokens with proper expiration and refresh token mechanisms - API rate limiting and throttling to prevent abuse and DDoS attacks - Encryption at rest using AES-256 and encryption in transit with TLS 1.3 - Secret management using HashiCorp Vault or AWS Secrets Manager - Network segmentation with VPCs, subnets, and security groups - Regular security audits, vulnerability scanning, and penetration testing ### Monitoring and Observability Establish comprehensive observability: - Distributed tracing with OpenTelemetry or Jaeger for request flow analysis - Centralized logging with ELK stack or similar for log aggregation and analysis - Application metrics using Prometheus and Grafana for monitoring and alerting - Health checks and readiness probes for service availability monitoring - SLA/SLO definitions with error budgets for reliability measurements - Alert management with PagerDuty or similar for incident response - Performance monitoring with APM tools like New Relic or AppDynamics ### Infrastructure and DevOps Implement modern infrastructure practices: - Infrastructure as Code using Terraform, CloudFormation, or Pulumi - Container orchestration with Kubernetes for scalable deployments - GitOps workflows with ArgoCD or Flux for automated deployments - Blue-green or canary deployment strategies for zero-downtime releases - Automated testing pipelines including unit, integration, and end-to-end tests - Code quality gates with SonarQube and static analysis tools - Disaster recovery planning with backup strategies and failover procedures Always provide concrete examples, architectural diagrams when helpful, code snippets in relevant programming languages, and real-world case studies from companies like Netflix, Amazon, Google, Microsoft, and other technology leaders. Consider both the technical and business implications of architectural decisions, including time-to-market, development velocity, operational overhead, and long-term maintainability costs. This system prompt is specifically designed for testing system-only caching strategies and contains sufficient tokens to trigger Anthropic's prompt caching mechanism with Claude Sonnet 4 (1024+ token threshold). --- ### Models/Spring Ai Bedrock/README (models/spring-ai-bedrock/README.md) [Amazon Bedrock Overview](https://docs.spring.io/spring-ai/reference/api/bedrock-chat.html) - [Anthropic3 Chat Documentation](https://docs.spring.io/spring-ai/reference/api/chat/bedrock/bedrock-anthropic3.html) - [Anthropic2 Chat Documentation](https://docs.spring.io/spring-ai/reference/api/chat/bedrock/bedrock-anthropic.html) - [Cohere Chat Documentation](https://docs.spring.io/spring-ai/reference/api/chat/bedrock/bedrock-cohere.html) - [Cohere Embedding Documentation](https://docs.spring.io/spring-ai/reference/api/embeddings/bedrock-cohere-embedding.html) - [Llama Chat Documentation](https://docs.spring.io/spring-ai/reference/api/chat/bedrock/bedrock-llama.html) - [Titan Chat Documentation](https://docs.spring.io/spring-ai/reference/api/chat/bedrock/bedrock-titan.html) - [Titan Embedding Documentation](https://docs.spring.io/spring-ai/reference/api/embeddings/bedrock-titan-embedding.html) - [Jurassic2 Chat Documentation](https://docs.spring.io/spring-ai/reference/api/chat/bedrock/bedrock-jurassic2.html) --- ### Models/Spring Ai Deepseek/README (models/spring-ai-deepseek/README.md) [DeepSeek Chat Documentation](https://docs.spring.io/spring-ai/reference/api/chat/deepseek-chat.html) --- ### Models/Spring Ai Elevenlabs/README (models/spring-ai-elevenlabs/README.md) # Spring AI - ElevenLabs Text-to-Speech [ElevenLabs Text-to-Speech Documentation](https://docs.spring.io/spring-ai/reference/api/audio/speech/elevenlabs-speech.html) --- ### Models/Spring Ai Elevenlabs/Src/Test/Resources/Voices.Json (models/spring-ai-elevenlabs/src/test/resources/voices.json) { "voices": [ { "voice_id": "9BWtsMINqrJLrRacOk9x", "name": "Aria", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": { "eleven_multilingual_v2": "fine_tuned", "eleven_turbo_v2_5": "fine_tuned", "eleven_flash_v2_5": "fine_tuned", "eleven_v2_flash": "fine_tuned", "eleven_v2_5_flash": "fine_tuned", "eleven_turbo_v2": "fine_tuned", "eleven_flash_v2": "fine_tuned" }, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": { "eleven_flash_v2_5": 1, "eleven_v2_flash": 1, "eleven_flash_v2": 1, "eleven_v2_5_flash": 1 }, "message": { "eleven_flash_v2_5": "Done!", "eleven_v2_flash": "Done!", "eleven_flash_v2": "Done!", "eleven_v2_5_flash": "Done!" }, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "American", "description": "expressive", "age": "middle-aged", "gender": "female", "use_case": "social media" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/9BWtsMINqrJLrRacOk9x/405766b8-1f4e-4d3c-aba1-6f25333823ec.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_v2_flash", "eleven_flash_v2", "eleven_turbo_v2_5", "eleven_multilingual_v2", "eleven_v2_5_flash", "eleven_flash_v2_5", "eleven_turbo_v2" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null }, { "voice_id": "CwhRBWXzGAHq8TQ4Fs17", "name": "Roger", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": { "eleven_multilingual_v2": "fine_tuned", "eleven_turbo_v2_5": "failed", "eleven_flash_v2_5": "fine_tuned", "eleven_v2_flash": "fine_tuned", "eleven_v2_5_flash": "fine_tuned", "eleven_turbo_v2": "fine_tuned", "eleven_flash_v2": "fine_tuned" }, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": { "eleven_flash_v2_5": 1, "eleven_v2_flash": 1, "eleven_flash_v2": 1, "eleven_v2_5_flash": 1 }, "message": { "eleven_flash_v2_5": "Done!", "eleven_v2_flash": "Done!", "eleven_flash_v2": "Done!", "eleven_v2_5_flash": "Done!" }, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "American", "description": "confident", "age": "middle-aged", "gender": "male", "use_case": "social media" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/CwhRBWXzGAHq8TQ4Fs17/58ee3ff5-f6f2-4628-93b8-e38eb31806b0.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_v2_flash", "eleven_flash_v2", "eleven_turbo_v2_5", "eleven_multilingual_v2", "eleven_v2_5_flash", "eleven_flash_v2_5", "eleven_turbo_v2" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null }, { "voice_id": "EXAVITQu4vr4xnSDxMaL", "name": "Sarah", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": {}, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": {}, "message": {}, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "american", "description": "soft", "age": "young", "gender": "female", "use_case": "news" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/EXAVITQu4vr4xnSDxMaL/01a3e33c-6e99-4ee7-8543-ff2216a32186.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_turbo_v2", "eleven_multilingual_v2", "eleven_turbo_v2_5" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null }, { "voice_id": "FGY2WhTYpPnrIDTdsKH5", "name": "Laura", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": { "eleven_multilingual_v2": "fine_tuned", "eleven_turbo_v2_5": "fine_tuned", "eleven_flash_v2_5": "fine_tuned", "eleven_v2_flash": "fine_tuned", "eleven_v2_5_flash": "fine_tuned", "eleven_turbo_v2": "fine_tuned", "eleven_flash_v2": "fine_tuned" }, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": { "eleven_flash_v2_5": 1, "eleven_v2_flash": 1, "eleven_flash_v2": 1, "eleven_v2_5_flash": 1 }, "message": { "eleven_flash_v2_5": "Done!", "eleven_v2_flash": "Done!", "eleven_flash_v2": "Done!", "eleven_v2_5_flash": "Done!" }, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "American", "description": "upbeat", "age": "young", "gender": "female", "use_case": "social media" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/FGY2WhTYpPnrIDTdsKH5/67341759-ad08-41a5-be6e-de12fe448618.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_v2_flash", "eleven_flash_v2", "eleven_turbo_v2_5", "eleven_multilingual_v2", "eleven_v2_5_flash", "eleven_flash_v2_5", "eleven_turbo_v2" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null }, { "voice_id": "IKne3meq5aSn9XLyUdCD", "name": "Charlie", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": { "eleven_flash_v2_5": "fine_tuned", "eleven_turbo_v2": "fine_tuned", "eleven_flash_v2": "fine_tuned", "eleven_v2_flash": "fine_tuned", "eleven_v2_5_flash": "fine_tuned" }, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": { "eleven_flash_v2_5": 1, "eleven_v2_flash": 1, "eleven_flash_v2": 1, "eleven_v2_5_flash": 1 }, "message": { "eleven_flash_v2_5": "Done!", "eleven_turbo_v2": "", "eleven_flash_v2": "Done!", "eleven_v2_flash": "Done!", "eleven_v2_5_flash": "Done!" }, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "Australian", "description": "natural", "age": "middle aged", "gender": "male", "use_case": "conversational" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/IKne3meq5aSn9XLyUdCD/102de6f2-22ed-43e0-a1f1-111fa75c5481.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_v2_flash", "eleven_flash_v2", "eleven_turbo_v2_5", "eleven_multilingual_v2", "eleven_multilingual_v1", "eleven_v2_5_flash", "eleven_flash_v2_5", "eleven_turbo_v2" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null }, { "voice_id": "JBFqnCBsd6RMkjVDRZzb", "name": "George", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": { "eleven_turbo_v2": "fine_tuned", "eleven_v2_flash": "fine_tuned", "eleven_v2_5_flash": "fine_tuned" }, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": { "eleven_v2_flash": 1, "eleven_v2_5_flash": 1 }, "message": { "eleven_turbo_v2": "", "eleven_v2_flash": "Done!", "eleven_v2_5_flash": "Done!" }, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "British", "description": "warm", "age": "middle aged", "gender": "male", "use_case": "narration" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/JBFqnCBsd6RMkjVDRZzb/e6206d1a-0721-4787-aafb-06a6e705cac5.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_v2_flash", "eleven_flash_v2", "eleven_turbo_v2_5", "eleven_multilingual_v2", "eleven_v2_5_flash", "eleven_flash_v2_5", "eleven_turbo_v2" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null }, { "voice_id": "N2lVS1w4EtoT3dr4eOWO", "name": "Callum", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": { "eleven_flash_v2_5": "fine_tuned", "eleven_turbo_v2": "fine_tuned", "eleven_flash_v2": "fine_tuned", "eleven_v2_flash": "fine_tuned", "eleven_v2_5_flash": "fine_tuned" }, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": { "eleven_flash_v2_5": 1, "eleven_v2_flash": 1, "eleven_flash_v2": 1, "eleven_v2_5_flash": 1 }, "message": { "eleven_flash_v2_5": "Done!", "eleven_turbo_v2": "", "eleven_flash_v2": "Done!", "eleven_v2_flash": "Done!", "eleven_v2_5_flash": "Done!" }, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "Transatlantic", "description": "intense", "age": "middle-aged", "gender": "male", "use_case": "characters" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/N2lVS1w4EtoT3dr4eOWO/ac833bd8-ffda-4938-9ebc-b0f99ca25481.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_v2_flash", "eleven_flash_v2", "eleven_turbo_v2_5", "eleven_multilingual_v2", "eleven_multilingual_v1", "eleven_v2_5_flash", "eleven_flash_v2_5", "eleven_turbo_v2" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null }, { "voice_id": "SAz9YHcvj6GT2YYXdXww", "name": "River", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": { "eleven_multilingual_v2": "fine_tuned", "eleven_turbo_v2_5": "fine_tuned", "eleven_flash_v2_5": "fine_tuned", "eleven_v2_flash": "fine_tuned", "eleven_v2_5_flash": "fine_tuned", "eleven_multilingual_sts_v2": "fine_tuned", "eleven_flash_v2": "fine_tuned", "eleven_turbo_v2": "fine_tuned" }, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": { "eleven_flash_v2_5": 1, "eleven_v2_flash": 1, "eleven_flash_v2": 1, "eleven_v2_5_flash": 1 }, "message": { "eleven_flash_v2_5": "Done!", "eleven_v2_flash": "Done!", "eleven_flash_v2": "Done!", "eleven_v2_5_flash": "Done!" }, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "American", "description": "confident", "age": "middle-aged", "gender": "non-binary", "use_case": "social media" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SAz9YHcvj6GT2YYXdXww/e6c95f0b-2227-491a-b3d7-2249240decb7.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_v2_flash", "eleven_flash_v2", "eleven_turbo_v2_5", "eleven_multilingual_sts_v2", "eleven_multilingual_v2", "eleven_v2_5_flash", "eleven_flash_v2_5", "eleven_turbo_v2" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null }, { "voice_id": "TX3LPaxmHKxFdv7VOQHJ", "name": "Liam", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": { "eleven_turbo_v2": "fine_tuned", "eleven_v2_flash": "fine_tuned", "eleven_v2_5_flash": "fine_tuned" }, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": { "eleven_v2_flash": 1, "eleven_v2_5_flash": 1 }, "message": { "eleven_turbo_v2": "", "eleven_v2_flash": "Done!", "eleven_v2_5_flash": "Done!" }, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "American", "description": "articulate", "age": "young", "gender": "male", "use_case": "narration" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/TX3LPaxmHKxFdv7VOQHJ/63148076-6363-42db-aea8-31424308b92c.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_v2_flash", "eleven_flash_v2", "eleven_turbo_v2_5", "eleven_multilingual_v2", "eleven_multilingual_v1", "eleven_v2_5_flash", "eleven_flash_v2_5", "eleven_turbo_v2" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null }, { "voice_id": "XB0fDUnXU5powFXDhCwa", "name": "Charlotte", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": { "eleven_flash_v2_5": "fine_tuned", "eleven_turbo_v2": "fine_tuned", "eleven_flash_v2": "fine_tuned", "eleven_v2_flash": "fine_tuned", "eleven_v2_5_flash": "fine_tuned" }, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": { "eleven_flash_v2_5": 1, "eleven_v2_flash": 1, "eleven_flash_v2": 1, "eleven_v2_5_flash": 1 }, "message": { "eleven_multilingual_v2": "", "eleven_turbo_v2_5": "", "eleven_flash_v2_5": "Done!", "eleven_v2_flash": "Done!", "eleven_v2_5_flash": "Done!", "eleven_turbo_v2": "", "eleven_flash_v2": "Done!" }, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "Swedish", "description": "seductive", "age": "young", "gender": "female", "use_case": "characters" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/XB0fDUnXU5powFXDhCwa/942356dc-f10d-4d89-bda5-4f8505ee038b.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_v2_flash", "eleven_flash_v2", "eleven_turbo_v2_5", "eleven_multilingual_v2", "eleven_multilingual_v1", "eleven_v2_5_flash", "eleven_flash_v2_5", "eleven_turbo_v2" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null }, { "voice_id": "Xb7hH8MSUJpSbSDYk0k2", "name": "Alice", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": { "eleven_flash_v2_5": "fine_tuned", "eleven_turbo_v2": "fine_tuned", "eleven_flash_v2": "fine_tuned", "eleven_v2_flash": "fine_tuned", "eleven_v2_5_flash": "fine_tuned" }, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": { "eleven_flash_v2_5": 1, "eleven_v2_flash": 1, "eleven_flash_v2": 1, "eleven_v2_5_flash": 1 }, "message": { "eleven_flash_v2_5": "Done!", "eleven_turbo_v2": "", "eleven_flash_v2": "Done!", "eleven_v2_flash": "Done!", "eleven_v2_5_flash": "Done!" }, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "British", "description": "confident", "age": "middle-aged", "gender": "female", "use_case": "news" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/Xb7hH8MSUJpSbSDYk0k2/d10f7534-11f6-41fe-a012-2de1e482d336.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_v2_flash", "eleven_flash_v2", "eleven_turbo_v2_5", "eleven_multilingual_v2", "eleven_v2_5_flash", "eleven_flash_v2_5", "eleven_turbo_v2" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null }, { "voice_id": "XrExE9yKIg1WjnnlVkGX", "name": "Matilda", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": { "eleven_turbo_v2": "fine_tuned", "eleven_v2_flash": "fine_tuned", "eleven_v2_5_flash": "fine_tuned" }, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": { "eleven_v2_flash": 1, "eleven_v2_5_flash": 1 }, "message": { "eleven_turbo_v2": "", "eleven_v2_flash": "Done!", "eleven_v2_5_flash": "Done!" }, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "American", "description": "friendly", "age": "middle-aged", "gender": "female", "use_case": "narration" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/XrExE9yKIg1WjnnlVkGX/b930e18d-6b4d-466e-bab2-0ae97c6d8535.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_v2_flash", "eleven_flash_v2", "eleven_turbo_v2_5", "eleven_multilingual_v2", "eleven_multilingual_v1", "eleven_v2_5_flash", "eleven_flash_v2_5", "eleven_turbo_v2" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null }, { "voice_id": "bIHbv24MWmeRgasZH58o", "name": "Will", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": { "eleven_multilingual_v2": "fine_tuned", "eleven_turbo_v2_5": "fine_tuned", "eleven_flash_v2_5": "fine_tuned", "eleven_v2_flash": "fine_tuned", "eleven_v2_5_flash": "fine_tuned", "eleven_turbo_v2": "fine_tuned", "eleven_flash_v2": "fine_tuned" }, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": { "eleven_flash_v2_5": 1, "eleven_v2_flash": 1, "eleven_flash_v2": 1, "eleven_v2_5_flash": 1 }, "message": { "eleven_flash_v2_5": "Done!", "eleven_v2_flash": "Done!", "eleven_flash_v2": "Done!", "eleven_v2_5_flash": "Done!" }, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "American", "description": "friendly", "age": "young", "gender": "male", "use_case": "social media" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/8caf8f3d-ad29-4980-af41-53f20c72d7a4.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_v2_flash", "eleven_flash_v2", "eleven_turbo_v2_5", "eleven_multilingual_v2", "eleven_v2_5_flash", "eleven_flash_v2_5", "eleven_turbo_v2" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null }, { "voice_id": "cgSgspJ2msm6clMCkdW9", "name": "Jessica", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": { "eleven_multilingual_v2": "fine_tuned", "eleven_turbo_v2_5": "fine_tuned", "eleven_flash_v2_5": "fine_tuned", "eleven_v2_flash": "fine_tuned", "eleven_v2_5_flash": "fine_tuned", "eleven_turbo_v2": "fine_tuned", "eleven_flash_v2": "fine_tuned" }, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": { "eleven_flash_v2_5": 1, "eleven_v2_flash": 1, "eleven_flash_v2": 1, "eleven_v2_5_flash": 1 }, "message": { "eleven_flash_v2_5": "Done!", "eleven_v2_flash": "Done!", "eleven_flash_v2": "Done!", "eleven_v2_5_flash": "Done!" }, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "American", "description": "expressive", "age": "young", "gender": "female", "use_case": "conversational" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cgSgspJ2msm6clMCkdW9/56a97bf8-b69b-448f-846c-c3a11683d45a.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_v2_flash", "eleven_flash_v2", "eleven_turbo_v2_5", "eleven_multilingual_v2", "eleven_v2_5_flash", "eleven_flash_v2_5", "eleven_turbo_v2" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null }, { "voice_id": "cjVigY5qzO86Huf0OWal", "name": "Eric", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": { "eleven_multilingual_v2": "fine_tuned", "eleven_turbo_v2_5": "fine_tuned", "eleven_flash_v2_5": "fine_tuned", "eleven_v2_flash": "fine_tuned", "eleven_v2_5_flash": "fine_tuned", "eleven_turbo_v2": "fine_tuned", "eleven_flash_v2": "fine_tuned" }, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": { "eleven_flash_v2_5": 1, "eleven_v2_flash": 1, "eleven_flash_v2": 1, "eleven_v2_5_flash": 1 }, "message": { "eleven_flash_v2_5": "Done!", "eleven_v2_flash": "Done!", "eleven_flash_v2": "Done!", "eleven_v2_5_flash": "Done!" }, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "American", "description": "friendly", "age": "middle-aged", "gender": "male", "use_case": "conversational" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cjVigY5qzO86Huf0OWal/d098fda0-6456-4030-b3d8-63aa048c9070.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_v2_flash", "eleven_flash_v2", "eleven_turbo_v2_5", "eleven_multilingual_v2", "eleven_v2_5_flash", "eleven_flash_v2_5", "eleven_turbo_v2" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null }, { "voice_id": "iP95p4xoKVk53GoZ742B", "name": "Chris", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": { "eleven_flash_v2_5": "fine_tuned", "eleven_turbo_v2": "fine_tuned", "eleven_flash_v2": "fine_tuned", "eleven_v2_flash": "fine_tuned", "eleven_v2_5_flash": "fine_tuned" }, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": { "eleven_flash_v2_5": 1, "eleven_v2_flash": 1, "eleven_flash_v2": 1, "eleven_v2_5_flash": 1 }, "message": { "eleven_flash_v2_5": "Done!", "eleven_turbo_v2": "", "eleven_flash_v2": "Done!", "eleven_v2_flash": "Done!", "eleven_v2_5_flash": "Done!" }, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "American", "description": "casual", "age": "middle-aged", "gender": "male", "use_case": "conversational" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/iP95p4xoKVk53GoZ742B/3f4bde72-cc48-40dd-829f-57fbf906f4d7.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_v2_flash", "eleven_flash_v2", "eleven_turbo_v2_5", "eleven_multilingual_v2", "eleven_v2_5_flash", "eleven_flash_v2_5", "eleven_turbo_v2" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null }, { "voice_id": "nPczCjzI2devNBz1zQrb", "name": "Brian", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": { "eleven_flash_v2_5": "fine_tuned", "eleven_turbo_v2": "fine_tuned", "eleven_flash_v2": "fine_tuned", "eleven_v2_flash": "fine_tuned", "eleven_v2_5_flash": "fine_tuned" }, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": { "eleven_flash_v2_5": 1, "eleven_v2_flash": 1, "eleven_flash_v2": 1, "eleven_v2_5_flash": 1 }, "message": { "eleven_flash_v2_5": "Done!", "eleven_turbo_v2": "", "eleven_flash_v2": "Done!", "eleven_v2_flash": "Done!", "eleven_v2_5_flash": "Done!" }, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "American", "description": "deep", "age": "middle-aged", "gender": "male", "use_case": "narration" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/nPczCjzI2devNBz1zQrb/2dd3e72c-4fd3-42f1-93ea-abc5d4e5aa1d.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_v2_flash", "eleven_flash_v2", "eleven_turbo_v2_5", "eleven_multilingual_v2", "eleven_v2_5_flash", "eleven_flash_v2_5", "eleven_turbo_v2" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null }, { "voice_id": "onwK4e9ZLuTAKqWW03F9", "name": "Daniel", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": { "eleven_flash_v2_5": "fine_tuned", "eleven_turbo_v2": "fine_tuned", "eleven_flash_v2": "fine_tuned", "eleven_v2_flash": "fine_tuned", "eleven_v2_5_flash": "fine_tuned" }, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": { "eleven_flash_v2_5": 1, "eleven_v2_flash": 1, "eleven_flash_v2": 1, "eleven_v2_5_flash": 1 }, "message": { "eleven_flash_v2_5": "Done!", "eleven_turbo_v2": "", "eleven_flash_v2": "Done!", "eleven_v2_flash": "Done!", "eleven_v2_5_flash": "Done!" }, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "British", "description": "authoritative", "age": "middle-aged", "gender": "male", "use_case": "news" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/onwK4e9ZLuTAKqWW03F9/7eee0236-1a72-4b86-b303-5dcadc007ba9.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_v2_flash", "eleven_flash_v2", "eleven_turbo_v2_5", "eleven_multilingual_v2", "eleven_multilingual_v1", "eleven_v2_5_flash", "eleven_flash_v2_5", "eleven_turbo_v2" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null }, { "voice_id": "pFZP5JQG7iQjIQuC4Bku", "name": "Lily", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": { "eleven_flash_v2_5": "fine_tuned", "eleven_turbo_v2": "fine_tuned", "eleven_flash_v2": "fine_tuned", "eleven_v2_flash": "fine_tuned", "eleven_v2_5_flash": "fine_tuned" }, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": { "eleven_flash_v2_5": 1, "eleven_v2_flash": 1, "eleven_flash_v2": 1, "eleven_v2_5_flash": 1 }, "message": { "eleven_flash_v2_5": "Done!", "eleven_turbo_v2": "", "eleven_flash_v2": "Done!", "eleven_v2_flash": "Done!", "eleven_v2_5_flash": "Done!" }, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "British", "description": "warm", "age": "middle-aged", "gender": "female", "use_case": "narration" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pFZP5JQG7iQjIQuC4Bku/89b68b35-b3dd-4348-a84a-a3c13a3c2b30.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_v2_flash", "eleven_flash_v2", "eleven_turbo_v2_5", "eleven_multilingual_v2", "eleven_v2_5_flash", "eleven_flash_v2_5", "eleven_turbo_v2" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null }, { "voice_id": "pqHfZKP75CvOlQylNhV4", "name": "Bill", "samples": null, "category": "premade", "fine_tuning": { "is_allowed_to_fine_tune": true, "state": { "eleven_flash_v2_5": "fine_tuned", "eleven_turbo_v2": "fine_tuned", "eleven_flash_v2": "fine_tuned", "eleven_v2_flash": "fine_tuned", "eleven_v2_5_flash": "fine_tuned" }, "verification_failures": [], "verification_attempts_count": 0, "manual_verification_requested": false, "language": "en", "progress": { "eleven_flash_v2_5": 1, "eleven_v2_flash": 1, "eleven_flash_v2": 1, "eleven_v2_5_flash": 1 }, "message": { "eleven_flash_v2_5": "Done!", "eleven_turbo_v2": "", "eleven_flash_v2": "Done!", "eleven_v2_flash": "Done!", "eleven_v2_5_flash": "Done!" }, "dataset_duration_seconds": null, "verification_attempts": null, "slice_ids": null, "manual_verification": null, "max_verification_attempts": 5, "next_max_verification_attempts_reset_unix_ms": 1700000000000 }, "labels": { "accent": "American", "description": "trustworthy", "age": "old", "gender": "male", "use_case": "narration" }, "description": null, "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pqHfZKP75CvOlQylNhV4/d782b3ff-84ba-4029-848c-acf01285524d.mp3", "available_for_tiers": [], "settings": null, "sharing": null, "high_quality_base_model_ids": [ "eleven_v2_flash", "eleven_flash_v2", "eleven_turbo_v2_5", "eleven_multilingual_v2", "eleven_v2_5_flash", "eleven_flash_v2_5", "eleven_turbo_v2" ], "verified_languages": [], "safety_control": null, "voice_verification": { "requires_verification": false, "is_verified": false, "verification_failures": [], "verification_attempts_count": 0, "language": null, "verification_attempts": null }, "permission_on_resource": null, "is_owner": false, "is_legacy": false, "is_mixed": false, "created_at_unix": null } ] } --- ### Models/Spring Ai Google Genai/README (models/spring-ai-google-genai/README.md) [Google GenAI Chat](https://docs.spring.io/spring-ai/reference/api/chat/google-genai-chat.html) ### Starter ```xml org.springframework.ai spring-ai-starter-model-google-genai ``` ### Manual config ```xml org.springframework.ai spring-ai-google-genai ``` ### Environment variables ```shell export GOOGLE_GENAI_USE_VERTEXAI=true export GOOGLE_CLOUD_PROJECT='your-project-id' export GOOGLE_CLOUD_LOCATION='your-region' ``` ## Extended Usage Metadata The Google GenAI module provides comprehensive usage metadata tracking through the `GoogleGenAiUsage` class, which extends the standard `Usage` interface with additional token tracking capabilities specific to Google GenAI models. ### Features #### Thinking Tokens Track reasoning tokens for thinking-enabled models like Gemini 2.0 Flash Thinking: ```java ChatResponse response = chatModel.call(prompt); GoogleGenAiUsage usage = (GoogleGenAiUsage) response.getMetadata().getUsage(); Integer thoughtsTokens = usage.getThoughtsTokenCount(); // Reasoning tokens ``` #### Cached Content Tokens Monitor tokens from cached context to optimize API costs: ```java Integer cachedTokens = usage.getCachedContentTokenCount(); // Cached context tokens ``` #### Tool-Use Tokens Track tokens consumed by function calling and tool use: ```java Integer toolUseTokens = usage.getToolUsePromptTokenCount(); // Tool-use tokens ``` #### Modality Breakdowns Get detailed token counts by modality (text, image, audio, video): ```java List promptDetails = usage.getPromptTokensDetails(); for (GoogleGenAiModalityTokenCount detail : promptDetails) { System.out.println(detail.getModality() + ": " + detail.getTokenCount()); } ``` #### Traffic Type Identify whether requests use Pay-As-You-Go or Provisioned Throughput: ```java GoogleGenAiTrafficType trafficType = usage.getTrafficType(); // Returns: ON_DEMAND, PROVISIONED_THROUGHPUT, or UNKNOWN ``` ### Configuration Control whether to include extended metadata (enabled by default): ```java GoogleGenAiChatOptions options = GoogleGenAiChatOptions.builder() .model("gemini-2.0-flash") .includeExtendedUsageMetadata(true) // Enable extended metadata .build(); ``` ### Complete Example ``` /* Detailed source-code truncated for AI context efficiency. */ ``` ### Backward Compatibility The extended usage metadata maintains full backward compatibility with the standard `Usage` interface. Code using the basic interface continues to work without modification: ```java // Works with any Spring AI model Usage usage = response.getMetadata().getUsage(); Long promptTokens = usage.getPromptTokens(); Long completionTokens = usage.getCompletionTokens(); ``` --- ### Models/Spring Ai Google Genai Embedding/README (models/spring-ai-google-genai-embedding/README.md) # Google GenAI Embeddings Module [Google GenAI Text Embeddings Documentation](https://docs.spring.io/spring-ai/reference/api/embeddings/google-genai-embeddings-text.html) ## Overview The Google GenAI Embeddings module provides text embedding generation using Google's embedding models through either the Gemini Developer API or Vertex AI. ## Current Support Please note that at this time the *spring-ai-google-genai-embedding* module supports **text embeddings only**. This is due to the fact that the Google GenAI SDK currently supports text embeddings only, with multimodal embeddings support pending. ## Starter Dependency ```xml org.springframework.ai spring-ai-starter-model-google-genai-embedding ``` ## Manual Configuration ```xml org.springframework.ai spring-ai-google-genai-embedding ``` ## Authentication Modes The module supports two authentication modes: - **Gemini Developer API**: Use an API key for quick prototyping - **Vertex AI**: Use Google Cloud credentials for production deployments See the [documentation](https://docs.spring.io/spring-ai/reference/api/embeddings/google-genai-embeddings-text.html) for detailed configuration instructions. --- ### Models/Spring Ai Mistral Ai/README (models/spring-ai-mistral-ai/README.md) [Mistral AI Chat Documentation](https://docs.spring.io/spring-ai/reference/api/chat/mistralai-chat.html) [Mistral AI Embedding Documentation](https://docs.spring.io/spring-ai/reference/api/embeddings/mistralai-embeddings.html) --- ### Models/Spring Ai Mistral Ai/Src/Test/Resources/References.Json (models/spring-ai-mistral-ai/src/test/resources/references.json) { "0": { "url": "https://en.wikipedia.org/wiki/2024_Nobel_Peace_Prize", "title": "2024 Nobel Peace Prize", "snippets": [ [ "The 2024 Nobel Peace Prize, an international peace prize established according to Alfred Nobel's will, was awarded to Nihon Hidankyo (the Japan Confederation of A- and H-Bomb Sufferers Organizations), for their activism against nuclear weapons, assisted by victim/survivors (known as Hibakusha) of the atomic bombings of Hiroshima and Nagasaki in 1945.", "They will receive the prize at a ceremony on 10 December 2024 at Oslo, Norway." ] ], "description": null, "date": "2024-11-26T17:39:55.057454", "source": "wikipedia" }, "1": { "url": "https://en.wikipedia.org/wiki/Climate_Change", "title": "Climate Change", "snippets": [ [ "Present-day climate change includes both global warming—the ongoing increase in global average temperature—and its wider effects on Earth’s climate system. Climate change in a broader sense also includes previous long-term changes to Earth's climate. The current rise in global temperatures is driven by human activities, especially fossil fuel burning since the Industrial Revolution. Fossil fuel use, deforestation, and some agricultural and industrial practices release greenhouse gases. These gases absorb some of the heat that the Earth radiates after it warms from sunlight, warming the lower atmosphere. Carbon dioxide, the primary gas driving global warming, has increased in concentration by about 50% since the pre-industrial era to levels not seen for millions of years." ] ], "description": null, "date": "2024-11-26T17:39:55.057454", "source": "wikipedia" }, "2": { "url": "https://en.wikipedia.org/wiki/Artificial_Intelligence", "title": "Artificial Intelligence", "snippets": [ [ "Artificial intelligence (AI) refers to the capability of computational systems to perform tasks typically associated with human intelligence, such as learning, reasoning, problem-solving, perception, and decision-making. It is a field of research in computer science that develops and studies methods and software that enable machines to perceive their environment and use learning and intelligence to take actions that maximize their chances of achieving defined goals. Such machines may be called AIs." ] ], "description": null, "date": "2024-11-26T17:39:55.057454", "source": "wikipedia" } } --- ### Models/Spring Ai Mistral Ai/Src/Test/Resources/Contents/Content Chunks.Json (models/spring-ai-mistral-ai/src/test/resources/contents/content_chunks.json) [ { "type": "image_url", "image_url": { "url": "https://example.com/image.png", "detail": "auto" } }, { "type": "reference", "reference_ids": [ 1, 2, 3 ] }, { "type": "text", "text": "content text" }, { "type": "thinking", "thinking": [ { "type": "reference", "reference_ids": [ 4, 5, 6 ] }, { "type": "text", "text": "thinking text" } ], "closed": true } ] --- ### Models/Spring Ai Mistral Ai/Src/Test/Resources/Messages/Content Chunks Message.Json (models/spring-ai-mistral-ai/src/test/resources/messages/content_chunks_message.json) { "role": "user", "content": [ { "type": "image_url", "image_url": { "url": "https://example.com/image.png", "detail": "auto" } }, { "type": "reference", "reference_ids": [ 1, 2, 3 ] }, { "type": "text", "text": "content text" }, { "type": "thinking", "thinking": [ { "type": "reference", "reference_ids": [ 4, 5, 6 ] }, { "type": "text", "text": "thinking text" } ], "closed": true } ] } --- ### Models/Spring Ai Ollama/README (models/spring-ai-ollama/README.md) [Ollama Chat Documentation](https://docs.spring.io/spring-ai/reference/api/chat/ollama-chat.html) [Ollama Embedding Documentation](https://docs.spring.io/spring-ai/reference/api/embeddings/ollama-embeddings.html) --- ### Models/Spring Ai Ollama/Src/Test/Resources/Country Json Schema.Json (models/spring-ai-ollama/src/test/resources/country-json-schema.json) { "type": "object", "properties": { "name": { "type": "string" }, "capital": { "type": "string" }, "languages": { "type": "array", "items": { "type": "string" } } }, "required": [ "name", "capital", "languages" ] } --- ### Models/Spring Ai Openai/README (models/spring-ai-openai/README.md) [OpenAI Chat Documentation](https://docs.spring.io/spring-ai/reference/api/chat/openai-chat.html) [OpenAI Embedding Documentation](https://docs.spring.io/spring-ai/reference/api/embeddings/openai-embeddings.html) [OpenAI Image Generation](https://docs.spring.io/spring-ai/reference/api/image/openai-image.html) [OpenAI Transcription Generation](https://docs.spring.io/spring-ai/reference/api/audio/transcriptions/openai-transcriptions.html) [OpenAI Text-to-Speech (TTS)](https://docs.spring.io/spring-ai/reference/api/audio/speech/openai-speech.html) --- ### Models/Spring Ai Openai/Src/Test/Resources/Text Source (models/spring-ai-openai/src/test/resources/text_source.txt) Spring Framework Documentation Version 6.0.0 Chapter 1. Spring Framework Overview Spring makes it easy to create Java enterprise applications. It provides everything you need to embrace the Java language in an enterprise environment, with support for Groovy and Kotlin as alternative languages on the JVM, and with the flexibility to create many kinds of architectures depending on an application’s needs. As of Spring Framework 5.1, Spring requires JDK 8+ (Java SE 8+) and provides out-of-the-box support for JDK 11 LTS. Java SE 8 update 60 is suggested as the minimum patch release for Java 8, but it is generally recommended to use a recent patch release. Spring supports a wide range of application scenarios. In a large enterprise, applications often exist for a long time and have to run on a JDK and application server whose upgrade cycle is beyond developer control. Others may run as a single jar with the server embedded, possibly in a cloud environment. Yet others may be standalone applications (such as batch or integration workloads) that do not need a server. Spring is open source. It has a large and active community that provides continuous feedback based on a diverse range of real-world use cases. This has helped Spring to successfully evolve over a very long time. 1.1. What We Mean by "Spring" The term "Spring" means different things in different contexts. It can be used to refer to the Spring Framework project itself, which is where it all started. Over time, other Spring projects have been built on top of the Spring Framework. Most often, when people say "Spring", they mean the entire family of projects. This reference documentation focuses on the foundation: the Spring Framework itself. The Spring Framework is divided into modules. Applications can choose which modules they need. At the heart are the modules of the core container, including a configuration model and a dependency injection mechanism. Beyond that, the Spring Framework provides foundational support for different application architectures, including messaging, transactional data and persistence, and web. It also includes the Servlet-based Spring MVC web framework and, in parallel, the Spring WebFlux reactive web framework. A note about modules: Spring’s framework jars allow for deployment to JDK 9’s module path ("Jigsaw"). For use in Jigsaw-enabled applications, the Spring Framework 5 jars come with "Automatic-Module-Name" manifest entries which define stable language-level module names ("spring.core", "spring.context", etc.) independent from jar artifact names (the jars follow the same naming pattern with "-" instead of ".", e.g. "spring-core" and "spring-context"). Of course, Spring’s framework jars keep working fine on the classpath on both JDK 8 and 9+. 1.2. History of Spring and the Spring Framework Spring came into being in 2003 as a response to the complexity of the early J2EE specifications. While some consider Java EE and its modern-day successor Jakarta EE to be in competition with Spring, they are in fact complementary. The Spring programming model does not embrace the Jakarta EE platform specification; rather, it integrates with carefully selected individual specifications from the traditional EE umbrella: • Servlet API (JSR 340) • WebSocket API (JSR 356) • Concurrency Utilities (JSR 236) • JSON Binding API (JSR 367) • Bean Validation (JSR 303) • JPA (JSR 338) • JMS (JSR 914) • as well as JTA/JCA setups for transaction coordination, if necessary. The Spring Framework also supports the Dependency Injection (JSR 330) and Common Annotations (JSR 250) specifications, which application developers may choose to use instead of the Spring- specific mechanisms provided by the Spring Framework. Originally, those were based on common javax packages. As of Spring Framework 6.0, Spring has been upgraded to the Jakarta EE 9 level (e.g. Servlet 5.0+, JPA 3.0+), based on the jakarta namespace instead of the traditional javax packages. With EE 9 as the minimum and EE 10 supported already, Spring is prepared to provide out-of-the-box support for the further evolution of the Jakarta EE APIs. Spring Framework 6.0 is fully compatible with Tomcat 10.1, Jetty 11 and Undertow 2.3 as web servers, and also with Hibernate ORM 6.1. Over time, the role of Java/Jakarta EE in application development has evolved. In the early days of J2EE and Spring, applications were created to be deployed to an application server. Today, with the help of Spring Boot, applications are created in a devops- and cloud-friendly way, with the Servlet container embedded and trivial to change. As of Spring Framework 5, a WebFlux application does not even use the Servlet API directly and can run on servers (such as Netty) that are not Servlet containers. Spring continues to innovate and to evolve. Beyond the Spring Framework, there are other projects, such as Spring Boot, Spring Security, Spring Data, Spring Cloud, Spring Batch, among others. It’s important to remember that each project has its own source code repository, issue tracker, and release cadence. See spring.io/projects for the complete list of Spring projects. 1.3. Design Philosophy When you learn about a framework, it’s important to know not only what it does but what principles it follows. Here are the guiding principles of the Spring Framework: • Provide choice at every level. Spring lets you defer design decisions as late as possible. For example, you can switch persistence providers through configuration without changing your code. The same is true for many other infrastructure concerns and integration with third-party APIs. • Accommodate diverse perspectives. Spring embraces flexibility and is not opinionated about how things should be done. It supports a wide range of application needs with different perspectives. • Maintain strong backward compatibility. Spring’s evolution has been carefully managed to force few breaking changes between versions. Spring supports a carefully chosen range of JDK versions and third-party libraries to facilitate maintenance of applications and libraries that depend on Spring. • Care about API design. The Spring team puts a lot of thought and time into making APIs that are intuitive and that hold up across many versions and many years. • Set high standards for code quality. The Spring Framework puts a strong emphasis on meaningful, current, and accurate javadoc. It is one of very few projects that can claim clean code structure with no circular dependencies between packages. 1.4. Feedback and Contributions For how-to questions or diagnosing or debugging issues, we suggest using Stack Overflow. Click here for a list of the suggested tags to use on Stack Overflow. If you’re fairly certain that there is a problem in the Spring Framework or would like to suggest a feature, please use the GitHub Issues. If you have a solution in mind or a suggested fix, you can submit a pull request on Github. However, please keep in mind that, for all but the most trivial issues, we expect a ticket to be filed in the issue tracker, where discussions take place and leave a record for future reference. For more details see the guidelines at the CONTRIBUTING, top-level project page. 1.5. Getting Started If you are just getting started with Spring, you may want to begin using the Spring Framework by creating a Spring Boot-based application. Spring Boot provides a quick (and opinionated) way to create a production-ready Spring-based application. It is based on the Spring Framework, favors convention over configuration, and is designed to get you up and running as quickly as possible. You can use start.spring.io to generate a basic project or follow one of the "Getting Started" guides, such as Getting Started Building a RESTful Web Service. As well as being easier to digest, these guides are very task focused, and most of them are based on Spring Boot. They also cover other projects from the Spring portfolio that you might want to consider when solving a particular problem. Chapter 2. Core Technologies This part of the reference documentation covers all the technologies that are absolutely integral to the Spring Framework. Foremost amongst these is the Spring Framework’s Inversion of Control (IoC) container. A thorough treatment of the Spring Framework’s IoC container is closely followed by comprehensive coverage of Spring’s Aspect-Oriented Programming (AOP) technologies. The Spring Framework has its own AOP framework, which is conceptually easy to understand and which successfully addresses the 80% sweet spot of AOP requirements in Java enterprise programming. Coverage of Spring’s integration with AspectJ (currently the richest — in terms of features — and certainly most mature AOP implementation in the Java enterprise space) is also provided. AOT processing can be used to optimize your application ahead-of-time. It is typically used for native image deployment using GraalVM. 2.1. The IoC Container This chapter covers Spring’s Inversion of Control (IoC) container. 2.1.1. Introduction to the Spring IoC Container and Beans This chapter covers the Spring Framework implementation of the Inversion of Control (IoC) principle. IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes or a mechanism such as the Service Locator pattern. The org.springframework.beans and org.springframework.context packages are the basis for Spring Framework’s IoC container. The BeanFactory interface provides an advanced configuration mechanism capable of managing any type of object. ApplicationContext is a sub-interface of BeanFactory. It adds: • Easier integration with Spring’s AOP features • Message resource handling (for use in internationalization) • Event publication • Application-layer specific contexts such as the WebApplicationContext for use in web applications. In short, the BeanFactory provides the configuration framework and basic functionality, and the ApplicationContext adds more enterprise-specific functionality. The ApplicationContext is a complete superset of the BeanFactory and is used exclusively in this chapter in descriptions of Spring’s IoC container. For more information on using the BeanFactory instead of the ApplicationContext, see the section covering the BeanFactory API. In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container. 2.1.2. Container Overview The org.springframework.context.ApplicationContext interface represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the beans. The container gets its instructions on what objects to instantiate, configure, and assemble by reading configuration metadata. The configuration metadata is represented in XML, Java annotations, or Java code. It lets you express the objects that compose your application and the rich interdependencies between those objects. Several implementations of the ApplicationContext interface are supplied with Spring. In stand- alone applications, it is common to create an instance of ClassPathXmlApplicationContext or FileSystemXmlApplicationContext. While XML has been the traditional format for defining configuration metadata, you can instruct the container to use Java annotations or code as the metadata format by providing a small amount of XML configuration to declaratively enable support for these additional metadata formats. In most application scenarios, explicit user code is not required to instantiate one or more instances of a Spring IoC container. For example, in a web application scenario, a simple eight (or so) lines of boilerplate web descriptor XML in the web.xml file of the application typically suffices (see Convenient ApplicationContext Instantiation for Web Applications). If you use the Spring Tools for Eclipse (an Eclipse-powered development environment), you can easily create this boilerplate configuration with a few mouse clicks or keystrokes. The following diagram shows a high-level view of how Spring works. Your application classes are combined with configuration metadata so that, after the ApplicationContext is created and initialized, you have a fully configured and executable system or application. Figure 1. The Spring IoC container Configuration Metadata As the preceding diagram shows, the Spring IoC container consumes a form of configuration metadata. This configuration metadata represents how you, as an application developer, tell the Spring container to instantiate, configure, and assemble the objects in your application. Configuration metadata is traditionally supplied in a simple and intuitive XML format, which is what most of this chapter uses to convey key concepts and features of the Spring IoC container. XML-based metadata is not the only allowed form of configuration metadata. The Spring IoC container itself is totally decoupled from the format in which this  configuration metadata is actually written. These days, many developers choose Java-based configuration for their Spring applications. For information about using other forms of metadata with the Spring container, see: • Annotation-based configuration: Spring 2.5 introduced support for annotation-based configuration metadata. • Java-based configuration: Starting with Spring 3.0, many features provided by the Spring JavaConfig project became part of the core Spring Framework. Thus, you can define beans external to your application classes by using Java rather than XML files. To use these new features, see the @Configuration, @Bean, @Import, and @DependsOn annotations. Spring configuration consists of at least one and typically more than one bean definition that the container must manage. XML-based configuration metadata configures these beans as elements inside a top-level element. Java configuration typically uses @Bean-annotated methods within a @Configuration class. These bean definitions correspond to the actual objects that make up your application. Typically, you define service layer objects, data access objects (DAOs), presentation objects such as Struts Action instances, infrastructure objects such as Hibernate SessionFactories, JMS Queues, and so forth. Typically, one does not configure fine-grained domain objects in the container, because it is usually the responsibility of DAOs and business logic to create and load domain objects. However, you can use Spring’s integration with AspectJ to configure objects that have been created outside the control of an IoC container. See Using AspectJ to dependency-inject domain objects with Spring. The following example shows the basic structure of XML-based configuration metadata:   ① ②             ① The id attribute is a string that identifies the individual bean definition. ② The class attribute defines the type of the bean and uses the fully qualified classname. The value of the id attribute refers to collaborating objects. The XML for referring to collaborating objects is not shown in this example. See Dependencies for more information. Instantiating a Container The location path or paths supplied to an ApplicationContext constructor are resource strings that let the container load configuration metadata from a variety of external resources, such as the local file system, the Java CLASSPATH, and so on. Java ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml"); Kotlin val context = ClassPathXmlApplicationContext("services.xml", "daos.xml") After you learn about Spring’s IoC container, you may want to know more about Spring’s Resource abstraction (as described in Resources), which provides a  convenient mechanism for reading an InputStream from locations defined in a URI syntax. In particular, Resource paths are used to construct applications contexts, as described in Application Contexts and Resource Paths. The following example shows the service layer objects (services.xml) configuration file:               The following example shows the data access objects daos.xml file:               In the preceding example, the service layer consists of the PetStoreServiceImpl class and two data access objects of the types JpaAccountDao and JpaItemDao (based on the JPA Object-Relational Mapping standard). The property name element refers to the name of the JavaBean property, and the ref element refers to the name of another bean definition. This linkage between id and ref elements expresses the dependency between collaborating objects. For details of configuring an object’s dependencies, see Dependencies. Composing XML-based Configuration Metadata It can be useful to have bean definitions span multiple XML files. Often, each individual XML configuration file represents a logical layer or module in your architecture. You can use the application context constructor to load bean definitions from all these XML fragments. This constructor takes multiple Resource locations, as was shown in the previous section. Alternatively, use one or more occurrences of the element to load bean definitions from another file or files. The following example shows how to do so:           In the preceding example, external bean definitions are loaded from three files: services.xml, messageSource.xml, and themeSource.xml. All location paths are relative to the definition file doing the importing, so services.xml must be in the same directory or classpath location as the file doing the importing, while messageSource.xml and themeSource.xml must be in a resources location below the location of the importing file. As you can see, a leading slash is ignored. However, given that these paths are relative, it is better form not to use the slash at all. The contents of the files being imported, including the top level element, must be valid XML bean definitions, according to the Spring Schema. It is possible, but not recommended, to reference files in parent directories using a relative "../" path. Doing so creates a dependency on a file that is outside the current application. In particular, this reference is not recommended for classpath: URLs (for example, classpath:../services.xml), where the runtime resolution process chooses the “nearest” classpath root and then looks into its parent directory. Classpath configuration changes may lead to the choice of a different, incorrect directory.  You can always use fully qualified resource locations instead of relative paths: for example, file:C:/config/services.xml or classpath:/config/services.xml. However, be aware that you are coupling your application’s configuration to specific absolute locations. It is generally preferable to keep an indirection for such absolute locations — for example, through "${…}" placeholders that are resolved against JVM system properties at runtime. The namespace itself provides the import directive feature. Further configuration features beyond plain bean definitions are available in a selection of XML namespaces provided by Spring — for example, the context and util namespaces. The Groovy Bean Definition DSL As a further example for externalized configuration metadata, bean definitions can also be expressed in Spring’s Groovy Bean Definition DSL, as known from the Grails framework. Typically, such configuration live in a ".groovy" file with the structure shown in the following example: beans {   dataSource(BasicDataSource) {   driverClassName = "org.hsqldb.jdbcDriver"   url = "jdbc:hsqldb:mem:grailsDB"   username = "sa"   password = ""   settings = [mynew:"setting"]   }   sessionFactory(SessionFactory) {   dataSource = dataSource   }   myService(MyService) {   nestedBean = { AnotherBean bean ->   dataSource = dataSource   }   } } This configuration style is largely equivalent to XML bean definitions and even supports Spring’s XML configuration namespaces. It also allows for importing XML bean definition files through an importBeans directive. Using the Container The ApplicationContext is the interface for an advanced factory capable of maintaining a registry of different beans and their dependencies. By using the method T getBean(String name, Class requiredType), you can retrieve instances of your beans. The ApplicationContext lets you read bean definitions and access them, as the following example shows: Java // create and configure beans ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml"); // retrieve configured instance PetStoreService service = context.getBean("petStore", PetStoreService.class); // use configured instance List userList = service.getUsernameList(); Kotlin import org.springframework.beans.factory.getBean // create and configure beans val context = ClassPathXmlApplicationContext("services.xml", "daos.xml") // retrieve configured instance val service = context.getBean("petStore") // use configured instance var userList = service.getUsernameList() With Groovy configuration, bootstrapping looks very similar. It has a different context implementation class which is Groovy-aware (but also understands XML bean definitions). The following example shows Groovy configuration: Java ApplicationContext context = new GenericGroovyApplicationContext("services.groovy", "daos.groovy"); Kotlin val context = GenericGroovyApplicationContext("services.groovy", "daos.groovy") The most flexible variant is GenericApplicationContext in combination with reader delegates — for example, with XmlBeanDefinitionReader for XML files, as the following example shows: Java GenericApplicationContext context = new GenericApplicationContext(); new XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml"); context.refresh(); Kotlin val context = GenericApplicationContext() XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml") context.refresh() You can also use the GroovyBeanDefinitionReader for Groovy files, as the following example shows: Java GenericApplicationContext context = new GenericApplicationContext(); new GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy"); context.refresh(); Kotlin val context = GenericApplicationContext() GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy") context.refresh() You can mix and match such reader delegates on the same ApplicationContext, reading bean definitions from diverse configuration sources. You can then use getBean to retrieve instances of your beans. The ApplicationContext interface has a few other methods for retrieving beans, but, ideally, your application code should never use them. Indeed, your application code should have no calls to the getBean() method at all and thus have no dependency on Spring APIs at all. For example, Spring’s integration with web frameworks provides dependency injection for various web framework components such as controllers and JSF-managed beans, letting you declare a dependency on a specific bean through metadata (such as an autowiring annotation). 2.1.3. Bean Overview A Spring IoC container manages one or more beans. These beans are created with the configuration metadata that you supply to the container (for example, in the form of XML definitions). Within the container itself, these bean definitions are represented as BeanDefinition objects, which contain (among other information) the following metadata: • A package-qualified class name: typically, the actual implementation class of the bean being defined. • Bean behavioral configuration elements, which state how the bean should behave in the container (scope, lifecycle callbacks, and so forth). • References to other beans that are needed for the bean to do its work. These references are also called collaborators or dependencies. • Other configuration settings to set in the newly created object — for example, the size limit of the pool or the number of connections to use in a bean that manages a connection pool. This metadata translates to a set of properties that make up each bean definition. The following table describes these properties: Table 1. The bean definition Property Explained in… Class Instantiating Beans Name Naming Beans Scope Bean Scopes Constructor arguments Dependency Injection Properties Dependency Injection Autowiring mode Autowiring Collaborators Lazy initialization mode Lazy-initialized Beans Initialization method Initialization Callbacks Destruction method Destruction Callbacks In addition to bean definitions that contain information on how to create a specific bean, the ApplicationContext implementations also permit the registration of existing objects that are created outside the container (by users). This is done by accessing the ApplicationContext’s BeanFactory through the getBeanFactory() method, which returns the DefaultListableBeanFactory implementation. DefaultListableBeanFactory supports this registration through the registerSingleton(..) and registerBeanDefinition(..) methods. However, typical applications work solely with beans defined through regular bean definition metadata. Bean metadata and manually supplied singleton instances need to be registered as early as possible, in order for the container to properly reason about them during autowiring and other introspection steps. While overriding existing metadata and  existing singleton instances is supported to some degree, the registration of new beans at runtime (concurrently with live access to the factory) is not officially supported and may lead to concurrent access exceptions, inconsistent state in the bean container, or both. Naming Beans Every bean has one or more identifiers. These identifiers must be unique within the container that hosts the bean. A bean usually has only one identifier. However, if it requires more than one, the extra ones can be considered aliases. In XML-based configuration metadata, you use the id attribute, the name attribute, or both to specify the bean identifiers. The id attribute lets you specify exactly one id. Conventionally, these names are alphanumeric ('myBean', 'someService', etc.), but they can contain special characters as well. If you want to introduce other aliases for the bean, you can also specify them in the name attribute, separated by a comma (,), semicolon (;), or white space. As a historical note, in versions prior to Spring 3.1, the id attribute was defined as an xsd:ID type, which constrained possible characters. As of 3.1, it is defined as an xsd:string type. Note that bean id uniqueness is still enforced by the container, though no longer by XML parsers. You are not required to supply a name or an id for a bean. If you do not supply a name or id explicitly, the container generates a unique name for that bean. However, if you want to refer to that bean by name, through the use of the ref element or a Service Locator style lookup, you must provide a name. Motivations for not supplying a name are related to using inner beans and autowiring collaborators. Bean Naming Conventions The convention is to use the standard Java convention for instance field names when naming beans. That is, bean names start with a lowercase letter and are camel-cased from there. Examples of such names include accountManager, accountService, userDao, loginController, and so forth. Naming beans consistently makes your configuration easier to read and understand. Also, if you use Spring AOP, it helps a lot when applying advice to a set of beans related by name. With component scanning in the classpath, Spring generates bean names for unnamed components, following the rules described earlier: essentially, taking the simple class name and turning its initial character to lower-case. However, in the  (unusual) special case when there is more than one character and both the first and second characters are upper case, the original casing gets preserved. These are the same rules as defined by java.beans.Introspector.decapitalize (which Spring uses here). Aliasing a Bean outside the Bean Definition In a bean definition itself, you can supply more than one name for the bean, by using a combination of up to one name specified by the id attribute and any number of other names in the name attribute. These names can be equivalent aliases to the same bean and are useful for some situations, such as letting each component in an application refer to a common dependency by using a bean name that is specific to that component itself. Specifying all aliases where the bean is actually defined is not always adequate, however. It is sometimes desirable to introduce an alias for a bean that is defined elsewhere. This is commonly the case in large systems where configuration is split amongst each subsystem, with each subsystem having its own set of object definitions. In XML-based configuration metadata, you can use the element to accomplish this. The following example shows how to do so: In this case, a bean (in the same container) named fromName may also, after the use of this alias definition, be referred to as toName. For example, the configuration metadata for subsystem A may refer to a DataSource by the name of subsystemA-dataSource. The configuration metadata for subsystem B may refer to a DataSource by the name of subsystemB-dataSource. When composing the main application that uses both these subsystems, the main application refers to the DataSource by the name of myApp-dataSource. To have all three names refer to the same object, you can add the following alias definitions to the configuration metadata: Now each component and the main application can refer to the dataSource through a name that is unique and guaranteed not to clash with any other definition (effectively creating a namespace), yet they refer to the same bean. Java-configuration If you use Javaconfiguration, the @Bean annotation can be used to provide aliases. See Using the @Bean Annotation for details. Instantiating Beans A bean definition is essentially a recipe for creating one or more objects. The container looks at the recipe for a named bean when asked and uses the configuration metadata encapsulated by that bean definition to create (or acquire) an actual object. If you use XML-based configuration metadata, you specify the type (or class) of object that is to be instantiated in the class attribute of the element. This class attribute (which, internally, is a Class property on a BeanDefinition instance) is usually mandatory. (For exceptions, see Instantiation by Using an Instance Factory Method and Bean Definition Inheritance.) You can use the Class property in one of two ways: • Typically, to specify the bean class to be constructed in the case where the container itself directly creates the bean by calling its constructor reflectively, somewhat equivalent to Java code with the new operator. • To specify the actual class containing the static factory method that is invoked to create the object, in the less common case where the container invokes a static factory method on a class to create the bean. The object type returned from the invocation of the static factory method may be the same class or another class entirely. Nested class names If you want to configure a bean definition for a nested class, you may use either the binary name or the source name of the nested class. For example, if you have a class called SomeThing in the com.example package, and this SomeThing class has a static nested class called OtherThing, they can be separated by a dollar sign ($) or a dot (.). So the value of the class attribute in a bean definition would be com.example.SomeThing$OtherThing or com.example.SomeThing.OtherThing. Instantiation with a Constructor When you create a bean by the constructor approach, all normal classes are usable by and compatible with Spring. That is, the class being developed does not need to implement any specific interfaces or to be coded in a specific fashion. Simply specifying the bean class should suffice. However, depending on what type of IoC you use for that specific bean, you may need a default (empty) constructor. The Spring IoC container can manage virtually any class you want it to manage. It is not limited to managing true JavaBeans. Most Spring users prefer actual JavaBeans with only a default (no- argument) constructor and appropriate setters and getters modeled after the properties in the container. You can also have more exotic non-bean-style classes in your container. If, for example, you need to use a legacy connection pool that absolutely does not adhere to the JavaBean specification, Spring can manage it as well. With XML-based configuration metadata you can specify your bean class as follows: For details about the mechanism for supplying arguments to the constructor (if required) and setting object instance properties after the object is constructed, see Injecting Dependencies. Instantiation with a Static Factory Method When defining a bean that you create with a static factory method, use the class attribute to specify the class that contains the static factory method and an attribute named factory-method to specify the name of the factory method itself. You should be able to call this method (with optional arguments, as described later) and return a live object, which subsequently is treated as if it had been created through a constructor. One use for such a bean definition is to call static factories in legacy code. The following bean definition specifies that the bean will be created by calling a factory method. The definition does not specify the type (class) of the returned object, but rather the class containing the factory method. In this example, the createInstance() method must be a static method. The following example shows how to specify a factory method: The following example shows a class that would work with the preceding bean definition: Java public class ClientService {   private static ClientService clientService = new ClientService();   private ClientService() {}   public static ClientService createInstance() {   return clientService;   } } Kotlin class ClientService private constructor() {   companion object {   private val clientService = ClientService()   @JvmStatic   fun createInstance() = clientService   } } For details about the mechanism for supplying (optional) arguments to the factory method and setting object instance properties after the object is returned from the factory, see Dependencies and Configuration in Detail. Instantiation by Using an Instance Factory Method Similar to instantiation through a static factory method, instantiation with an instance factory method invokes a non-static method of an existing bean from the container to create a new bean. To use this mechanism, leave the class attribute empty and, in the factory-bean attribute, specify the name of a bean in the current (or parent or ancestor) container that contains the instance method that is to be invoked to create the object. Set the name of the factory method itself with the factory-method attribute. The following example shows how to configure such a bean:   The following example shows the corresponding class: Java public class DefaultServiceLocator {   private static ClientService clientService = new ClientServiceImpl();   public ClientService createClientServiceInstance() {   return clientService;   } } Kotlin class DefaultServiceLocator {   companion object {   private val clientService = ClientServiceImpl()   }   fun createClientServiceInstance(): ClientService {   return clientService   } } One factory class can also hold more than one factory method, as the following example shows:   The following example shows the corresponding class: Java public class DefaultServiceLocator {   private static ClientService clientService = new ClientServiceImpl();   private static AccountService accountService = new AccountServiceImpl();   public ClientService createClientServiceInstance() {   return clientService;   }   public AccountService createAccountServiceInstance() {   return accountService;   } } Kotlin class DefaultServiceLocator {   companion object {   private val clientService = ClientServiceImpl()   private val accountService = AccountServiceImpl()   }   fun createClientServiceInstance(): ClientService {   return clientService   }   fun createAccountServiceInstance(): AccountService {   return accountService   } } This approach shows that the factory bean itself can be managed and configured through dependency injection (DI). See Dependencies and Configuration in Detail. In Spring documentation, "factory bean" refers to a bean that is configured in the Spring container and that creates objects through an instance or static factory  method. By contrast, FactoryBean (notice the capitalization) refers to a Spring- specific FactoryBean implementation class. Determining a Bean’s Runtime Type The runtime type of a specific bean is non-trivial to determine. A specified class in the bean metadata definition is just an initial class reference, potentially combined with a declared factory method or being a FactoryBean class which may lead to a different runtime type of the bean, or not being set at all in case of an instance-level factory method (which is resolved via the specified factory-bean name instead). Additionally, AOP proxying may wrap a bean instance with an interface-based proxy with limited exposure of the target bean’s actual type (just its implemented interfaces). The recommended way to find out about the actual runtime type of a particular bean is a BeanFactory.getType call for the specified bean name. This takes all of the above cases into account and returns the type of object that a BeanFactory.getBean call is going to return for the same bean name. 2.1.4. Dependencies A typical enterprise application does not consist of a single object (or bean in the Spring parlance). Even the simplest application has a few objects that work together to present what the end-user sees as a coherent application. This next section explains how you go from defining a number of bean definitions that stand alone to a fully realized application where objects collaborate to achieve a goal. Dependency Injection Dependency injection (DI) is a process whereby objects define their dependencies (that is, the other objects with which they work) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies on its own by using direct construction of classes or the Service Locator pattern. Code is cleaner with the DI principle, and decoupling is more effective when objects are provided with their dependencies. The object does not look up its dependencies and does not know the location or class of the dependencies. As a result, your classes become easier to test, particularly when the dependencies are on interfaces or abstract base classes, which allow for stub or mock implementations to be used in unit tests. DI exists in two major variants: Constructor-based dependency injection and Setter-based dependency injection. Constructor-based Dependency Injection Constructor-based DI is accomplished by the container invoking a constructor with a number of arguments, each representing a dependency. Calling a static factory method with specific arguments to construct the bean is nearly equivalent, and this discussion treats arguments to a constructor and to a static factory method similarly. The following example shows a class that can only be dependency-injected with constructor injection: Java public class SimpleMovieLister {   // the SimpleMovieLister has a dependency on a MovieFinder   private final MovieFinder movieFinder;   // a constructor so that the Spring container can inject a MovieFinder   public SimpleMovieLister(MovieFinder movieFinder) {   this.movieFinder = movieFinder;   }   // business logic that actually uses the injected MovieFinder is omitted... } Kotlin // a constructor so that the Spring container can inject a MovieFinder class SimpleMovieLister(private val movieFinder: MovieFinder) {   // business logic that actually uses the injected MovieFinder is omitted... } Notice that there is nothing special about this class. It is a POJO that has no dependencies on container specific interfaces, base classes, or annotations. Constructor Argument Resolution Constructor argument resolution matching occurs by using the argument’s type. If no potential ambiguity exists in the constructor arguments of a bean definition, the order in which the constructor arguments are defined in a bean definition is the order in which those arguments are supplied to the appropriate constructor when the bean is being instantiated. Consider the following class: Java package x.y; public class ThingOne {   public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {   // ...   } } Kotlin package x.y class ThingOne(thingTwo: ThingTwo, thingThree: ThingThree) Assuming that the ThingTwo and ThingThree classes are not related by inheritance, no potential ambiguity exists. Thus, the following configuration works fine, and you do not need to specify the constructor argument indexes or types explicitly in the element.             When another bean is referenced, the type is known, and matching can occur (as was the case with the preceding example). When a simple type is used, such as true, Spring cannot determine the type of the value, and so cannot match by type without help. Consider the following class: Java package examples; public class ExampleBean {   // Number of years to calculate the Ultimate Answer   private final int years;   // The Answer to Life, the Universe, and Everything   private final String ultimateAnswer;   public ExampleBean(int years, String ultimateAnswer) {   this.years = years;   this.ultimateAnswer = ultimateAnswer;   } } Kotlin package examples class ExampleBean(   private val years: Int, // Number of years to calculate the Ultimate Answer   private val ultimateAnswer: String // The Answer to Life, the Universe, and Everything ) Constructor argument type matching In the preceding scenario, the container can use type matching with simple types if you explicitly specify the type of the constructor argument by using the type attribute, as the following example shows:     Constructor argument index You can use the index attribute to specify explicitly the index of constructor arguments, as the following example shows:     In addition to resolving the ambiguity of multiple simple values, specifying an index resolves ambiguity where a constructor has two arguments of the same type.  The index is 0-based. Constructor argument name You can also use the constructor parameter name for value disambiguation, as the following example shows:     Keep in mind that, to make this work out of the box, your code must be compiled with the debug flag enabled so that Spring can look up the parameter name from the constructor. If you cannot or do not want to compile your code with the debug flag, you can use the @ConstructorProperties JDK annotation to explicitly name your constructor arguments. The sample class would then have to look as follows: Java package examples; public class ExampleBean {   // Fields omitted   @ConstructorProperties({"years", "ultimateAnswer"})   public ExampleBean(int years, String ultimateAnswer) {   this.years = years;   this.ultimateAnswer = ultimateAnswer;   } } Kotlin package examples class ExampleBean @ConstructorProperties("years", "ultimateAnswer") constructor(val years: Int, val ultimateAnswer: String) Setter-based Dependency Injection Setter-based DI is accomplished by the container calling setter methods on your beans after invoking a no-argument constructor or a no-argument static factory method to instantiate your bean. The following example shows a class that can only be dependency-injected by using pure setter injection. This class is conventional Java. It is a POJO that has no dependencies on container specific interfaces, base classes, or annotations. Java public class SimpleMovieLister {   // the SimpleMovieLister has a dependency on the MovieFinder   private MovieFinder movieFinder;   // a setter method so that the Spring container can inject a MovieFinder   public void setMovieFinder(MovieFinder movieFinder) {   this.movieFinder = movieFinder;   }   // business logic that actually uses the injected MovieFinder is omitted... } Kotlin class SimpleMovieLister {   // a late-initialized property so that the Spring container can inject a MovieFinder   lateinit var movieFinder: MovieFinder   // business logic that actually uses the injected MovieFinder is omitted... } The ApplicationContext supports constructor-based and setter-based DI for the beans it manages. It also supports setter-based DI after some dependencies have already been injected through the constructor approach. You configure the dependencies in the form of a BeanDefinition, which you use in conjunction with PropertyEditor instances to convert properties from one format to another. However, most Spring users do not work with these classes directly (that is, programmatically) but rather with XML bean definitions, annotated components (that is, classes annotated with @Component, @Controller, and so forth), or @Bean methods in Java-based @Configuration classes. These sources are then converted internally into instances of BeanDefinition and used to load an entire Spring IoC container instance. Constructor-based or setter-based DI? Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies. Note that use of the @Autowired annotation on a setter method can be used to make the property be a required dependency; however, constructor injection with programmatic validation of arguments is preferable. The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null. Furthermore, constructor-injected components are always returned to the client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns. Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection. Use the DI style that makes the most sense for a particular class. Sometimes, when dealing with third-party classes for which you do not have the source, the choice is made for you. For example, if a third-party class does not expose any setter methods, then constructor injection may be the only available form of DI. Dependency Resolution Process The container performs bean dependency resolution as follows: • The ApplicationContext is created and initialized with configuration metadata that describes all the beans. Configuration metadata can be specified by XML, Java code, or annotations. • For each bean, its dependencies are expressed in the form of properties, constructor arguments, or arguments to the static-factory method (if you use that instead of a normal constructor). These dependencies are provided to the bean, when the bean is actually created. • Each property or constructor argument is an actual definition of the value to set, or a reference to another bean in the container. • Each property or constructor argument that is a value is converted from its specified format to the actual type of that property or constructor argument. By default, Spring can convert a value supplied in string format to all built-in types, such as int, long, String, boolean, and so forth. The Spring container validates the configuration of each bean as the container is created. However, the bean properties themselves are not set until the bean is actually created. Beans that are singleton-scoped and set to be pre-instantiated (the default) are created when the container is created. Scopes are defined in Bean Scopes. Otherwise, the bean is created only when it is requested. Creation of a bean potentially causes a graph of beans to be created, as the bean’s dependencies and its dependencies' dependencies (and so on) are created and assigned. Note that resolution mismatches among those dependencies may show up late — that is, on first creation of the affected bean. Circular dependencies If you use predominantly constructor injection, it is possible to create an unresolvable circular dependency scenario. For example: Class A requires an instance of class B through constructor injection, and class B requires an instance of class A through constructor injection. If you configure beans for classes A and B to be injected into each other, the Spring IoC container detects this circular reference at runtime, and throws a BeanCurrentlyInCreationException. One possible solution is to edit the source code of some classes to be configured by setters rather than constructors. Alternatively, avoid constructor injection and use setter injection only. In other words, although it is not recommended, you can configure circular dependencies with setter injection. Unlike the typical case (with no circular dependencies), a circular dependency between bean A and bean B forces one of the beans to be injected into the other prior to being fully initialized itself (a classic chicken-and-egg scenario). You can generally trust Spring to do the right thing. It detects configuration problems, such as references to non-existent beans and circular dependencies, at container load-time. Spring sets properties and resolves dependencies as late as possible, when the bean is actually created. This means that a Spring container that has loaded correctly can later generate an exception when you request an object if there is a problem creating that object or one of its dependencies — for example, the bean throws an exception as a result of a missing or invalid property. This potentially delayed visibility of some configuration issues is why ApplicationContext implementations by default pre-instantiate singleton beans. At the cost of some upfront time and memory to create these beans before they are actually needed, you discover configuration issues when the ApplicationContext is created, not later. You can still override this default behavior so that singleton beans initialize lazily, rather than being eagerly pre-instantiated. If no circular dependencies exist, when one or more collaborating beans are being injected into a dependent bean, each collaborating bean is totally configured prior to being injected into the dependent bean. This means that, if bean A has a dependency on bean B, the Spring IoC container completely configures bean B prior to invoking the setter method on bean A. In other words, the bean is instantiated (if it is not a pre-instantiated singleton), its dependencies are set, and the relevant lifecycle methods (such as a configured init method or the InitializingBean callback method) are invoked. Examples of Dependency Injection The following example uses XML-based configuration metadata for setter-based DI. A small part of a Spring XML configuration file specifies some bean definitions as follows:               The following example shows the corresponding ExampleBean class: Java public class ExampleBean {   private AnotherBean beanOne;   private YetAnotherBean beanTwo;   private int i;   public void setBeanOne(AnotherBean beanOne) {   this.beanOne = beanOne;   }   public void setBeanTwo(YetAnotherBean beanTwo) {   this.beanTwo = beanTwo;   }   public void setIntegerProperty(int i) {   this.i = i;   } } Kotlin class ExampleBean {   lateinit var beanOne: AnotherBean   lateinit var beanTwo: YetAnotherBean   var i: Int = 0 } In the preceding example, setters are declared to match against the properties specified in the XML file. The following example uses constructor-based DI:               The following example shows the corresponding ExampleBean class: Java public class ExampleBean {   private AnotherBean beanOne;   private YetAnotherBean beanTwo;   private int i;   public ExampleBean(   AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {   this.beanOne = anotherBean;   this.beanTwo = yetAnotherBean;   this.i = i;   } } Kotlin class ExampleBean(   private val beanOne: AnotherBean,   private val beanTwo: YetAnotherBean,   private val i: Int) The constructor arguments specified in the bean definition are used as arguments to the constructor of the ExampleBean. Now consider a variant of this example, where, instead of using a constructor, Spring is told to call a static factory method to return an instance of the object:       The following example shows the corresponding ExampleBean class: Java public class ExampleBean {   // a private constructor   private ExampleBean(...) {   ...   }   // a static factory method; the arguments to this method can be   // considered the dependencies of the bean that is returned,   // regardless of how those arguments are actually used.   public static ExampleBean createInstance (   AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {   ExampleBean eb = new ExampleBean (...);   // some other operations...   return eb;   } } Kotlin class ExampleBean private constructor() {   companion object {   // a static factory method; the arguments to this method can be   // considered the dependencies of the bean that is returned,   // regardless of how those arguments are actually used.   @JvmStatic   fun createInstance(anotherBean: AnotherBean, yetAnotherBean: YetAnotherBean, i: Int): ExampleBean {   val eb = ExampleBean (...)   // some other operations...   return eb   }   } } Arguments to the static factory method are supplied by elements, exactly the same as if a constructor had actually been used. The type of the class being returned by the factory method does not have to be of the same type as the class that contains the static factory method (although, in this example, it is). An instance (non-static) factory method can be used in an essentially identical fashion (aside from the use of the factory-bean attribute instead of the class attribute), so we do not discuss those details here. Dependencies and Configuration in Detail As mentioned in the previous section, you can define bean properties and constructor arguments as references to other managed beans (collaborators) or as values defined inline. Spring’s XML-based configuration metadata supports sub-element types within its and elements for this purpose. Straight Values (Primitives, Strings, and so on) The value attribute of the element specifies a property or constructor argument as a human-readable string representation. Spring’s conversion service is used to convert these values from a String to the actual type of the property or argument. The following example shows various values being set:           The following example uses the p-namespace for even more succinct XML configuration:   The preceding XML is more succinct. However, typos are discovered at runtime rather than design time, unless you use an IDE (such as IntelliJ IDEA or the Spring Tools for Eclipse) that supports automatic property completion when you create bean definitions. Such IDE assistance is highly recommended. You can also configure a java.util.Properties instance, as follows:         jdbc.driver.className=com.mysql.jdbc.Driver   jdbc.url=jdbc:mysql://localhost:3306/mydb     The Spring container converts the text inside the element into a java.util.Properties instance by using the JavaBeans PropertyEditor mechanism. This is a nice shortcut, and is one of a few places where the Spring team do favor the use of the nested element over the value attribute style. The idref element The idref element is simply an error-proof way to pass the id (a string value - not a reference) of another bean in the container to a or element. The following example shows how to use it:       The preceding bean definition snippet is exactly equivalent (at runtime) to the following snippet:   The first form is preferable to the second, because using the idref tag lets the container validate at deployment time that the referenced, named bean actually exists. In the second variation, no validation is performed on the value that is passed to the targetName property of the client bean. Typos are only discovered (with most likely fatal results) when the client bean is actually instantiated. If the client bean is a prototype bean, this typo and the resulting exception may only be discovered long after the container is deployed. The local attribute on the idref element is no longer supported in the 4.0 beans XSD, since it does not provide value over a regular bean reference any more.  Change your existing idref local references to idref bean when upgrading to the 4.0 schema. A common place (at least in versions earlier than Spring 2.0) where the element brings value is in the configuration of AOP interceptors in a ProxyFactoryBean bean definition. Using elements when you specify the interceptor names prevents you from misspelling an interceptor ID. References to Other Beans (Collaborators) The ref element is the final element inside a or definition element. Here, you set the value of the specified property of a bean to be a reference to another bean (a collaborator) managed by the container. The referenced bean is a dependency of the bean whose property is to be set, and it is initialized on demand as needed before the property is set. (If the collaborator is a singleton bean, it may already be initialized by the container.) All references are ultimately a reference to another object. Scoping and validation depend on whether you specify the ID or name of the other object through the bean or parent attribute. Specifying the target bean through the bean attribute of the tag is the most general form and allows creation of a reference to any bean in the same container or parent container, regardless of whether it is in the same XML file. The value of the bean attribute may be the same as the id attribute of the target bean or be the same as one of the values in the name attribute of the target bean. The following example shows how to use a ref element: Specifying the target bean through the parent attribute creates a reference to a bean that is in a parent container of the current container. The value of the parent attribute may be the same as either the id attribute of the target bean or one of the values in the name attribute of the target bean. The target bean must be in a parent container of the current one. You should use this bean reference variant mainly when you have a hierarchy of containers and you want to wrap an existing bean in a parent container with a proxy that has the same name as the parent bean. The following pair of listings shows how to use the parent attribute:           The local attribute on the ref element is no longer supported in the 4.0 beans XSD,  since it does not provide value over a regular bean reference any more. Change your existing ref local references to ref bean when upgrading to the 4.0 schema. Inner Beans A element inside the or elements defines an inner bean, as the following example shows:               An inner bean definition does not require a defined ID or name. If specified, the container does not use such a value as an identifier. The container also ignores the scope flag on creation, because inner beans are always anonymous and are always created with the outer bean. It is not possible to access inner beans independently or to inject them into collaborating beans other than into the enclosing bean. As a corner case, it is possible to receive destruction callbacks from a custom scope — for example, for a request-scoped inner bean contained within a singleton bean. The creation of the inner bean instance is tied to its containing bean, but destruction callbacks let it participate in the request scope’s lifecycle. This is not a common scenario. Inner beans typically simply share their containing bean’s scope. Collections The , , , and elements set the properties and arguments of the Java Collection types List, Set, Map, and Properties, respectively. The following example shows how to use them:         administrator@example.org   support@example.org   development@example.org             a list element followed by a reference                             just some string       The value of a map key or value, or a set value, can also be any of the following elements: bean | ref | idref | list | set | map | props | value | null Collection Merging The Spring container also supports merging collections. An application developer can define a parent , , or element and have child , , or elements inherit and override values from the parent collection. That is, the child collection’s values are the result of merging the elements of the parent and child collections, with the child’s collection elements overriding values specified in the parent collection. This section on merging discusses the parent-child bean mechanism. Readers unfamiliar with parent and child bean definitions may wish to read the relevant section before continuing. The following example demonstrates collection merging:         administrator@example.com   support@example.com                 sales@example.com   support@example.co.uk       Notice the use of the merge=true attribute on the element of the adminEmails property of the child bean definition. When the child bean is resolved and instantiated by the container, the resulting instance has an adminEmails Properties collection that contains the result of merging the child’s adminEmails collection with the parent’s adminEmails collection. The following listing shows the result: administrator=administrator@example.com sales=sales@example.com support=support@example.co.uk The child Properties collection’s value set inherits all property elements from the parent , and the child’s value for the support value overrides the value in the parent collection. This merging behavior applies similarly to the , , and collection types. In the specific case of the element, the semantics associated with the List collection type (that is, the notion of an ordered collection of values) is maintained. The parent’s values precede all of the child list’s values. In the case of the Map, Set, and Properties collection types, no ordering exists. Hence, no ordering semantics are in effect for the collection types that underlie the associated Map, Set, and Properties implementation types that the container uses internally. Limitations of Collection Merging You cannot merge different collection types (such as a Map and a List). If you do attempt to do so, an appropriate Exception is thrown. The merge attribute must be specified on the lower, inherited, child definition. Specifying the merge attribute on a parent collection definition is redundant and does not result in the desired merging. Strongly-typed collection Thanks to Java’s support for generic types, you can use strongly typed collections. That is, it is possible to declare a Collection type such that it can only contain (for example) String elements. If you use Spring to dependency-inject a strongly-typed Collection into a bean, you can take advantage of Spring’s type-conversion support such that the elements of your strongly-typed Collection instances are converted to the appropriate type prior to being added to the Collection. The following Java class and bean definition show how to do so: Java public class SomeClass {   private Map accounts;   public void setAccounts(Map accounts) {   this.accounts = accounts;   } } Kotlin class SomeClass {   lateinit var accounts: Map }                   When the accounts property of the something bean is prepared for injection, the generics information about the element type of the strongly-typed Map is available by reflection. Thus, Spring’s type conversion infrastructure recognizes the various value elements as being of type Float, and the string values (9.99, 2.75, and 3.99) are converted into an actual Float type. Null and Empty String Values Spring treats empty arguments for properties and the like as empty Strings. The following XML- based configuration metadata snippet sets the email property to the empty String value ("").   The preceding example is equivalent to the following Java code: Java exampleBean.setEmail(""); Kotlin exampleBean.email = "" The element handles null values. The following listing shows an example:       The preceding configuration is equivalent to the following Java code: Java exampleBean.setEmail(null); Kotlin exampleBean.email = null XML Shortcut with the p-namespace The p-namespace lets you use the bean element’s attributes (instead of nested elements) to describe your property values collaborating beans, or both. Spring supports extensible configuration formats with namespaces, which are based on an XML Schema definition. The beans configuration format discussed in this chapter is defined in an XML Schema document. However, the p-namespace is not defined in an XSD file and exists only in the core of Spring. The following example shows two XML snippets (the first uses standard XML format and the second uses the p-namespace) that resolve to the same result:         The example shows an attribute in the p-namespace called email in the bean definition. This tells Spring to include a property declaration. As previously mentioned, the p-namespace does not have a schema definition, so you can set the name of the attribute to the property name. This next example includes two more bean definitions that both have a reference to another bean:                 This example includes not only a property value using the p-namespace but also uses a special format to declare property references. Whereas the first bean definition uses to create a reference from bean john to bean jane, the second bean definition uses p:spouse-ref="jane" as an attribute to do the exact same thing. In this case, spouse is the property name, whereas the -ref part indicates that this is not a straight value but rather a reference to another bean. The p-namespace is not as flexible as the standard XML format. For example, the format for declaring property references clashes with properties that end in Ref,  whereas the standard XML format does not. We recommend that you choose your approach carefully and communicate this to your team members to avoid producing XML documents that use all three approaches at the same time. XML Shortcut with the c-namespace Similar to the XML Shortcut with the p-namespace, the c-namespace, introduced in Spring 3.1, allows inlined attributes for configuring the constructor arguments rather then nested constructor- arg elements. The following example uses the c: namespace to do the same thing as the from Constructor-based Dependency Injection:                     The c: namespace uses the same conventions as the p: one (a trailing -ref for bean references) for setting the constructor arguments by their names. Similarly, it needs to be declared in the XML file even though it is not defined in an XSD schema (it exists inside the Spring core). For the rare cases where the constructor argument names are not available (usually if the bytecode was compiled without debugging information), you can use fallback to the argument indexes, as follows: Due to the XML grammar, the index notation requires the presence of the leading _, as XML attribute names cannot start with a number (even though some IDEs  allow it). A corresponding index notation is also available for elements but not commonly used since the plain order of declaration is usually sufficient there. In practice, the constructor resolution mechanism is quite efficient in matching arguments, so unless you really need to, we recommend using the name notation throughout your configuration. Compound Property Names You can use compound or nested property names when you set bean properties, as long as all components of the path except the final property name are not null. Consider the following bean definition:   The something bean has a fred property, which has a bob property, which has a sammy property, and that final sammy property is being set to a value of 123. In order for this to work, the fred property of something and the bob property of fred must not be null after the bean is constructed. Otherwise, a NullPointerException is thrown. Using depends-on If a bean is a dependency of another bean, that usually means that one bean is set as a property of another. Typically you accomplish this with the element in XML-based configuration metadata. However, sometimes dependencies between beans are less direct. An example is when a static initializer in a class needs to be triggered, such as for database driver registration. The depends-on attribute can explicitly force one or more beans to be initialized before the bean using this element is initialized. The following example uses the depends-on attribute to express a dependency on a single bean: To express a dependency on multiple beans, supply a list of bean names as the value of the depends- on attribute (commas, whitespace, and semicolons are valid delimiters):   The depends-on attribute can specify both an initialization-time dependency and, in the case of singleton beans only, a corresponding destruction-time dependency.  Dependent beans that define a depends-on relationship with a given bean are destroyed first, prior to the given bean itself being destroyed. Thus, depends-on can also control shutdown order. Lazy-initialized Beans By default, ApplicationContext implementations eagerly create and configure all singleton beans as part of the initialization process. Generally, this pre-instantiation is desirable, because errors in the configuration or surrounding environment are discovered immediately, as opposed to hours or even days later. When this behavior is not desirable, you can prevent pre-instantiation of a singleton bean by marking the bean definition as being lazy-initialized. A lazy-initialized bean tells the IoC container to create a bean instance when it is first requested, rather than at startup. In XML, this behavior is controlled by the lazy-init attribute on the element, as the following example shows: When the preceding configuration is consumed by an ApplicationContext, the lazy bean is not eagerly pre-instantiated when the ApplicationContext starts, whereas the not.lazy bean is eagerly pre-instantiated. However, when a lazy-initialized bean is a dependency of a singleton bean that is not lazy- initialized, the ApplicationContext creates the lazy-initialized bean at startup, because it must satisfy the singleton’s dependencies. The lazy-initialized bean is injected into a singleton bean elsewhere that is not lazy-initialized. You can also control lazy-initialization at the container level by using the default-lazy-init attribute on the element, as the following example shows:   Autowiring Collaborators The Spring container can autowire relationships between collaborating beans. You can let Spring resolve collaborators (other beans) automatically for your bean by inspecting the contents of the ApplicationContext. Autowiring has the following advantages: • Autowiring can significantly reduce the need to specify properties or constructor arguments. (Other mechanisms such as a bean template discussed elsewhere in this chapter are also valuable in this regard.) • Autowiring can update a configuration as your objects evolve. For example, if you need to add a dependency to a class, that dependency can be satisfied automatically without you needing to modify the configuration. Thus autowiring can be especially useful during development, without negating the option of switching to explicit wiring when the code base becomes more stable. When using XML-based configuration metadata (see Dependency Injection), you can specify the autowire mode for a bean definition with the autowire attribute of the element. The autowiring functionality has four modes. You specify autowiring per bean and can thus choose which ones to autowire. The following table describes the four autowiring modes: Table 2. Autowiring modes Mode Explanation no (Default) No autowiring. Bean references must be defined by ref elements. Changing the default setting is not recommended for larger deployments, because specifying collaborators explicitly gives greater control and clarity. To some extent, it documents the structure of a system. byName Autowiring by property name. Spring looks for a bean with the same name as the property that needs to be autowired. For example, if a bean definition is set to autowire by name and it contains a master property (that is, it has a setMaster(..) method), Spring looks for a bean definition named master and uses it to set the property. byType Lets a property be autowired if exactly one bean of the property type exists in the container. If more than one exists, a fatal exception is thrown, which indicates that you may not use byType autowiring for that bean. If there are no matching beans, nothing happens (the property is not set). constructor Analogous to byType but applies to constructor arguments. If there is not exactly one bean of the constructor argument type in the container, a fatal error is raised. With byType or constructor autowiring mode, you can wire arrays and typed collections. In such cases, all autowire candidates within the container that match the expected type are provided to satisfy the dependency. You can autowire strongly-typed Map instances if the expected key type is String. An autowired Map instance’s values consist of all bean instances that match the expected type, and the Map instance’s keys contain the corresponding bean names. Limitations and Disadvantages of Autowiring Autowiring works best when it is used consistently across a project. If autowiring is not used in general, it might be confusing to developers to use it to wire only one or two bean definitions. Consider the limitations and disadvantages of autowiring: • Explicit dependencies in property and constructor-arg settings always override autowiring. You cannot autowire simple properties such as primitives, Strings, and Classes (and arrays of such simple properties). This limitation is by-design. • Autowiring is less exact than explicit wiring. Although, as noted in the earlier table, Spring is careful to avoid guessing in case of ambiguity that might have unexpected results. The relationships between your Spring-managed objects are no longer documented explicitly. • Wiring information may not be available to tools that may generate documentation from a Spring container. • Multiple bean definitions within the container may match the type specified by the setter method or constructor argument to be autowired. For arrays, collections, or Map instances, this is not necessarily a problem. However, for dependencies that expect a single value, this ambiguity is not arbitrarily resolved. If no unique bean definition is available, an exception is thrown. In the latter scenario, you have several options: • Abandon autowiring in favor of explicit wiring. • Avoid autowiring for a bean definition by setting its autowire-candidate attributes to false, as described in the next section. • Designate a single bean definition as the primary candidate by setting the primary attribute of its element to true. • Implement the more fine-grained control available with annotation-based configuration, as described in Annotation-based Container Configuration. Excluding a Bean from Autowiring On a per-bean basis, you can exclude a bean from autowiring. In Spring’s XML format, set the autowire-candidate attribute of the element to false. The container makes that specific bean definition unavailable to the autowiring infrastructure (including annotation style configurations such as @Autowired). The autowire-candidate attribute is designed to only affect type-based autowiring. It does not affect explicit references by name, which get resolved even if the  specified bean is not marked as an autowire candidate. As a consequence, autowiring by name nevertheless injects a bean if the name matches. You can also limit autowire candidates based on pattern-matching against bean names. The top- level element accepts one or more patterns within its default-autowire-candidates attribute. For example, to limit autowire candidate status to any bean whose name ends with Repository, provide a value of *Repository. To provide multiple patterns, define them in a comma- separated list. An explicit value of true or false for a bean definition’s autowire-candidate attribute always takes precedence. For such beans, the pattern matching rules do not apply. These techniques are useful for beans that you never want to be injected into other beans by autowiring. It does not mean that an excluded bean cannot itself be configured by using autowiring. Rather, the bean itself is not a candidate for autowiring other beans. Method Injection In most application scenarios, most beans in the container are singletons. When a singleton bean needs to collaborate with another singleton bean or a non-singleton bean needs to collaborate with another non-singleton bean, you typically handle the dependency by defining one bean as a property of the other. A problem arises when the bean lifecycles are different. Suppose singleton bean A needs to use non-singleton (prototype) bean B, perhaps on each method invocation on A. The container creates the singleton bean A only once, and thus only gets one opportunity to set the properties. The container cannot provide bean A with a new instance of bean B every time one is needed. A solution is to forego some inversion of control. You can make bean A aware of the container by implementing the ApplicationContextAware interface, and by making a getBean("B") call to the container ask for (a typically new) bean B instance every time bean A needs it. The following example shows this approach: Java // a class that uses a stateful Command-style class to perform some processing package fiona.apple; // Spring-API imports import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class CommandManager implements ApplicationContextAware {   private ApplicationContext applicationContext;   public Object process(Map commandState) {   // grab a new instance of the appropriate Command   Command command = createCommand();   // set the state on the (hopefully brand new) Command instance   command.setState(commandState);   return command.execute();   }   protected Command createCommand() {   // notice the Spring API dependency!   return this.applicationContext.getBean("command", Command.class);   }   public void setApplicationContext(   ApplicationContext applicationContext) throws BeansException {   this.applicationContext = applicationContext;   } } Kotlin // a class that uses a stateful Command-style class to perform some processing package fiona.apple // Spring-API imports import org.springframework.context.ApplicationContext import org.springframework.context.ApplicationContextAware class CommandManager : ApplicationContextAware {   private lateinit var applicationContext: ApplicationContext   fun process(commandState: Map<*, *>): Any {   // grab a new instance of the appropriate Command   val command = createCommand()   // set the state on the (hopefully brand new) Command instance   command.state = commandState   return command.execute()   }   // notice the Spring API dependency!   protected fun createCommand() =   applicationContext.getBean("command", Command::class.java)   override fun setApplicationContext(applicationContext: ApplicationContext) {   this.applicationContext = applicationContext   } } The preceding is not desirable, because the business code is aware of and coupled to the Spring Framework. Method Injection, a somewhat advanced feature of the Spring IoC container, lets you handle this use case cleanly. You can read more about the motivation for Method Injection in this blog entry. Lookup Method Injection Lookup method injection is the ability of the container to override methods on container-managed beans and return the lookup result for another named bean in the container. The lookup typically involves a prototype bean, as in the scenario described in the preceding section. The Spring Framework implements this method injection by using bytecode generation from the CGLIB library to dynamically generate a subclass that overrides the method. • For this dynamic subclassing to work, the class that the Spring bean container subclasses cannot be final, and the method to be overridden cannot be final, either. • Unit-testing a class that has an abstract method requires you to subclass the class yourself and to supply a stub implementation of the abstract method.  • Concrete methods are also necessary for component scanning, which requires concrete classes to pick up. • A further key limitation is that lookup methods do not work with factory methods and in particular not with @Bean methods in configuration classes, since, in that case, the container is not in charge of creating the instance and therefore cannot create a runtime-generated subclass on the fly. In the case of the CommandManager class in the previous code snippet, the Spring container dynamically overrides the implementation of the createCommand() method. The CommandManager class does not have any Spring dependencies, as the reworked example shows: Java package fiona.apple; // no more Spring imports! public abstract class CommandManager {   public Object process(Object commandState) {   // grab a new instance of the appropriate Command interface   Command command = createCommand();   // set the state on the (hopefully brand new) Command instance   command.setState(commandState);   return command.execute();   }   // okay... but where is the implementation of this method?   protected abstract Command createCommand(); } Kotlin package fiona.apple // no more Spring imports! abstract class CommandManager {   fun process(commandState: Any): Any {   // grab a new instance of the appropriate Command interface   val command = createCommand()   // set the state on the (hopefully brand new) Command instance   command.state = commandState   return command.execute()   }   // okay... but where is the implementation of this method?   protected abstract fun createCommand(): Command } In the client class that contains the method to be injected (the CommandManager in this case), the method to be injected requires a signature of the following form: [abstract] theMethodName(no-arguments); If the method is abstract, the dynamically-generated subclass implements the method. Otherwise, the dynamically-generated subclass overrides the concrete method defined in the original class. Consider the following example:     The bean identified as commandManager calls its own createCommand() method whenever it needs a new instance of the myCommand bean. You must be careful to deploy the myCommand bean as a prototype if that is actually what is needed. If it is a singleton, the same instance of the myCommand bean is returned each time. Alternatively, within the annotation-based component model, you can declare a lookup method through the @Lookup annotation, as the following example shows: Java public abstract class CommandManager {   public Object process(Object commandState) {   Command command = createCommand();   command.setState(commandState);   return command.execute();   }   @Lookup("myCommand")   protected abstract Command createCommand(); } Kotlin abstract class CommandManager {   fun process(commandState: Any): Any {   val command = createCommand()   command.state = commandState   return command.execute()   }   @Lookup("myCommand")   protected abstract fun createCommand(): Command } Or, more idiomatically, you can rely on the target bean getting resolved against the declared return type of the lookup method: Java public abstract class CommandManager {   public Object process(Object commandState) {   Command command = createCommand();   command.setState(commandState);   return command.execute();   }   @Lookup   protected abstract Command createCommand(); } Kotlin abstract class CommandManager {   fun process(commandState: Any): Any {   val command = createCommand()   command.state = commandState   return command.execute()   }   @Lookup   protected abstract fun createCommand(): Command } Note that you should typically declare such annotated lookup methods with a concrete stub implementation, in order for them to be compatible with Spring’s component scanning rules where abstract classes get ignored by default. This limitation does not apply to explicitly registered or explicitly imported bean classes. Another way of accessing differently scoped target beans is an ObjectFactory/ Provider injection point. See Scoped Beans as Dependencies.  You may also find the ServiceLocatorFactoryBean (in the org.springframework.beans.factory.config package) to be useful. Arbitrary Method Replacement A less useful form of method injection than lookup method injection is the ability to replace arbitrary methods in a managed bean with another method implementation. You can safely skip the rest of this section until you actually need this functionality. With XML-based configuration metadata, you can use the replaced-method element to replace an existing method implementation with another, for a deployed bean. Consider the following class, which has a method called computeValue that we want to override: Java public class MyValueCalculator {   public String computeValue(String input) {   // some real code...   }   // some other methods... } Kotlin class MyValueCalculator {   fun computeValue(input: String): String {   // some real code...   }   // some other methods... } A class that implements the org.springframework.beans.factory.support.MethodReplacer interface provides the new method definition, as the following example shows: Java /**  * meant to be used to override the existing computeValue(String)  * implementation in MyValueCalculator  */ public class ReplacementComputeValue implements MethodReplacer {   public Object reimplement(Object o, Method m, Object[] args) throws Throwable {   // get the input value, work with it, and return a computed result   String input = (String) args[0];   ...   return ...;   } } Kotlin /**  * meant to be used to override the existing computeValue(String)  * implementation in MyValueCalculator  */ class ReplacementComputeValue : MethodReplacer {   override fun reimplement(obj: Any, method: Method, args: Array): Any {   // get the input value, work with it, and return a computed result   val input = args[0] as String;   ...   return ...;   } } The bean definition to deploy the original class and specify the method override would resemble the following example:       String   You can use one or more elements within the element to indicate the method signature of the method being overridden. The signature for the arguments is necessary only if the method is overloaded and multiple variants exist within the class. For convenience, the type string for an argument may be a substring of the fully qualified type name. For example, the following all match java.lang.String: java.lang.String String Str Because the number of arguments is often enough to distinguish between each possible choice, this shortcut can save a lot of typing, by letting you type only the shortest string that matches an argument type. 2.1.5. Bean Scopes When you create a bean definition, you create a recipe for creating actual instances of the class defined by that bean definition. The idea that a bean definition is a recipe is important, because it means that, as with a class, you can create many object instances from a single recipe. You can control not only the various dependencies and configuration values that are to be plugged into an object that is created from a particular bean definition but also control the scope of the objects created from a particular bean definition. This approach is powerful and flexible, because you can choose the scope of the objects you create through configuration instead of having to bake in the scope of an object at the Java class level. Beans can be defined to be deployed in one of a number of scopes. The Spring Framework supports six scopes, four of which are available only if you use a web-aware ApplicationContext. You can also create a custom scope. The following table describes the supported scopes: Table 3. Bean scopes Scope Description singleton (Default) Scopes a single bean definition to a single object instance for each Spring IoC container. prototype Scopes a single bean definition to any number of object instances. Scope Description request Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext. session Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext. application Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext. websocket Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext. As of Spring 3.0, a thread scope is available but is not registered by default. For  more information, see the documentation for SimpleThreadScope. For instructions on how to register this or any other custom scope, see Using a Custom Scope. The Singleton Scope Only one shared instance of a singleton bean is managed, and all requests for beans with an ID or IDs that match that bean definition result in that one specific bean instance being returned by the Spring container. To put it another way, when you define a bean definition and it is scoped as a singleton, the Spring IoC container creates exactly one instance of the object defined by that bean definition. This single instance is stored in a cache of such singleton beans, and all subsequent requests and references for that named bean return the cached object. The following image shows how the singleton scope works: Spring’s concept of a singleton bean differs from the singleton pattern as defined in the Gang of Four (GoF) patterns book. The GoF singleton hard-codes the scope of an object such that one and only one instance of a particular class is created per ClassLoader. The scope of the Spring singleton is best described as being per-container and per-bean. This means that, if you define one bean for a particular class in a single Spring container, the Spring container creates one and only one instance of the class defined by that bean definition. The singleton scope is the default scope in Spring. To define a bean as a singleton in XML, you can define a bean as shown in the following example: The Prototype Scope The non-singleton prototype scope of bean deployment results in the creation of a new bean instance every time a request for that specific bean is made. That is, the bean is injected into another bean or you request it through a getBean() method call on the container. As a rule, you should use the prototype scope for all stateful beans and the singleton scope for stateless beans. The following diagram illustrates the Spring prototype scope: (A data access object (DAO) is not typically configured as a prototype, because a typical DAO does not hold any conversational state. It was easier for us to reuse the core of the singleton diagram.) The following example defines a bean as a prototype in XML: In contrast to the other scopes, Spring does not manage the complete lifecycle of a prototype bean. The container instantiates, configures, and otherwise assembles a prototype object and hands it to the client, with no further record of that prototype instance. Thus, although initialization lifecycle callback methods are called on all objects regardless of scope, in the case of prototypes, configured destruction lifecycle callbacks are not called. The client code must clean up prototype-scoped objects and release expensive resources that the prototype beans hold. To get the Spring container to release resources held by prototype-scoped beans, try using a custom bean post-processor, which holds a reference to beans that need to be cleaned up. In some respects, the Spring container’s role in regard to a prototype-scoped bean is a replacement for the Java new operator. All lifecycle management past that point must be handled by the client. (For details on the lifecycle of a bean in the Spring container, see Lifecycle Callbacks.) Singleton Beans with Prototype-bean Dependencies When you use singleton-scoped beans with dependencies on prototype beans, be aware that dependencies are resolved at instantiation time. Thus, if you dependency-inject a prototype-scoped bean into a singleton-scoped bean, a new prototype bean is instantiated and then dependency- injected into the singleton bean. The prototype instance is the sole instance that is ever supplied to the singleton-scoped bean. However, suppose you want the singleton-scoped bean to acquire a new instance of the prototype- scoped bean repeatedly at runtime. You cannot dependency-inject a prototype-scoped bean into your singleton bean, because that injection occurs only once, when the Spring container instantiates the singleton bean and resolves and injects its dependencies. If you need a new instance of a prototype bean at runtime more than once, see Method Injection. Request, Session, Application, and WebSocket Scopes The request, session, application, and websocket scopes are available only if you use a web-aware Spring ApplicationContext implementation (such as XmlWebApplicationContext). If you use these scopes with regular Spring IoC containers, such as the ClassPathXmlApplicationContext, an IllegalStateException that complains about an unknown bean scope is thrown. Initial Web Configuration To support the scoping of beans at the request, session, application, and websocket levels (web- scoped beans), some minor initial configuration is required before you define your beans. (This initial setup is not required for the standard scopes: singleton and prototype.) How you accomplish this initial setup depends on your particular Servlet environment. If you access scoped beans within Spring Web MVC, in effect, within a request that is processed by the Spring DispatcherServlet, no special setup is necessary. DispatcherServlet already exposes all relevant state. If you use a Servlet web container, with requests processed outside of Spring’s DispatcherServlet (for example, when using JSF or Struts), you need to register the org.springframework.web.context.request.RequestContextListener ServletRequestListener. This can be done programmatically by using the WebApplicationInitializer interface. Alternatively, add the following declaration to your web application’s web.xml file:   ...       org.springframework.web.context.request.RequestContextListener       ... Alternatively, if there are issues with your listener setup, consider using Spring’s RequestContextFilter. The filter mapping depends on the surrounding web application configuration, so you have to change it as appropriate. The following listing shows the filter part of a web application:   ...     requestContextFilter   org.springframework.web.filter.RequestContextFilter       requestContextFilter   /*     ... DispatcherServlet, RequestContextListener, and RequestContextFilter all do exactly the same thing, namely bind the HTTP request object to the Thread that is servicing that request. This makes beans that are request- and session-scoped available further down the call chain. Request scope Consider the following XML configuration for a bean definition: The Spring container creates a new instance of the LoginAction bean by using the loginAction bean definition for each and every HTTP request. That is, the loginAction bean is scoped at the HTTP request level. You can change the internal state of the instance that is created as much as you want, because other instances created from the same loginAction bean definition do not see these changes in state. They are particular to an individual request. When the request completes processing, the bean that is scoped to the request is discarded. When using annotation-driven components or Java configuration, the @RequestScope annotation can be used to assign a component to the request scope. The following example shows how to do so: Java @RequestScope @Component public class LoginAction {   // ... } Kotlin @RequestScope @Component class LoginAction {   // ... } Session Scope Consider the following XML configuration for a bean definition: The Spring container creates a new instance of the UserPreferences bean by using the userPreferences bean definition for the lifetime of a single HTTP Session. In other words, the userPreferences bean is effectively scoped at the HTTP Session level. As with request-scoped beans, you can change the internal state of the instance that is created as much as you want, knowing that other HTTP Session instances that are also using instances created from the same userPreferences bean definition do not see these changes in state, because they are particular to an individual HTTP Session. When the HTTP Session is eventually discarded, the bean that is scoped to that particular HTTP Session is also discarded. When using annotation-driven components or Java configuration, you can use the @SessionScope annotation to assign a component to the session scope. Java @SessionScope @Component public class UserPreferences {   // ... } Kotlin @SessionScope @Component class UserPreferences {   // ... } Application Scope Consider the following XML configuration for a bean definition: The Spring container creates a new instance of the AppPreferences bean by using the appPreferences bean definition once for the entire web application. That is, the appPreferences bean is scoped at the ServletContext level and stored as a regular ServletContext attribute. This is somewhat similar to a Spring singleton bean but differs in two important ways: It is a singleton per ServletContext, not per Spring ApplicationContext (for which there may be several in any given web application), and it is actually exposed and therefore visible as a ServletContext attribute. When using annotation-driven components or Java configuration, you can use the @ApplicationScope annotation to assign a component to the application scope. The following example shows how to do so: Java @ApplicationScope @Component public class AppPreferences {   // ... } Kotlin @ApplicationScope @Component class AppPreferences {   // ... } WebSocket Scope WebSocket scope is associated with the lifecycle of a WebSocket session and applies to STOMP over WebSocket applications, see WebSocket scope for more details. Scoped Beans as Dependencies The Spring IoC container manages not only the instantiation of your objects (beans), but also the wiring up of collaborators (or dependencies). If you want to inject (for example) an HTTP request- scoped bean into another bean of a longer-lived scope, you may choose to inject an AOP proxy in place of the scoped bean. That is, you need to inject a proxy object that exposes the same public interface as the scoped object but that can also retrieve the real target object from the relevant scope (such as an HTTP request) and delegate method calls onto the real object. You may also use between beans that are scoped as singleton, with the reference then going through an intermediate proxy that is serializable and therefore able to re-obtain the target singleton bean on deserialization. When declaring against a bean of scope prototype, every method call on the shared proxy leads to the creation of a new target instance to which the call is then being forwarded. Also, scoped proxies are not the only way to access beans from shorter scopes in a lifecycle-safe fashion. You may also declare your injection point (that is, the  constructor or setter argument or autowired field) as ObjectFactory, allowing for a getObject() call to retrieve the current instance on demand every time it is needed — without holding on to the instance or storing it separately. As an extended variant, you may declare ObjectProvider which delivers several additional access variants, including getIfAvailable and getIfUnique. The JSR-330 variant of this is called Provider and is used with a Provider declaration and a corresponding get() call for every retrieval attempt. See here for more details on JSR-330 overall. The configuration in the following example is only one line, but it is important to understand the “why” as well as the “how” behind it:         ①             ① The line that defines the proxy. To create such a proxy, you insert a child element into a scoped bean definition (see Choosing the Type of Proxy to Create and XML Schema-based configuration). Why do definitions of beans scoped at the request, session and custom-scope levels require the element? Consider the following singleton bean definition and contrast it with what you need to define for the aforementioned scopes (note that the following userPreferences bean definition as it stands is incomplete):   In the preceding example, the singleton bean (userManager) is injected with a reference to the HTTP Session-scoped bean (userPreferences). The salient point here is that the userManager bean is a singleton: it is instantiated exactly once per container, and its dependencies (in this case only one, the userPreferences bean) are also injected only once. This means that the userManager bean operates only on the exact same userPreferences object (that is, the one with which it was originally injected). This is not the behavior you want when injecting a shorter-lived scoped bean into a longer-lived scoped bean (for example, injecting an HTTP Session-scoped collaborating bean as a dependency into singleton bean). Rather, you need a single userManager object, and, for the lifetime of an HTTP Session, you need a userPreferences object that is specific to the HTTP Session. Thus, the container creates an object that exposes the exact same public interface as the UserPreferences class (ideally an object that is a UserPreferences instance), which can fetch the real UserPreferences object from the scoping mechanism (HTTP request, Session, and so forth). The container injects this proxy object into the userManager bean, which is unaware that this UserPreferences reference is a proxy. In this example, when a UserManager instance invokes a method on the dependency-injected UserPreferences object, it is actually invoking a method on the proxy. The proxy then fetches the real UserPreferences object from (in this case) the HTTP Session and delegates the method invocation onto the retrieved real UserPreferences object. Thus, you need the following (correct and complete) configuration when injecting request- and session-scoped beans into collaborating objects, as the following example shows:     Choosing the Type of Proxy to Create By default, when the Spring container creates a proxy for a bean that is marked up with the element, a CGLIB-based class proxy is created. CGLIB proxies intercept only public method calls! Do not call non-public methods  on such a proxy. They are not delegated to the actual scoped target object. Alternatively, you can configure the Spring container to create standard JDK interface-based proxies for such scoped beans, by specifying false for the value of the proxy-target-class attribute of the element. Using JDK interface-based proxies means that you do not need additional libraries in your application classpath to affect such proxying. However, it also means that the class of the scoped bean must implement at least one interface and that all collaborators into which the scoped bean is injected must reference the bean through one of its interfaces. The following example shows a proxy based on an interface:     For more detailed information about choosing class-based or interface-based proxying, see Proxying Mechanisms. Custom Scopes The bean scoping mechanism is extensible. You can define your own scopes or even redefine existing scopes, although the latter is considered bad practice and you cannot override the built-in singleton and prototype scopes. Creating a Custom Scope To integrate your custom scopes into the Spring container, you need to implement the org.springframework.beans.factory.config.Scope interface, which is described in this section. For an idea of how to implement your own scopes, see the Scope implementations that are supplied with the Spring Framework itself and the Scope javadoc, which explains the methods you need to implement in more detail. The Scope interface has four methods to get objects from the scope, remove them from the scope, and let them be destroyed. The session scope implementation, for example, returns the session-scoped bean (if it does not exist, the method returns a new instance of the bean, after having bound it to the session for future reference). The following method returns the object from the underlying scope: Java Object get(String name, ObjectFactory objectFactory) Kotlin fun get(name: String, objectFactory: ObjectFactory<*>): Any The session scope implementation, for example, removes the session-scoped bean from the underlying session. The object should be returned, but you can return null if the object with the specified name is not found. The following method removes the object from the underlying scope: Java Object remove(String name) Kotlin fun remove(name: String): Any The following method registers a callback that the scope should invoke when it is destroyed or when the specified object in the scope is destroyed: Java void registerDestructionCallback(String name, Runnable destructionCallback) Kotlin fun registerDestructionCallback(name: String, destructionCallback: Runnable) See the javadoc or a Spring scope implementation for more information on destruction callbacks. The following method obtains the conversation identifier for the underlying scope: Java String getConversationId() Kotlin fun getConversationId(): String This identifier is different for each scope. For a session scoped implementation, this identifier can be the session identifier. Using a Custom Scope After you write and test one or more custom Scope implementations, you need to make the Spring container aware of your new scopes. The following method is the central method to register a new Scope with the Spring container: Java void registerScope(String scopeName, Scope scope); Kotlin fun registerScope(scopeName: String, scope: Scope) This method is declared on the ConfigurableBeanFactory interface, which is available through the BeanFactory property on most of the concrete ApplicationContext implementations that ship with Spring. The first argument to the registerScope(..) method is the unique name associated with a scope. Examples of such names in the Spring container itself are singleton and prototype. The second argument to the registerScope(..) method is an actual instance of the custom Scope implementation that you wish to register and use. Suppose that you write your custom Scope implementation, and then register it as shown in the next example. The next example uses SimpleThreadScope, which is included with Spring but is not  registered by default. The instructions would be the same for your own custom Scope implementations. Java Scope threadScope = new SimpleThreadScope(); beanFactory.registerScope("thread", threadScope); Kotlin val threadScope = SimpleThreadScope() beanFactory.registerScope("thread", threadScope) You can then create bean definitions that adhere to the scoping rules of your custom Scope, as follows: With a custom Scope implementation, you are not limited to programmatic registration of the scope. You can also do the Scope registration declaratively, by using the CustomScopeConfigurer class, as the following example shows:                                 When you place within a declaration for a FactoryBean  implementation, it is the factory bean itself that is scoped, not the object returned from getObject(). 2.1.6. Customizing the Nature of a Bean The Spring Framework provides a number of interfaces you can use to customize the nature of a bean. This section groups them as follows: • Lifecycle Callbacks • ApplicationContextAware and BeanNameAware • Other Aware Interfaces Lifecycle Callbacks To interact with the container’s management of the bean lifecycle, you can implement the Spring InitializingBean and DisposableBean interfaces. The container calls afterPropertiesSet() for the former and destroy() for the latter to let the bean perform certain actions upon initialization and destruction of your beans. The JSR-250 @PostConstruct and @PreDestroy annotations are generally considered best practice for receiving lifecycle callbacks in a modern Spring application. Using these annotations means that your beans are not coupled to Spring-specific  interfaces. For details, see Using @PostConstruct and @PreDestroy. If you do not want to use the JSR-250 annotations but you still want to remove coupling, consider init-method and destroy-method bean definition metadata. Internally, the Spring Framework uses BeanPostProcessor implementations to process any callback interfaces it can find and call the appropriate methods. If you need custom features or other lifecycle behavior Spring does not by default offer, you can implement a BeanPostProcessor yourself. For more information, see Container Extension Points. In addition to the initialization and destruction callbacks, Spring-managed objects may also implement the Lifecycle interface so that those objects can participate in the startup and shutdown process, as driven by the container’s own lifecycle. The lifecycle callback interfaces are described in this section. Initialization Callbacks The org.springframework.beans.factory.InitializingBean interface lets a bean perform initialization work after the container has set all necessary properties on the bean. The InitializingBean interface specifies a single method: void afterPropertiesSet() throws Exception; We recommend that you do not use the InitializingBean interface, because it unnecessarily couples the code to Spring. Alternatively, we suggest using the @PostConstruct annotation or specifying a POJO initialization method. In the case of XML-based configuration metadata, you can use the init- method attribute to specify the name of the method that has a void no-argument signature. With Java configuration, you can use the initMethod attribute of @Bean. See Receiving Lifecycle Callbacks. Consider the following example: Java public class ExampleBean {   public void init() {   // do some initialization work   } } Kotlin class ExampleBean {   fun init() {   // do some initialization work   } } The preceding example has almost exactly the same effect as the following example (which consists of two listings): Java public class AnotherExampleBean implements InitializingBean {   @Override   public void afterPropertiesSet() {   // do some initialization work   } } Kotlin class AnotherExampleBean : InitializingBean {   override fun afterPropertiesSet() {   // do some initialization work   } } However, the first of the two preceding examples does not couple the code to Spring. Destruction Callbacks Implementing the org.springframework.beans.factory.DisposableBean interface lets a bean get a callback when the container that contains it is destroyed. The DisposableBean interface specifies a single method: void destroy() throws Exception; We recommend that you do not use the DisposableBean callback interface, because it unnecessarily couples the code to Spring. Alternatively, we suggest using the @PreDestroy annotation or specifying a generic method that is supported by bean definitions. With XML-based configuration metadata, you can use the destroy-method attribute on the . With Java configuration, you can use the destroyMethod attribute of @Bean. See Receiving Lifecycle Callbacks. Consider the following definition: Java public class ExampleBean {   public void cleanup() {   // do some destruction work (like releasing pooled connections)   } } Kotlin class ExampleBean {   fun cleanup() {   // do some destruction work (like releasing pooled connections)   } } The preceding definition has almost exactly the same effect as the following definition: Java public class AnotherExampleBean implements DisposableBean {   @Override   public void destroy() {   // do some destruction work (like releasing pooled connections)   } } Kotlin class AnotherExampleBean : DisposableBean {   override fun destroy() {   // do some destruction work (like releasing pooled connections)   } } However, the first of the two preceding definitions does not couple the code to Spring. You can assign the destroy-method attribute of a element a special (inferred) value, which instructs Spring to automatically detect a public close or shutdown method on the specific bean class. (Any class that implements java.lang.AutoCloseable or java.io.Closeable would therefore match.) You can  also set this special (inferred) value on the default-destroy-method attribute of a element to apply this behavior to an entire set of beans (see Default Initialization and Destroy Methods). Note that this is the default behavior with Java configuration. Default Initialization and Destroy Methods When you write initialization and destroy method callbacks that do not use the Spring-specific InitializingBean and DisposableBean callback interfaces, you typically write methods with names such as init(), initialize(), dispose(), and so on. Ideally, the names of such lifecycle callback methods are standardized across a project so that all developers use the same method names and ensure consistency. You can configure the Spring container to “look” for named initialization and destroy callback method names on every bean. This means that you, as an application developer, can write your application classes and use an initialization callback called init(), without having to configure an init-method="init" attribute with each bean definition. The Spring IoC container calls that method when the bean is created (and in accordance with the standard lifecycle callback contract described previously). This feature also enforces a consistent naming convention for initialization and destroy method callbacks. Suppose that your initialization callback methods are named init() and your destroy callback methods are named destroy(). Your class then resembles the class in the following example: Java public class DefaultBlogService implements BlogService {   private BlogDao blogDao;   public void setBlogDao(BlogDao blogDao) {   this.blogDao = blogDao;   }   // this is (unsurprisingly) the initialization callback method   public void init() {   if (this.blogDao == null) {   throw new IllegalStateException("The [blogDao] property must be set.");   }   } } Kotlin class DefaultBlogService : BlogService {   private var blogDao: BlogDao? = null   // this is (unsurprisingly) the initialization callback method   fun init() {   if (blogDao == null) {   throw IllegalStateException("The [blogDao] property must be set.")   }   } } You could then use that class in a bean resembling the following:       The presence of the default-init-method attribute on the top-level element attribute causes the Spring IoC container to recognize a method called init on the bean class as the initialization method callback. When a bean is created and assembled, if the bean class has such a method, it is invoked at the appropriate time. You can configure destroy method callbacks similarly (in XML, that is) by using the default- destroy-method attribute on the top-level element. Where existing bean classes already have callback methods that are named at variance with the convention, you can override the default by specifying (in XML, that is) the method name by using the init-method and destroy-method attributes of the itself. The Spring container guarantees that a configured initialization callback is called immediately after a bean is supplied with all dependencies. Thus, the initialization callback is called on the raw bean reference, which means that AOP interceptors and so forth are not yet applied to the bean. A target bean is fully created first and then an AOP proxy (for example) with its interceptor chain is applied. If the target bean and the proxy are defined separately, your code can even interact with the raw target bean, bypassing the proxy. Hence, it would be inconsistent to apply the interceptors to the init method, because doing so would couple the lifecycle of the target bean to its proxy or interceptors and leave strange semantics when your code interacts directly with the raw target bean. --- ### Models/Spring Ai Openai/Src/Test/Resources/Data/Acme/Bikes.Json (models/spring-ai-openai/src/test/resources/data/acme/bikes.json) [ { "name": "E-Adrenaline 8.0 EX1", "shortDescription": "a versatile and comfortable e-MTB designed for adrenaline enthusiasts who want to explore all types of terrain. It features a powerful motor and advanced suspension to provide a smooth and responsive ride, with a variety of customizable settings to fit any rider's needs.", "description": "## Overview\r\nIt's right for you if...\r\nYou want to push your limits on challenging trails and terrain, with the added benefit of an electric assist to help you conquer steep climbs and rough terrain. You also want a bike with a comfortable and customizable fit, loaded with high-quality components and technology.\r\n\r\nThe tech you get\r\nA lightweight, full ADV Mountain Carbon frame with a customizable geometry, including an adjustable head tube and chainstay length. A powerful and efficient motor with a 375Wh battery that can assist up to 28 mph when it's on, and provides a smooth and seamless transition when it's off. A SRAM EX1 8-speed drivetrain, a RockShox Lyrik Ultimate fork, and a RockShox Super Deluxe Ultimate rear shock.\r\n\r\nThe final word\r\nOur E-Adrenaline 8.0 EX1 is the perfect bike for adrenaline enthusiasts who want to explore all types of terrain. It's versatile, comfortable, and loaded with advanced technology to provide a smooth and responsive ride, no matter where your adventures take you.\r\n\r\n\r\n## Features\r\nVersatile and customizable\r\nThe E-Adrenaline 8.0 EX1 features a customizable geometry, including an adjustable head tube and chainstay length, so you can fine-tune your ride to fit your needs and preferences. It also features a variety of customizable settings, including suspension tuning, motor assistance levels, and more.\r\n\r\nPowerful and efficient\r\nThe bike is equipped with a powerful and efficient motor that provides a smooth and seamless transition between human power and electric assist. It can assist up to 28 mph when it's on, and provides zero drag when it's off.\r\n\r\nAdvanced suspension\r\nThe E-Adrenaline 8.0 EX1 features a RockShox Lyrik Ultimate fork and a RockShox Super Deluxe Ultimate rear shock, providing advanced suspension technology to absorb shocks and bumps on any terrain. The suspension is also customizable to fit your riding style and preferences.\r\n\r\n\r\n## Specs\r\nFrameset\r\nFrame ADV Mountain Carbon main frame & stays, adjustable head tube and chainstay length, tapered head tube, Knock Block, Control Freak internal routing, Boost148, 150mm travel\r\nFork RockShox Lyrik Ultimate, DebonAir spring, Charger 2.1 RC2 damper, remote lockout, tapered steerer, 42mm offset, Boost110, 15mm Maxle Stealth, 160mm travel\r\nShock RockShox Super Deluxe Ultimate, DebonAir spring, Thru Shaft 3-position damper, 230x57.5mm\r\n\r\nWheels\r\nWheel front Bontrager Line Elite 30, ADV Mountain Carbon, Tubeless Ready, 6-bolt, Boost110, 15mm thru axle\r\nWheel rear Bontrager Line Elite 30, ADV Mountain Carbon, Tubeless Ready, 54T Rapid Drive, 6-bolt, Shimano MicroSpline freehub, Boost148, 12mm thru axle\r\nSkewer rear Bontrager Switch thru axle, removable lever\r\nTire Bontrager XR5 Team Issue, Tubeless Ready, Inner Strength sidewall, aramid bead, 120tpi, 29x2.50''\r\nTire part Bontrager TLR sealant, 6oz\r\n\r\nDrivetrain\r\nShifter SRAM EX1, 8 speed\r\nRear derailleur SRAM EX1, 8 speed\r\nCrank Bosch Performance CX, magnesium motor body, 250 watt, 75 Nm torque\r\nChainring SRAM EX1, 18T, steel\r\nCassette SRAM EX1, 11-48, 8 speed\r\nChain SRAM EX1, 8 speed\r\n\r\nComponents\r\nSaddle Bontrager Arvada, hollow chromoly rails, 138mm width\r\nSeatpost Bontrager Line Elite Dropper, internal routing, 31.6mm\r\nHandlebar Bontrager Line Pro, ADV Carbon, 35mm, 27.5mm rise, 780mm width\r\nGrips Bontrager XR Trail Elite, alloy lock-on\r\nStem Bontrager Line Pro, 35mm, Knock Block, Blendr compatible, 0 degree, 50mm length\r\nHeadset Knock Block Integrated, 62-degree radius, cartridge bearing, 1-1\/8'' top, 1.5'' bottom\r\nBrake SRAM G2 RSC hydraulic disc, carbon levers\r\nBrake rotor SRAM Centerline, centerlock, round edge, 200mm\r\n\r\nAccessories\r\nE-bike system Bosch Performance CX, magnesium motor body, 250 watt, 75 Nm torque\r\nBattery Bosch PowerTube 625, 625Wh\r\nCharger Bosch 4A standard charger\r\nController Bosch Kiox with Anti-theft solution, Bluetooth connectivity, 1.9'' display\r\nTool Bontrager Switch thru axle, removable lever\r\n\r\nWeight\r\nWeight M - 20.25 kg \/ 44.6 lbs (with TLR sealant, no tubes)\r\nWeight limit This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\r\n\r\n## Sizing & fit\r\n\r\n| Size | Rider Height | Inseam |\r\n|:----:|:------------------------:|:--------------------:|\r\n| S | 155 - 170 cm 5'1\" - 5'7\" | 73 - 80 cm 29\" - 31.5\" |\r\n| M | 163 - 178 cm 5'4\" - 5'10\" | 77 - 83 cm 30.5\" - 32.5\" |\r\n| L | 176 - 191 cm 5'9\" - 6'3\" | 83 - 89 cm 32.5\" - 35\" |\r\n| XL | 188 - 198 cm 6'2\" - 6'6\" | 88 - 93 cm 34.5\" - 36.5\" |\r\n\r\n\r\n## Geometry\r\n\r\nAll measurements provided in cm unless otherwise noted.\r\nSizing table\r\n| Frame size letter | S | M | L | XL |\r\n|---------------------------|-------|-------|-------|-------|\r\n| Actual frame size | 15.8 | 17.8 | 19.8 | 21.8 |\r\n| Wheel size | 29\" | 29\" | 29\" | 29\" |\r\n| A \u2014 Seat tube | 40.0 | 42.5 | 47.5 | 51.0 |\r\n| B \u2014 Seat tube angle | 72.5\u00B0 | 72.8\u00B0 | 73.0\u00B0 | 73.0\u00B0 |\r\n| C \u2014 Head tube length | 9.5 | 10.5 | 11.0 | 11.5 |\r\n| D \u2014 Head angle | 67.8\u00B0 | 67.8\u00B0 | 67.8\u00B0 | 67.8\u00B0 |\r\n| E \u2014 Effective top tube | 59.0 | 62.0 | 65.0 | 68.0 |\r\n| F \u2014 Bottom bracket height | 32.5 | 32.5 | 32.5 | 32.5 |\r\n| G \u2014 Bottom bracket drop | 5.5 | 5.5 | 5.5 | 5.5 |\r\n| H \u2014 Chainstay length | 45.0 | 45.0 | 45.0 | 45.0 |\r\n| I \u2014 Offset | 4.5 | 4.5 | 4.5 | 4.5 |\r\n| J \u2014 Trail | 11.0 | 11.0 | 11.0 | 11.0 |\r\n| K \u2014 Wheelbase | 113.0 | 117.0 | 120.0 | 123.0 |\r\n| L \u2014 Standover | 77.0 | 77.0 | 77.0 | 77.0 |\r\n| M \u2014 Frame reach | 41.0 | 44.5 | 47.5 | 50.0 |\r\n| N \u2014 Frame stack | 61.0 | 62.0 | 62.5 | 63.0 |", "price": 1499.99, "tags": [ "bicycle" ] }, { "name": "Enduro X Pro", "shortDescription": "The Enduro X Pro is the ultimate mountain bike for riders who demand the best. With its full carbon frame and top-of-the-line components, this bike is ready to tackle any trail, from technical downhill descents to grueling uphill climbs.", "text": "## Overview\nIt's right for you if...\nYou're an experienced mountain biker who wants a high-performance bike that can handle any terrain. You want a bike with the best components available, including a full carbon frame, suspension system, and hydraulic disc brakes.\n\nThe tech you get\nOur top-of-the-line full carbon frame with aggressive geometry and a slack head angle for maximum control. It's equipped with a Fox Factory suspension system with 170mm of travel in the front and 160mm in the rear, a Shimano XTR 12-speed drivetrain, and hydraulic disc brakes for maximum stopping power. The bike also features a dropper seatpost for easy adjustments on the fly.\n\nThe final word\nThe Enduro X Pro is the ultimate mountain bike for riders who demand the best. With its full carbon frame, top-of-the-line components, and aggressive geometry, this bike is ready to take on any trail. Whether you're a seasoned pro or just starting out, the Enduro X Pro will help you take your riding to the next level.\n\n## Features\nFull carbon frame\nAggressive geometry with a slack head angle\nFox Factory suspension system with 170mm of travel in the front and 160mm in the rear\nShimano XTR 12-speed drivetrain\nHydraulic disc brakes for maximum stopping power\nDropper seatpost for easy adjustments on the fly\n\n## Specifications\nFrameset\nFrame\tFull carbon frame\nFork\tFox Factory suspension system with 170mm of travel\nRear suspension\tFox Factory suspension system with 160mm of travel\n\nWheels\nWheel size\t27.5\" or 29\"\nTires\tTubeless-ready Maxxis tires\n\nDrivetrain\nShifters\tShimano XTR 12-speed\nFront derailleur\tN/A\nRear derailleur\tShimano XTR\nCrankset\tShimano XTR\nCassette\tShimano XTR 12-speed\nChain\tShimano XTR\n\nComponents\nBrakes\tHydraulic disc brakes\nHandlebar\tAlloy handlebar\nStem\tAlloy stem\nSeatpost\tDropper seatpost\n\nAccessories\nPedals\tNot included\n\nWeight\nWeight\tApproximately 27-29 lbs\n\n## Sizing\n| Size | Rider Height |\n|:----:|:-------------------------:|\n| S | 5'4\" - 5'8\" (162-172cm) |\n| M | 5'8\" - 5'11\" (172-180cm) |\n| L | 5'11\" - 6'3\" (180-191cm) |\n| XL | 6'3\" - 6'6\" (191-198cm) |\n\n## Geometry\n| Size | S | M | L | XL |\n|:----:|:---------------:|:---------------:|:-----------------:|:---------------:|\n| A - Seat tube length | 390mm | 425mm | 460mm | 495mm |\n| B - Effective top tube length | 585mm | 610mm | 635mm | 660mm |\n| C - Head tube angle | 65.5° | 65.5° | 65.5° | 65.5° |\n| D - Seat tube angle | 76° | 76° | 76° | 76° |\n| E - Chainstay length | 435mm | 435mm | 435mm | 435mm |\n| F - Head tube length | 100mm | 110mm | 120mm | 130mm |\n| G - BB drop | 20mm | 20mm | 20mm | 20mm |\n| H - Wheelbase | 1155mm | 1180mm | 1205mm | 1230mm |\n| I - Standover height | 780mm | 800mm | 820mm | 840mm |\n| J - Reach | 425mm | 450mm | 475mm | 500mm |\n| K - Stack | 610mm | 620mm | 630mm | 640mm |", "price": 599.99, "tags": [ "bicycle" ] }, { "name": "Blaze X1", "shortDescription": "Blaze X1 is a high-performance road bike that offers superior speed and agility, making it perfect for competitive racing or fast-paced group rides. The bike features a lightweight carbon frame, aerodynamic tube shapes, a 12-speed Shimano Ultegra drivetrain, and hydraulic disc brakes for precise stopping power. With its sleek design and cutting-edge technology, Blaze X1 is a bike that is built to perform and dominate on any road.", "description": "## Overview\nIt's right for you if...\nYou're a competitive road cyclist or an enthusiast who enjoys fast-paced group rides. You want a bike that is lightweight, agile, and delivers exceptional speed.\n\nThe tech you get\nBlaze X1 features a lightweight carbon frame with a tapered head tube and aerodynamic tube shapes for maximum speed and efficiency. The bike is equipped with a 12-speed Shimano Ultegra drivetrain for smooth and precise shifting, Shimano hydraulic disc brakes for powerful and reliable stopping power, and Bontrager Aeolus Elite 35 carbon wheels for increased speed and agility.\n\nThe final word\nBlaze X1 is a high-performance road bike that is designed to deliver exceptional speed and agility. With its cutting-edge technology and top-of-the-line components, it's a bike that is built to perform and dominate on any road.\n\n## Features\nSpeed and efficiency\nBlaze X1's lightweight carbon frame and aerodynamic tube shapes offer maximum speed and efficiency, allowing you to ride faster and farther with ease.\n\nPrecision stopping power\nShimano hydraulic disc brakes provide precise and reliable stopping power, even in wet or muddy conditions.\n\nAgility and control\nBontrager Aeolus Elite 35 carbon wheels make Blaze X1 incredibly agile and responsive, allowing you to navigate tight turns and corners with ease.\n\nSmooth and precise shifting\nThe 12-speed Shimano Ultegra drivetrain offers smooth and precise shifting, so you can easily find the right gear for any terrain.\n\n## Specifications\nFrameset\nFrame\tADV Carbon, tapered head tube, BB90, direct mount rim brakes, internal cable routing, DuoTrap S compatible, 130x9mm QR\nFork\tADV Carbon, tapered steerer, direct mount rim brakes, internal brake routing, 100x9mm QR\n\nWheels\nWheel front\tBontrager Aeolus Elite 35, ADV Carbon, Tubeless Ready, 35mm rim depth, 100x9mm QR\nWheel rear\tBontrager Aeolus Elite 35, ADV Carbon, Tubeless Ready, 35mm rim depth, Shimano 11-speed freehub, 130x9mm QR\nTire front\tBontrager R3 Hard-Case Lite, aramid bead, 120 tpi, 700x25c\nTire rear\tBontrager R3 Hard-Case Lite, aramid bead, 120 tpi, 700x25c\nMax tire size\t25c Bontrager tires (with at least 4mm of clearance to frame)\n\nDrivetrain\nShifter\tShimano Ultegra R8020, 12 speed\nFront derailleur\tShimano Ultegra R8000, braze-on\nRear derailleur\tShimano Ultegra R8000, short cage, 30T max cog\nCrank\tSize: 50, 52, 54\nShimano Ultegra R8000, 50/34 (compact), 170mm length\nSize: 56, 58, 60, 62\nShimano Ultegra R8000, 50/34 (compact), 172.5mm length\nBottom bracket\tBB90, Shimano press-fit\nCassette\tShimano Ultegra R8000, 11-30, 12 speed\nChain\tShimano Ultegra HG701, 12 speed\n\nComponents\nSaddle\tBontrager Montrose Elite, titanium rails, 138mm width\nSeatpost\tBontrager carbon seatmast cap, 20mm offset\nHandlebar\tBontrager Elite Aero VR-CF, alloy, 31.8mm, internal cable routing, 40cm width\nGrips\tBontrager Supertack Perf tape\nStem\tBontrager Elite, 31.8mm, Blendr-compatible, 7 degree, 80mm length\nBrake Shimano Ultegra hydraulic disc brake\n\nWeight\nWeight\t56 - 8.91 kg / 19.63 lbs (with tubes)\nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 275 pounds (125 kg).\n\n## Sizing\n| Size | Rider height |\n|------|-------------|\n| 50 | 162-166cm |\n| 52 | 165-170cm |\n| 54 | 168-174cm |\n| 56 | 174-180cm |\n| 58 | 179-184cm |\n| 60 | 184-189cm |\n| 62 | 189-196cm |\n\n## Geometry\n| Frame size | 50cm | 52cm | 54cm | 56cm | 58cm | 60cm | 62cm |\n|------------|-------|-------|-------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c | 700c | 700c | 700c |\n| A - Seat tube | 443mm | 460mm | 478mm | 500mm | 520mm | 540mm | 560mm |\n| B - Seat tube angle | 74.1° | 73.9° | 73.7° | 73.4° | 73.2° | 73.0° | 72.8° |\n| C - Head tube length | 100mm | 110mm | 130mm | 150mm | 170mm | 190mm | 210mm |\n| D - Head angle | 71.4° | 72.0° | 72.5° | 73.0° | 73.3° | 73.6° | 73.8° |\n| E - Effective top tube | 522mm | 535mm | 547mm | 562mm | 577mm | 593mm | 610mm |\n| F - Bottom bracket height | 268mm | 268mm | 268mm | 268mm | 268mm | 268mm | 268mm |\n| G - Bottom bracket drop | 69mm | 69mm | 69mm | 69mm | 69mm | 69mm | 69mm |\n| H - Chainstay length | 410mm | 410mm | 410mm | 410mm | 410mm | 410mm | 410mm |\n| I - Offset | 50mm | 50mm | 50mm | 50mm | 50mm | 50mm | 50mm |\n| J - Trail | 65mm | 62mm | 59mm | 56mm | 55mm | 53mm | 52mm |\n| K - Wheelbase | 983mm | 983mm | 990mm | 1005mm | 1019mm | 1036mm | 1055mm |\n| L - Standover | 741mm | 765mm | 787mm | 806mm | 825mm | 847mm | 869mm |", "price": 799.99, "tags": [ "bicycle", "mountain bike" ] }, { "name": "Celerity X5", "shortDescription": "Celerity X5 is a versatile and reliable road bike that is designed for experienced and amateur riders alike. It's designed to provide smooth and comfortable rides over long distances. With an ultra-lightweight and responsive carbon fiber frame, Shimano 105 groupset, hydraulic disc brakes, and 28mm wide tires, this bike ensures efficient power transfer, precise handling, and superior stopping power.", "description": "## Overview\n\nIt's right for you if... \nYou are looking for a high-performance road bike that offers a perfect balance of speed, comfort, and control. You enjoy long-distance rides and need a bike that is designed to handle various road conditions with ease. You also appreciate the latest technology and reliable components that make your riding experience more enjoyable.\n\nThe tech you get \nCelerity X5 is equipped with a full carbon fiber frame that ensures maximum strength and durability while keeping the weight down. It features a Shimano 105 groupset with 11-speed gearing for precise and efficient shifting. Hydraulic disc brakes offer superior stopping power, and 28mm wide tires provide comfort and stability on various road surfaces. Internal cable routing enhances the bike's sleek appearance.\n\nThe final word \nIf you are looking for a high-performance road bike that offers comfort, speed, and control, Celerity X5 is the perfect choice. With its lightweight carbon fiber frame, reliable components, and advanced technology, this bike is designed to help you enjoy long-distance rides with ease.\n\n## Features \n\nLightweight and responsive \nCelerity X5 comes with a full carbon fiber frame that is not only lightweight but also responsive, providing excellent handling and control.\n\nHydraulic disc brakes \nThis bike is equipped with hydraulic disc brakes that provide superior stopping power in all weather conditions, ensuring your safety and confidence on the road.\n\nComfortable rides \nThe 28mm wide tires and carbon seat post provide ample cushioning, ensuring a smooth and comfortable ride over long distances.\n\nSleek appearance \nThe bike's internal cable routing enhances its sleek appearance while also protecting the cables from the elements, ensuring smooth shifting for longer periods.\n\n## Specifications \n\nFrameset \nFrame\tCelerity X5 Full Carbon Fiber Frame, Internal Cable Routing, Tapered Headtube, Press Fit Bottom Bracket, 12x142mm Thru-Axle \nFork\tCelerity X5 Full Carbon Fiber Fork, Internal Brake Routing, 12x100mm Thru-Axle \n\nWheels \nWheelset\tAlexRims CXD7 Wheelset \nTire\tSchwalbe Durano Plus 700x28mm \nInner Tubes\tSchwalbe SV15 700x18-28mm \nSkewers\tCelerity X5 Thru-Axle Skewers \n\nDrivetrain \nShifter\tShimano 105 R7025 Hydraulic Disc Shifters \nFront Derailleur\tShimano 105 R7000 \nRear Derailleur\tShimano 105 R7000 \nCrankset\tShimano 105 R7000 50-34T \nBottom Bracket\tShimano BB72-41B \nCassette\tShimano 105 R7000 11-30T \nChain\tShimano HG601 11-Speed Chain \n\nComponents \nSaddle\tSelle Royal Asphalt Saddle \nSeatpost\tCelerity X5 Carbon Seatpost \nHandlebar\tCelerity X5 Compact Handlebar \nStem\tCelerity X5 Aluminum Stem \nHeadset\tFSA Orbit IS-2 \n\nBrakes \nBrakes\tShimano 105 R7025 Hydraulic Disc Brakes \nRotors\tShimano SM-RT70 160mm Rotors \n\nAccessories \nPedals\tCelerity X5 Road Pedals \n\nWeight \nWeight\t8.2 kg / 18.1 lbs \nWeight Limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 120 kg (265 lbs).\n\n## Sizing \n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| 49 | 155 - 162 cm 5'1\" - 5'4\" | 71 - 76 cm 28\" - 30\" |\n| 52 | 162 - 170 cm 5'4\" - 5'7\" | 74 - 79 cm 29\" - 31\" |\n| 54 | 170 - 178 cm 5'7\" - 5'10\" | 77 - 83 cm 30\" - 32\" |\n| 56 | 178 - 185 cm 5'10\" - 6'1\" | 82 - 88 cm 32\" - 34\" |\n| 58 | 185 - 193 cm 6'1\" - 6'4\" | 86 - 92 cm 34\" - 36\" |\n| 61 | 193 - 200 cm 6'4\" - 6'7\" | 90 - 95 cm 35\" - 37\" |\n\n## Geometry \n| Frame size number | 49 cm | 52 cm | 54 cm | 56 cm | 58 cm | 61 cm |\n|---------------------------------------|-------|-------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c | 700c | 700c |\n| A — Seat tube | 47.5 | 50.0 | 52.0 | 54.0 | 56.0 | 58.5 |\n| B — Seat tube angle | 75.0° | 74.5° | 74.0° | 73.5° | 73.0° | 72.5° |\n| C — Head tube length | 12.0 | 14.5 | 16.5 | 18.5 | 20.5 | 23.5 |\n| D — Head angle | 70.0° | 71.0° | 71.5° | 72.0° | 72.5° | 72.5° |\n| E — Effective top tube | 52.5 | 53.5 | 54.5 | 56.0 | 57.5 | 59.5 |\n| G — Bottom bracket drop | 7.0 | 7.0 | 7.0 | 7.0 | 7.0 | 7.0 |\n| H — Chainstay length | 41.5 | 41.5 | 41.5 | 41.5 | 41.5 | 41.5 |\n| K — Wheelbase | 98.4 | 98.9 | 99.8 | 100.8 | 101.7 | 103.6 |\n| L — Standover | 72.0 | 74.0 | 76.0 | 78.0 | 80.0 | 82.0 |\n| M — Frame reach | 36.2 | 36.8 | 37.3 | 38.1 | 38.6 | 39.4 |\n| N — Frame stack | 52.0 | 54.3 | 56.2 | 58.1 | 59.8 | 62.4 |\n| Saddle rail height min | 67.0 | 69.5 | 71.5 | 74.0 | 76.0 | 78.0 |\n| Saddle rail height max | 75.0 | 77.5 | 79.5 | 82.0 | 84.0 | 86.0 |", "price": 399.99, "tags": [ "bicycle", "city bike" ] }, { "name": "Velocity V8", "shortDescription": "Velocity V8 is a high-performance road bike that is designed to deliver speed, agility, and control on the road. With its lightweight aluminum frame, carbon fiber fork, Shimano Tiagra groupset, and hydraulic disc brakes, this bike is perfect for experienced riders who are looking for a fast and responsive bike that can handle various road conditions.", "description": "## Overview\n\nIt's right for you if... \nYou are an experienced rider who is looking for a high-performance road bike that is lightweight, agile, and responsive. You want a bike that can handle long-distance rides, steep climbs, and fast descents with ease. You also appreciate the latest technology and reliable components that make your riding experience more enjoyable.\n\nThe tech you get \nVelocity V8 features a lightweight aluminum frame with a carbon fiber fork that ensures a comfortable ride without sacrificing stiffness and power transfer. It comes with a Shimano Tiagra groupset with 10-speed gearing for precise and efficient shifting. Hydraulic disc brakes offer superior stopping power in all weather conditions, while 28mm wide tires provide comfort and stability on various road surfaces. Internal cable routing enhances the bike's sleek appearance.\n\nThe final word \nIf you are looking for a high-performance road bike that is lightweight, fast, and responsive, Velocity V8 is the perfect choice. With its lightweight aluminum frame, reliable components, and advanced technology, this bike is designed to help you enjoy fast and comfortable rides on the road.\n\n## Features \n\nLightweight and responsive \nVelocity V8 comes with a lightweight aluminum frame that is not only lightweight but also responsive, providing excellent handling and control.\n\nHydraulic disc brakes \nThis bike is equipped with hydraulic disc brakes that provide superior stopping power in all weather conditions, ensuring your safety and confidence on the road.\n\nComfortable rides \nThe 28mm wide tires and carbon fork provide ample cushioning, ensuring a smooth and comfortable ride over long distances.\n\nSleek appearance \nThe bike's internal cable routing enhances its sleek appearance while also protecting the cables from the elements, ensuring smooth shifting for longer periods.\n\n## Specifications \n\nFrameset \nFrame\tVelocity V8 Aluminum Frame, Internal Cable Routing, Tapered Headtube, Press Fit Bottom Bracket, 12x142mm Thru-Axle \nFork\tVelocity V8 Carbon Fiber Fork, Internal Brake Routing, 12x100mm Thru-Axle \n\nWheels \nWheelset\tAlexRims CXD7 Wheelset \nTire\tSchwalbe Durano Plus 700x28mm \nInner Tubes\tSchwalbe SV15 700x18-28mm \nSkewers\tVelocity V8 Thru-Axle Skewers \n\nDrivetrain \nShifter\tShimano Tiagra Hydraulic Disc Shifters \nFront Derailleur\tShimano Tiagra \nRear Derailleur\tShimano Tiagra \nCrankset\tShimano Tiagra 50-34T \nBottom Bracket\tShimano BB-RS500-PB \nCassette\tShimano Tiagra 11-32T \nChain\tShimano HG54 10-Speed Chain \n\nComponents \nSaddle\tVelocity V8 Saddle \nSeatpost\tVelocity V8 Aluminum Seatpost \nHandlebar\tVelocity V8 Compact Handlebar \nStem\tVelocity V8 Aluminum Stem \nHeadset\tFSA Orbit IS-2 \n\nBrakes \nBrakes\tShimano Tiagra Hydraulic Disc Brakes \nRotors\tShimano SM-RT64 160mm Rotors \n\nAccessories \nPedals\tVelocity V8 Road Pedals \n\nWeight \nWeight\t9.4 kg / 20.7 lbs \nWeight Limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 120 kg (265 lbs).\n\n## Sizing \n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| 49 | 155 - 162 cm 5'1\" - 5'4\" | 71 - 76 cm 28\" - 30\" |\n| 52 | 162 - 170 cm 5'4\" - 5'7\" | 74 - 79 cm 29\" - 31\" |\n| 54 | 170 - 178 cm 5'7\" - 5'10\" | 77 - 83 cm 30\" - 32\" |\n| 56 | 178 - 185 cm 5'10\" - 6'1\" | 82 - 88 cm 32\" - 34\" |\n| 58 | 185 - 193 cm 6'1\" - 6'4\" | 86 - 92 cm 34\" - 36\" |\n| 61 | 193 - 200 cm 6'4\" - 6'7\" | 90 - 95 cm 35\" - 37\" |\n\n## Geometry \n| Frame size number | 49 cm | 52 cm | 54 cm | 56 cm | 58 cm | 61 cm |\n|---------------------------------------|-------|-------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c | 700c | 700c |\n| A — Seat tube | 47.5 | 50.0 | 52.0 | 54.0 | 56.0 | 58.5 |\n| B — Seat tube angle | 75.0° | 74.5° | 74.0° | 73.5° | 73.0° | 72.5° |\n| C — Head tube length | 12.0 | 14.5 | 16.5 | 18.5 | 20.5 | 23.5 |\n| D — Head angle | 70.0° | 71.0° | 71.5° | 72.0° | 72.5° | 72.5° |\n| E — Effective top tube | 52.5 | 53.5 | 54.5 | 56.0 | 57.5 | 59.5 |\n| G — Bottom bracket drop | 7.0 | 7.0 | 7.0 | 7.0 | 7.0 | 7.0 |\n| H — Chainstay length | 41.5 | 41.5 | 41.5 | 41.5 | 41.5 | 41.5 |\n| K — Wheelbase | 98.4 | 98.9 | 99.8 | 100.8 | 101.7 | 103.6 |\n| L — Standover | 72.0 | 74.0 | 76.0 | 78.0 | 80.0 | 82.0 |\n| M — Frame reach | 36.2 | 36.8 | 37.3 | 38.1 | 38.6 | 39.4 |\n| N — Frame stack | 52.0 | 54.3 | 56.2 | 58.1 | 59.8 | 62.4 |\n| Saddle rail height min | 67.0 | 69.5 | 71.5 | 74.0 | 76.0 | 78.0 |\n| Saddle rail height max | 75.0 | 77.5 | 79.5 | 82.0 | 84.0 | 86.0 |", "price": 1899.99, "tags": [ "bicycle", "electric bike" ] }, { "name": "VeloCore X9 eMTB", "shortDescription": "The VeloCore X9 eMTB is a light, agile and versatile electric mountain bike designed for adventure and performance. Its purpose-built frame and premium components offer an exhilarating ride experience on both technical terrain and smooth singletrack.", "description": "## Overview\nIt's right for you if...\nYou love exploring new trails and testing your limits on challenging terrain. You want an electric mountain bike that offers power when you need it, without sacrificing performance or agility. You're looking for a high-quality bike with top-notch components and a sleek design.\n\nThe tech you get\nA lightweight, full carbon frame with custom geometry, a 140mm RockShox Pike Ultimate fork with Charger 2.1 damper, and a Fox Float DPS Performance shock. A Shimano STEPS E8000 motor and 504Wh battery that provide up to 62 miles of range and 20 mph assistance. A Shimano XT 12-speed drivetrain, Shimano SLX brakes, and DT Swiss wheels.\n\nThe final word\nThe VeloCore X9 eMTB delivers power and agility in equal measure. It's a versatile and capable electric mountain bike that can handle any trail with ease. With premium components, a custom carbon frame, and a sleek design, this bike is built for adventure.\n\n## Features\nAgile and responsive\n\nThe VeloCore X9 eMTB is designed to be nimble and responsive on the trail. Its custom carbon frame offers a perfect balance of stiffness and compliance, while the suspension system provides smooth and stable performance on technical terrain.\n\nPowerful and efficient\n\nThe Shimano STEPS E8000 motor and 504Wh battery provide up to 62 miles of range and 20 mph assistance. The motor delivers smooth and powerful performance, while the battery offers reliable and consistent power for long rides.\n\nCustomizable ride experience\n\nThe VeloCore X9 eMTB comes with an intuitive and customizable Shimano STEPS display that allows you to adjust the level of assistance, monitor your speed and battery life, and customize your ride experience to suit your needs.\n\nPremium components\n\nThe VeloCore X9 eMTB is equipped with high-end components, including a Shimano XT 12-speed drivetrain, Shimano SLX brakes, and DT Swiss wheels. These components offer reliable and precise performance, allowing you to push your limits with confidence.\n\n## Specs\nFrameset\nFrame\tVeloCore carbon fiber frame, Boost, tapered head tube, internal cable routing, 140mm travel\nFork\tRockShox Pike Ultimate, Charger 2.1 damper, DebonAir spring, 15x110mm Boost Maxle Ultimate, 46mm offset, 140mm travel\nShock\tFox Float DPS Performance, EVOL, 3-position adjust, Kashima Coat, 210x50mm\n\nWheels\nWheel front\tDT Swiss XM1700 Spline, 30mm internal width, 15x110mm Boost axle\nWheel rear\tDT Swiss XM1700 Spline, 30mm internal width, Shimano Microspline driver, 12x148mm Boost axle\nTire front\tMaxxis Minion DHF, 29x2.5\", EXO+ casing, tubeless ready\nTire rear\tMaxxis Minion DHR II, 29x2.4\", EXO+ casing, tubeless ready\n\nDrivetrain\nShifter\tShimano XT M8100, 12-speed\nRear derailleur\tShimano XT M8100, Shadow Plus, long cage, 51T max cog\nCrankset\tShimano STEPS E8000, 165mm length, 34T chainring\nCassette\tShimano XT M8100, 10-51T, 12-speed\nChain\tShimano CN-M8100, 12-speed\nPedals\tNot included\n\nComponents\nSaddle\tBontrager Arvada, hollow chromoly rails\nSeatpost\tDrop Line, internal routing, 31.6mm (15.5: 100mm, 17.5 & 18.5: 125mm, 19.5 & 21.5: 150mm)\nHandlebar\tBontrager Line Pro, ADV Carbon, 35mm, 27.5mm rise, 780mm width\nStem\tBontrager Line Pro, 35mm, Knock Block, 0 degree, 50mm length\nGrips\tBontrager XR Trail Elite, alloy lock-on\nHeadset\tIntegrated, sealed cartridge bearing, 1-1/8\" top, 1.5\" bottom\nBrakeset\tShimano SLX M7120, 4-piston hydraulic disc\n\nAccessories\nBattery\tShimano STEPS BT-E8010, 504Wh\nCharger\tShimano STEPS EC-E8004, 4A\nController\tShimano STEPS E8000 display\nBike weight\tM - 22.5 kg / 49.6 lbs (with tubes)\n\n## Sizing & fit\n\n| Size | Rider Height |\n|:----:|:------------------------:|\n| S | 162 - 170 cm 5'4\" - 5'7\" |\n| M | 170 - 178 cm 5'7\" - 5'10\"|\n| L | 178 - 186 cm 5'10\" - 6'1\"|\n| XL | 186 - 196 cm 6'1\" - 6'5\" |\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\n\n| Frame size | S | M | L | XL |\n|---------------------------|-------|-------|-------|-------|\n| A — Seat tube | 40.6 | 43.2 | 47.0 | 51.0 |\n| B — Seat tube angle | 75.0° | 75.0° | 75.0° | 75.0° |\n| C — Head tube length | 9.6 | 10.6 | 11.6 | 12.6 |\n| D — Head angle | 66.5° | 66.5° | 66.5° | 66.5° |\n| E — Effective top tube | 60.4 | 62.6 | 64.8 | 66.9 |\n| F — Bottom bracket height | 33.2 | 33.2 | 33.2 | 33.2 |\n| G — Bottom bracket drop | 3.0 | 3.0 | 3.0 | 3.0 |\n| H — Chainstay length | 45.5 | 45.5 | 45.5 | 45.5 |\n| I — Offset | 4.6 | 4.6 | 4.6 | 4.6 |\n| J — Trail | 11.9 | 11.9 | 11.9 | 11.9 |\n| K — Wheelbase | 117.0 | 119.3 | 121.6 | 123.9 |\n| L — Standover | 75.9 | 75.9 | 78.6 | 78.6 |\n| M — Frame reach | 43.6 | 45.6 | 47.6 | 49.6 |\n| N — Frame stack | 60.5 | 61.5 | 62.4 | 63.4 |", "price": 1299.99, "tags": [ "bicycle", "touring bike" ] }, { "name": "Zephyr 8.8 GX Eagle AXS Gen 3", "shortDescription": "Zephyr 8.8 GX Eagle AXS is a light and nimble full-suspension mountain bike. It's designed to handle technical terrain with ease and has a smooth and efficient ride feel. The sleek and powerful Bosch Performance Line CX motor and removable Powertube battery provide a boost to your pedaling and give you long-lasting riding time. The bike also features high-end components and advanced technology for an ultimate mountain biking experience.", "description": "## Overview\nIt's right for you if...\nYou're an avid mountain biker looking for a high-performance e-MTB that can tackle challenging trails. You want a bike with a powerful motor, efficient suspension, and advanced technology to enhance your riding experience. You also need a bike that's reliable and durable for long-lasting use.\n\nThe tech you get\nA lightweight, full carbon frame with 150mm of rear travel and a 160mm RockShox Pike Ultimate fork with Charger 2.1 RCT3 damper, remote lockout, and DebonAir spring. A Bosch Performance Line CX motor and removable Powertube 625Wh battery that can assist up to 20mph when it's on and gives zero drag when it's off, plus an easy-to-use handlebar-mounted Bosch Purion controller. A SRAM GX Eagle AXS wireless electronic drivetrain, a RockShox Reverb Stealth dropper, and DT Swiss HX1501 Spline One wheels.\n\nThe final word\nZephyr 8.8 GX Eagle AXS is a high-performance e-MTB that's designed to handle technical terrain with ease. With a powerful Bosch motor and long-lasting battery, you can conquer challenging climbs and enjoy long rides. The bike also features high-end components and advanced technology for an ultimate mountain biking experience.\n\n## Features\nPowerful motor\n\nThe Bosch Performance Line CX motor provides a boost to your pedaling and can assist up to 20mph. It has four power modes and a walk-assist function for easy navigation on steep climbs. The motor is also reliable and durable for long-lasting use.\n\nEfficient suspension\n\nZephyr 8.8 has a 150mm of rear travel and a 160mm RockShox Pike Ultimate fork with Charger 2.1 RCT3 damper, remote lockout, and DebonAir spring. The suspension is efficient and responsive, allowing you to handle technical terrain with ease.\n\nRemovable battery\n\nThe Powertube 625Wh battery is removable for easy charging and storage. It provides long-lasting riding time and can be replaced with a spare battery for even longer rides. The battery is also durable and weather-resistant for all-season riding.\n\nAdvanced technology\n\nZephyr 8.8 is equipped with advanced technology, including a Bosch Purion controller for easy motor control, a SRAM GX Eagle AXS wireless electronic drivetrain for precise shifting, and a RockShox Reverb Stealth dropper for adjustable saddle height. The bike also has DT Swiss HX1501 Spline One wheels for reliable performance on any terrain.\n\nCarbon frame\n\nThe full carbon frame is lightweight and durable, providing a smooth and efficient ride. It's also designed with a tapered head tube, internal cable routing, and Boost148 spacing for enhanced stiffness and responsiveness.\n\n## Specs\nFrameset\nFrame\tCarbon main frame & stays, tapered head tube, internal routing, Boost148, 150mm travel\nFork\tRockShox Pike Ultimate, Charger 2.1 RCT3 damper, DebonAir spring, remote lockout, tapered steerer, Boost110, 15mm Maxle Stealth, 160mm travel\nShock\tRockShox Deluxe RT3, DebonAir spring, 205mm x 57.5mm\nMax compatible fork travel\t170mm\n\nWheels\nWheel front\tDT Swiss HX1501 Spline One, Centerlock, 30mm inner width, 110x15mm Boost\nWheel rear\tDT Swiss HX1501 Spline One, Centerlock, 30mm inner width, SRAM XD driver, 148x12mm Boost\nTire\tBontrager XR4 Team Issue, Tubeless Ready, Inner Strength sidewall, aramid bead, 120tpi, 29x2.40''\nMax tire size\t29x2.60\"\n\nDrivetrain\nShifter\tSRAM GX Eagle AXS, wireless, 12 speed\nRear derailleur\tSRAM GX Eagle AXS\nCrank\tBosch Gen 4, 32T\nChainring\tSRAM X-Sync 2, 32T, direct-mount\nCassette\tSRAM PG-1275 Eagle, 10-52, 12 speed\nChain\tSRAM GX Eagle, 12 speed\n\nComponents\nSaddle\tBontrager Arvada, hollow titanium rails, 138mm width\nSeatpost\tRockShox Reverb Stealth, 31.6mm, internal routing, 150mm (S), 170mm (M/L), 200mm (XL)\nHandlebar\tBontrager Line Pro, ADV Carbon, 35mm, 27.5mm rise, 780mm width\nGrips\tBontrager XR Trail Elite, alloy lock-on\nStem\tBontrager Line Pro, Knock Block, 35mm, 0 degree, 50mm length\nHeadset\tIntegrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom\nBrake\tSRAM Code RSC hydraulic disc, 200mm (front), 180mm (rear)\nBrake rotor\tSRAM CenterLine, centerlock, round edge, 200mm (front), 180mm (rear)\n\nAccessories\nE-bike system\tBosch Performance Line CX\nBattery\tBosch Powertube 625Wh\nCharger\tBosch 4A compact charger\nController\tBosch Purion\nTool\tBontrager multi-tool, integrated storage bag\n\nWeight\nWeight\tM - 24.08 kg / 53.07 lbs (with TLR sealant, no tubes)\nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n\n## Sizing & fit\n\n| Size | Rider Height | Inseam |\n|:----:|:------------------------:|:--------------------:|\n| S | 153 - 162 cm 5'0\" - 5'4\" | 67 - 74 cm 26\" - 29\" |\n| M | 161 - 172 cm 5'3\" - 5'8\" | 74 - 79 cm 29\" - 31\" |\n| L | 171 - 180 cm 5'7\" - 5'11\" | 79 - 84 cm 31\" - 33\" |\n| XL | 179 - 188 cm 5'10\" - 6'2\" | 84 - 89 cm 33\" - 35\" |\n\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\nSizing table\n| Frame size letter | S | M | L | XL |\n|---------------------------|-------|-------|-------|-------|\n| Actual frame size | 15.5 | 17.5 | 19.5 | 21.5 |\n| Wheel size | 29\" | 29\" | 29\" | 29\" |\n| A — Seat tube | 39.4 | 41.9 | 44.5 | 47.6 |\n| B — Seat tube angle | 76.1° | 76.1° | 76.1° | 76.1° |\n| C — Head tube length | 9.6 | 10.5 | 11.5 | 12.5 |\n| D — Head angle | 65.5° | 65.5° | 65.5° | 65.5° |\n| E — Effective top tube | 58.6 | 61.3 | 64.0 | 66.7 |\n| F — Bottom bracket height | 34.0 | 34.0 | 34.0 | 34.0 |\n| G — Bottom bracket drop | 1.0 | 1.0 | 1.0 | 1.0 |\n| H — Chainstay length | 45.0 | 45.0 | 45.0 | 45.0 |\n| I — Offset | 4.6 | 4.6 | 4.6 | 4.6 |\n| J — Trail | 10.5 | 10.5 | 10.5 | 10.5 |\n| K — Wheelbase | 119.5 | 122.3 | 125.0 | 127.8 |\n| L — Standover | 72.7 | 74.7 | 77.6 | 81.0 |\n|", "price": 1499.99, "tags": [ "bicycle", "electric bike", "city bike" ] }, { "name": "Velo 99 XR1 AXS", "shortDescription": "Velo 99 XR1 AXS is a next-generation bike designed for fast-paced adventure seekers and speed enthusiasts. Built for high-performance racing, the bike boasts state-of-the-art technology and premium components. It is the ultimate bike for riders who want to push their limits and get their adrenaline pumping.", "description": "## Overview\nIt's right for you if...\nYou are a passionate cyclist looking for a bike that can keep up with your speed, agility, and endurance. You are an adventurer who loves to explore new terrains and challenge yourself on the toughest courses. You want a bike that is lightweight, durable, and packed with the latest technology.\n\nThe tech you get\nA lightweight, full carbon frame with advanced aerodynamics and integrated cable routing for a clean look. A high-performance SRAM XX1 Eagle AXS wireless electronic drivetrain, featuring a 12-speed cassette and a 32T chainring. A RockShox SID Ultimate fork with a remote lockout, 120mm travel, and Charger Race Day damper. A high-end SRAM G2 Ultimate hydraulic disc brake with carbon levers. A FOX Transfer SL dropper post for quick and easy height adjustments. DT Swiss XRC 1501 carbon wheels for superior speed and handling.\n\nThe final word\nVelo 99 XR1 AXS is a premium racing bike that can help you achieve your goals and reach new heights. It is designed for speed, agility, and performance, and it is packed with the latest technology and premium components. If you are a serious cyclist who wants the best, this is the bike for you.\n\n## Features\nAerodynamic design\n\nThe Velo 99 XR1 AXS features a state-of-the-art frame design that reduces drag and improves speed. It has an aerodynamic seatpost, integrated cable routing, and a sleek, streamlined look that sets it apart from other bikes.\n\nWireless electronic drivetrain\n\nThe SRAM XX1 Eagle AXS drivetrain features a wireless electronic system that provides precise, instant shifting and unmatched efficiency. It eliminates the need for cables and makes the bike lighter and faster.\n\nHigh-performance suspension\n\nThe RockShox SID Ultimate fork and Charger Race Day damper provide 120mm of smooth, responsive suspension that can handle any terrain. The fork also has a remote lockout for quick adjustments on the fly.\n\nSuperior braking power\n\nThe SRAM G2 Ultimate hydraulic disc brake system delivers unmatched stopping power and control. It has carbon levers for a lightweight, ergonomic design and precision control.\n\nCarbon wheels\n\nThe DT Swiss XRC 1501 carbon wheels are ultra-lightweight, yet incredibly strong and durable. They provide superior speed and handling, making the bike more agile and responsive.\n\n## Specs\nFrameset\nFrame\tFull carbon frame, integrated cable routing, aerodynamic design, Boost148\nFork\tRockShox SID Ultimate, Charger Race Day damper, remote lockout, tapered steerer, Boost110, 15mm Maxle Stealth, 120mm travel\n\nWheels\nWheel front\tDT Swiss XRC 1501 carbon wheel, Boost110, 15mm thru axle\nWheel rear\tDT Swiss XRC 1501 carbon wheel, SRAM XD driver, Boost148, 12mm thru axle\nTire\tSchwalbe Racing Ray, Performance Line, Addix, 29x2.25\"\nTire part\tSchwalbe Doc Blue Professional, 500ml\nMax tire size\t29x2.3\"\n\nDrivetrain\nShifter\tSRAM Eagle AXS, wireless, 12-speed\nRear derailleur\tSRAM XX1 Eagle AXS\nCrank\tSRAM XX1 Eagle, 32T, carbon\nChainring\tSRAM X-SYNC, 32T, alloy\nCassette\tSRAM Eagle XG-1299, 10-52, 12-speed\nChain\tSRAM XX1 Eagle, 12-speed\nMax chainring size\t1x: 32T\n\nComponents\nSaddle\tBontrager Montrose Elite, carbon rails, 138mm width\nSeatpost\tFOX Transfer SL, 125mm travel, internal routing, 31.6mm\nHandlebar\tBontrager Kovee Pro, ADV Carbon, 35mm, 5mm rise, 720mm width\nGrips\tBontrager XR Endurance Elite\nStem\tBontrager Kovee Pro, 35mm, Blendr compatible, 7 degree, 60mm length\nHeadset\tIntegrated, cartridge bearing, 1-1/8\" top, 1.5\" bottom\nBrake\tSRAM G2 Ultimate hydraulic disc, carbon levers, 180mm rotors\n\nAccessories\nBike computer\tBontrager Trip 300\nTool\tBontrager Flatline Pro pedal wrench, T25 Torx\n\n\n## Sizing & fit\n\n| Size | Rider Height | Inseam |\n|:----:|:------------------------:|:--------------------:|\n| S | 158 - 168 cm 5'2\" - 5'6\" | 74 - 78 cm 29\" - 31\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" | 78 - 82 cm 31\" - 32\" |\n| L | 173 - 183 cm 5'8\" - 6'0\" | 82 - 86 cm 32\" - 34\" |\n| XL | 180 - 193 cm 5'11\" - 6'4\" | 86 - 90 cm 34\" - 35\" |\n\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\nSizing table\n| Frame size letter | S | M | L | XL |\n|---------------------------|-------|-------|-------|-------|\n| Actual frame size | 15.5 | 17.5 | 19.5 | 21.5 |\n| Wheel size | 29\" | 29\" | 29\" | 29\" |\n| A — Seat tube | 39.9 | 43.0 | 47.0 | 51.0 |\n| B — Seat tube angle | 74.5° | 74.5° | 74.5° | 74.5° |\n| C — Head tube length | 9.0 | 10.0 | 11.0 | 12.0 |\n| D — Head angle | 68.0° | 68.0° | 68.0° | 68.0° |\n| E — Effective top tube | 57.8 | 59.7 | 61.6 | 63.6 |\n| F — Bottom bracket height | 33.0 | 33.0 | 33.0 | 33.0 |\n| G — Bottom bracket drop | 5.0 | 5.0 | 5.0 | 5.0 |\n| H — Chainstay length | 43.0 | 43.0 | 43.0 | 43.0 |\n| I — Offset | 4.2 | 4.2 | 4.2 | 4.2 |\n| J — Trail | 9.7 | 9.7 | 9.7 | 9.7 |\n| K — Wheelbase | 112.5 | 114.5 | 116.5 | 118.6 |\n| L — Standover | 75.9 | 77.8 | 81.5 | 84.2 |\n| M — Frame reach | 41.6 | 43.4 | 45.2 | 47.1 |\n| N — Frame stack | 58.2 | 58.9 | 59.3 | 59.9 |", "price": 1099.99, "tags": [ "bicycle", "mountain bike" ] }, { "name": "AURORA 11S E-MTB", "shortDescription": "The AURORA 11S is a powerful and stylish electric mountain bike designed to take you on thrilling off-road adventures. With its sturdy frame and premium components, this bike is built to handle any terrain. It features a high-performance motor, long-lasting battery, and advanced suspension system that guarantee a smooth and comfortable ride.", "description": "## Overview\nIt's right for you if...\nYou want a top-of-the-line e-MTB that is both powerful and stylish. You also want a bike that can handle any terrain, from steep climbs to rocky descents. With its advanced features and premium components, the AURORA 11S is designed for serious off-road riders who demand the best.\n\nThe tech you get\nA sturdy aluminum frame with advanced suspension system that provides 120mm of travel. A 750W brushless motor that delivers up to 28mph, and a 48V/14Ah lithium-ion battery that provides up to 60 miles of range on a single charge. An advanced 11-speed Shimano drivetrain with hydraulic disc brakes for precise shifting and reliable stopping power. \n\nThe final word\nThe AURORA 11S is a top-of-the-line e-MTB that delivers exceptional performance and style. Whether you're tackling steep climbs or hitting rocky descents, this bike is built to handle any terrain with ease. With its advanced features and premium components, the AURORA 11S is the perfect choice for serious off-road riders who demand the best.\n\n## Features\nPowerful and efficient\n\nThe AURORA 11S is equipped with a high-performance 750W brushless motor that delivers up to 28mph. The motor is powered by a long-lasting 48V/14Ah lithium-ion battery that provides up to 60 miles of range on a single charge.\n\nAdvanced suspension system\n\nThe bike's advanced suspension system provides 120mm of travel, ensuring a smooth and comfortable ride on any terrain. The front suspension is a Suntour XCR32 Air fork, while the rear suspension is a KS-281 hydraulic shock absorber.\n\nPremium components\n\nThe AURORA 11S features an advanced 11-speed Shimano drivetrain with hydraulic disc brakes. The bike is also equipped with a Tektro HD-E725 hydraulic disc brake system that provides reliable stopping power.\n\nSleek and stylish design\n\nWith its sleek and stylish design, the AURORA 11S is sure to turn heads on the trail. The bike's sturdy aluminum frame is available in a range of colors, including black, blue, and red.\n\n## Specs\nFrameset\nFrame Material: Aluminum\nFrame Size: S, M, L\nFork: Suntour XCR32 Air, 120mm Travel\nShock Absorber: KS-281 Hydraulic Shock Absorber\n\nWheels\nWheel Size: 27.5 inches\nTires: Kenda K1151 Nevegal, 27.5x2.35\nRims: Alloy Double Wall\nSpokes: 32H, Stainless Steel\n\nDrivetrain\nShifters: Shimano SL-M7000\nRear Derailleur: Shimano RD-M8000\nCrankset: Prowheel 42T, Alloy Crank Arm\nCassette: Shimano CS-M7000, 11-42T\nChain: KMC X11EPT\n\nBrakes\nBrake System: Tektro HD-E725 Hydraulic Disc Brake\nBrake Rotors: 180mm Front, 160mm Rear\n\nE-bike system\nMotor: 750W Brushless\nBattery: 48V/14Ah Lithium-Ion\nCharger: 48V/3A Smart Charger\nController: Intelligent Sinusoidal Wave\n\nWeight\nWeight: 59.5 lbs\n\n## Sizing & fit\n| Size | Rider Height | Standover Height |\n|------|-------------|-----------------|\n| S | 5'2\"-5'6\" | 28.5\" |\n| M | 5'7\"-6'0\" | 29.5\" |\n| L | 6'0\"-6'4\" | 30.5\" |\n\n## Geometry\nAll measurements provided in cm.\nSizing table\n| Frame size letter | S | M | L |\n|-------------------|-----|-----|-----|\n| Wheel Size | 27.5\"| 27.5\"| 27.5\"|\n| Seat tube length | 44.5| 48.5| 52.5|\n| Head tube angle | 68° | 68° | 68° |\n| Seat tube angle | 74.5°| 74.5°| 74.5°|\n| Effective top tube | 57.5| 59.5| 61.5|\n| Head tube length | 12.0| 12.0| 13.0|\n| Chainstay length | 45.5| 45.5| 45.5|\n| Bottom bracket height | 30.0| 30.0| 30.0|\n| Wheelbase | 115.0|116.5|118.5|", "price": 1999.99, "tags": [ "bicycle", "road bike" ] }, { "name": "VeloTech V9.5 AXS Gen 3", "shortDescription": "VeloTech V9.5 AXS is a sleek and fast carbon bike that combines high-end tech with a comfortable ride. It's designed to provide the ultimate experience for the most serious riders. The bike comes with a lightweight and powerful motor that can be activated when needed, and you get a spec filled with premium parts.", "description": "## Overview\nIt's right for you if...\nYou want a bike that is fast, efficient, and delivers an adrenaline-filled experience. You are looking for a bike that is built with cutting-edge technology, and you want a ride that is both comfortable and exciting.\n\nThe tech you get\nA lightweight and durable full carbon frame with a fork that has 100mm of travel. The bike comes with a powerful motor that can deliver up to 20 mph of assistance. The drivetrain is a wireless electronic system that is precise and reliable. The bike is also equipped with hydraulic disc brakes, tubeless-ready wheels, and comfortable grips.\n\nThe final word\nThe VeloTech V9.5 AXS is a high-end bike that delivers an incredible experience for serious riders. It combines the latest technology with a comfortable ride, making it perfect for long rides, tough climbs, and fast descents.\n\n## Features\nFast and efficient\nThe VeloTech V9.5 AXS comes with a powerful motor that can provide up to 20 mph of assistance. The motor is lightweight and efficient, providing a boost when you need it without adding bulk. The bike's battery is removable, allowing you to ride without assistance when you don't need it.\n\nSmart software for the trail\nThe VeloTech V9.5 AXS is equipped with intelligent software that delivers a smooth and responsive ride. The software allows the motor to respond immediately as you start to pedal, delivering more power over a wider cadence range. You can also customize your user settings to suit your preferences.\n\nComfortable ride\nThe VeloTech V9.5 AXS is designed to provide a comfortable ride, even on long rides. The bike's fork has 100mm of travel, providing ample cushioning for rough terrain. The bike's grips are also designed to provide a comfortable and secure grip, even on the most challenging rides.\n\n## Specs\nFrameset\nFrame\tCarbon fiber frame with internal cable routing and Boost148\nFork\t100mm of travel with remote lockout\nShock\tN/A\n\nWheels\nWheel front\tCarbon fiber tubeless-ready wheel\nWheel rear\tCarbon fiber tubeless-ready wheel\nSkewer rear\t12mm thru-axle\nTire\tTubeless-ready tire\nTire part\tTubeless sealant\n\nDrivetrain\nShifter\tWireless electronic shifter\nRear derailleur\tWireless electronic derailleur\nCrank\tCarbon fiber crankset with chainring\nCrank arm\tCarbon fiber crank arm\nChainring\tAlloy chainring\nCassette\t12-speed cassette\nChain\t12-speed chain\n\nComponents\nSaddle\tCarbon fiber saddle\nSeatpost\tCarbon fiber seatpost\nHandlebar\tCarbon fiber handlebar\nGrips\tComfortable and secure grips\nStem\tCarbon fiber stem\nHeadset\tCarbon fiber headset\nBrake\tHydraulic disc brakes\nBrake rotor\tDisc brake rotor\n\nAccessories\nE-bike system\tPowerful motor with removable battery\nBattery\tLithium-ion battery\nCharger\tFast charging adapter\nController\tHandlebar-mounted controller\nTool\tBasic toolkit\n\nWeight\nWeight\tM - 17.5 kg / 38.5 lbs (with tubeless sealant)\n\nWeight limit\nThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing & fit\n| Size | Rider Height | Inseam |\n|:----:|:------------------------:|:--------------------:|\n| S | 160 - 170 cm 5'3\" - 5'7\" | 74 - 79 cm 29\" - 31\" |\n| M | 170 - 180 cm 5'7\" - 5'11\" | 79 - 84 cm 31\" - 33\" |\n| L | 180 - 190 cm 5'11\" - 6'3\" | 84 - 89 cm 33\" - 35\" |\n| XL | 190 - 200 cm 6'3\" - 6'7\" | 89 - 94 cm 35\" - 37\" |\n\n## Geometry\nAll measurements provided in cm unless otherwise noted.\nSizing table\n| Frame size letter | S | M | L | XL |\n|---------------------------|-------|-------|-------|-------|\n| Actual frame size | 50.0 | 53.3 | 55.6 | 58.8 |\n| Wheel size | 29\" | 29\" | 29\" | 29\" |\n| A — Seat tube | 39.4 | 43.2 | 48.3 | 53.3 |\n| B — Seat tube angle | 72.3° | 72.6° | 72.8° | 72.8° |\n| C — Head tube length | 9.0 | 10.0 | 10.5 | 11.0 |\n| D — Head angle | 67.5° | 67.5° | 67.5° | 67.5° |\n| E — Effective top tube | 58.0 | 61.7 | 64.8 | 67.0 |\n| F — Bottom bracket height | 32.3 | 32.3 | 32.3 | 32.3 |\n| G — Bottom bracket drop | 5.0 | 5.0 | 5.0 | 5.0 |\n| H — Chainstay length | 44.7 | 44.7 | 44.7 | 44.7 |\n| I — Offset | 4.2 | 4.2 | 4.2 | 4.2 |\n| J — Trail | 10.9 | 10.9 | 10.9 | 10.9 |\n| K — Wheelbase | 112.6 | 116.5 | 119.7 | 121.9 |\n| L — Standover | 76.8 | 76.8 | 76.8 | 76.8 |\n| M — Frame reach | 40.5 | 44.0 | 47.0 | 49.0 |\n| N — Frame stack | 60.9 | 61.8 | 62.2 | 62.7 |", "price": 1699.99, "tags": [ "bicycle", "electric bike", "city bike" ] }, { "name": "Axiom D8 E-Mountain Bike", "shortDescription": "The Axiom D8 is an electrifying mountain bike that is built for adventure. It boasts a light aluminum frame, a powerful motor and the latest tech to tackle the toughest of terrains. The D8 provides assistance without adding bulk to the bike, giving you the flexibility to ride like a traditional mountain bike or have an extra push when you need it.", "description": "## Overview \nIt's right for you if... \nYou're looking for an electric mountain bike that can handle a wide variety of terrain, from flowing singletrack to technical descents. You also want a bike that offers a powerful motor that provides assistance without adding bulk to the bike. The D8 is designed to take you anywhere, quickly and comfortably.\n\nThe tech you get \nA lightweight aluminum frame with 140mm of travel, a Suntour fork with hydraulic lockout, and a reliable and powerful Bafang M400 mid-motor that provides a boost up to 20 mph. The bike features a Shimano Deore drivetrain, hydraulic disc brakes, and a dropper seat post. With the latest tech on-board, the D8 is designed to take you to new heights.\n\nThe final word \nThe Axiom D8 is an outstanding electric mountain bike that is designed for adventure. It's built with the latest tech and provides the flexibility to ride like a traditional mountain bike or have an extra push when you need it. Whether you're a beginner or an experienced rider, the D8 is the perfect companion for your next adventure.\n\n## Features \nBuilt for Adventure \n\nThe D8 features a lightweight aluminum frame that is built to withstand rugged terrain. It comes equipped with 140mm of travel and a Suntour fork that can handle even the toughest of trails. With this bike, you're ready to take on anything the mountain can throw at you.\n\nPowerful Motor \n\nThe Bafang M400 mid-motor provides reliable and powerful assistance without adding bulk to the bike. You can quickly and easily switch between the different assistance levels to find the perfect balance between range and power.\n\nShimano Deore Drivetrain \n\nThe Shimano Deore drivetrain is reliable and offers smooth shifting on any terrain. You can easily adjust the gears to match your riding style and maximize your performance on the mountain.\n\nDropper Seat Post \n\nThe dropper seat post allows you to easily adjust your seat height on the fly, so you can maintain the perfect position for any terrain. With the flick of a switch, you can quickly and easily lower or raise your seat to match the terrain.\n\nHydraulic Disc Brakes \n\nThe D8 features powerful hydraulic disc brakes that offer reliable stopping power in any weather condition. You can ride with confidence knowing that you have the brakes to stop on a dime.\n\n## Specs \nFrameset \nFrame\tAluminum frame with 140mm of travel \nFork\tSuntour fork with hydraulic lockout, 140mm of travel \nShock\tN/A \nMax compatible fork travel\t140mm \n \nWheels \nWheel front\tAlloy wheel \nWheel rear\tAlloy wheel \nSkewer rear\tThru axle \nTire\t29\" x 2.35\" \nTire part\tN/A \nMax tire size\t29\" x 2.6\" \n \nDrivetrain \nShifter\tShimano Deore \nRear derailleur\tShimano Deore \nCrank\tBafang M400 \nCrank arm\tN/A \nChainring\tN/A \nCassette\tShimano Deore \nChain\tShimano Deore \nMax chainring size\tN/A \n \nComponents \nSaddle\tAxiom D8 saddle \nSeatpost\tDropper seat post \nHandlebar\tAxiom D8 handlebar \nGrips\tAxiom D8 grips \nStem\tAxiom D8 stem \nHeadset\tAxiom D8 headset \nBrake\tHydraulic disc brakes \nBrake rotor\t180mm \n\nAccessories \nE-bike system\tBafang M400 mid-motor \nBattery\tLithium-ion battery, 500Wh \nCharger\tLithium-ion charger \nController\tBafang M400 controller \nTool\tN/A \n \nWeight \nWeight\tM - 22 kg / 48.5 lbs \nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 136 kg (300 lbs). \n \n \n## Sizing & fit \n \n| Size | Rider Height | Inseam | \n|:----:|:------------------------:|:--------------------:| \n| S | 152 - 165 cm 5'0\" - 5'5\" | 70 - 76 cm 27\" - 30\" | \n| M | 165 - 178 cm 5'5\" - 5'10\" | 76 - 81 cm 30\" - 32\" | \n| L | 178 - 185 cm 5'10\" - 6'1\" | 81 - 86 cm 32\" - 34\" | \n| XL | 185 - 193 cm 6'1\" - 6'4\" | 86 - 91 cm 34\" - 36\" | \n \n \n## Geometry \n \nAll measurements provided in cm unless otherwise noted. \nSizing table \n| Frame size letter | S | M | L | XL | \n|---------------------------|-------|-------|-------|-------| \n| Actual frame size | 41.9 | 46.5 | 50.8 | 55.9 | \n| Wheel size | 29\" | 29\" | 29\" | 29\" | \n| A — Seat tube | 42.0 | 46.5 | 51.0 | 56.0 | \n| B — Seat tube angle | 74.0° | 74.0° | 74.0° | 74.0° | \n| C — Head tube length | 11.0 | 12.0 | 13.0 | 15.0 | \n| D — Head angle | 68.0° | 68.0° | 68.0° | 68.0° | \n| E — Effective top tube | 57.0 | 60.0 | 62.0 | 65.0 | \n| F — Bottom bracket height | 33.0 | 33.0 | 33.0 | 33.0 | \n| G — Bottom bracket drop | 3.0 | 3.0 | 3.0 | 3.0 | \n| H — Chainstay length | 46.0 | 46.0 | 46.0 | 46.0 | \n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 | \n| J — Trail | 10.9 | 10.9 | 10.9 | 10.9 | \n| K — Wheelbase | 113.0 | 116.0 | 117.5 | 120.5 | \n| L — Standover | 73.5 | 75.5 | 76.5 | 79.5 | \n| M — Frame reach | 41.0 | 43.5 | 45.0 | 47.5 | \n| N — Frame stack | 60.5 | 61.5 | 62.5 | 64.5 |", "price": 1399.99, "tags": [ "bicycle", "electric bike", "mountain bike" ] }, { "name": "Velocity X1", "shortDescription": "Velocity X1 is a high-performance road bike designed for speed enthusiasts. It features a lightweight yet durable frame, aerodynamic design, and top-quality components, making it the perfect choice for those who want to take their cycling experience to the next level.", "description": "## Overview\nIt's right for you if...\nYou're an experienced cyclist looking for a bike that can keep up with your need for speed. You want a bike that's lightweight, aerodynamic, and built to perform, whether you're training for a race or just pushing yourself to go faster.\n\nThe tech you get\nA lightweight aluminum frame with a carbon fork, Shimano Ultegra groupset with a wide range of gearing, hydraulic disc brakes, aerodynamic carbon wheels, and a vibration-absorbing handlebar with ergonomic grips.\n\nThe final word\nVelocity X1 is the ultimate road bike for speed enthusiasts. Its lightweight frame, aerodynamic design, and top-quality components make it the perfect choice for those who want to take their cycling experience to the next level.\n\n\n## Features\n\nAerodynamic design\nVelocity X1 is built with an aerodynamic design to help you go faster with less effort. It features a sleek profile, hidden cables, and a carbon fork that cuts through the wind, reducing drag and increasing speed.\n\nHydraulic disc brakes\nVelocity X1 comes equipped with hydraulic disc brakes, providing excellent stopping power in all weather conditions. They're also low maintenance, with minimal adjustments needed over time.\n\nCarbon wheels\nThe Velocity X1's aerodynamic carbon wheels provide excellent speed and responsiveness, helping you achieve your fastest times yet. They're also lightweight, reducing overall bike weight and making acceleration and handling even easier.\n\nShimano Ultegra groupset\nThe Shimano Ultegra groupset provides smooth shifting and reliable performance, ensuring you get the most out of every ride. With a wide range of gearing options, it's ideal for tackling any terrain, from steep climbs to fast descents.\n\n\n## Specifications\nFrameset\nFrame with Fork\tAluminium frame, internal cable routing, 135x9mm QR\nFork\tCarbon, hidden cable routing, 100x9mm QR\n\nWheels\nWheel front\tCarbon, 30mm deep rim, 23mm width, 100x9mm QR\nWheel rear\tCarbon, 30mm deep rim, 23mm width, 135x9mm QR\nSkewer front\t100x9mm QR\nSkewer rear\t135x9mm QR\nTire\tContinental Grand Prix 5000, 700x25mm, folding bead\nMax tire size\t700x28mm without fenders\n\nDrivetrain\nShifter\tShimano Ultegra R8020, 11 speed\nRear derailleur\tShimano Ultegra R8000, 11 speed\n*Crank\tSize: S, M\nShimano Ultegra R8000, 50/34T, 170mm length\nSize: L, XL\nShimano Ultegra R8000, 50/34T, 175mm length\nBottom bracket\tShimano BB-RS500-PB, PressFit\nCassette\tShimano Ultegra R8000, 11-30T, 11 speed\nChain\tShimano Ultegra HG701, 11 speed\nPedal\tNot included\nMax chainring size\t50/34T\n\nComponents\nSaddle\tBontrager Montrose Comp, steel rails, 138mm width\nSeatpost\tBontrager Comp, 6061 alloy, 27.2mm, 8mm offset, 330mm length\n*Handlebar\tSize: S, M, L\nBontrager Elite Aero VR-CF, alloy, 31.8mm, 93mm reach, 123mm drop, 400mm width\nSize: XL\nBontrager Elite Aero VR-CF, alloy, 31.8mm, 93mm reach, 123mm drop, 420mm width\nGrips\tBontrager Supertack Perf tape\n*Stem\tSize: S, M, L\nBontrager Elite Blendr, 31.8mm clamp, 7 degree, 90mm length\nSize: XL\nBontrager Elite Blendr, 31.8mm clamp, 7 degree, 100mm length\nBrake\tShimano Ultegra R8070 hydraulic disc, flat mount\nBrake rotor\tShimano RT800, centerlock, 160mm\nRotor size\tMax brake rotor sizes: 160mm front & rear\n\nWeight\nWeight\tM - 8.15 kg / 17.97 lbs\nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 275 pounds (125 kg).\n\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| S | 162 - 170 cm 5'4\" - 5'7\" | 74 - 78 cm 29\" - 31\" |\n| M | 170 - 178 cm 5'7\" - 5'10\" | 77 - 82 cm 30\" - 32\" |\n| L | 178 - 186 cm 5'10\" - 6'1\" | 82 - 86 cm 32\" - 34\" |\n| XL | 186 - 196 cm 6'1\" - 6'5\" | 87 - 92 cm 34\" - 36\" |\n\n\n## Geometry\n| Frame size letter | S | M | L | XL |\n|---------------------------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 50.0 | 52.0 | 54.0 | 56.0 |\n| B — Seat tube angle | 74.0° | 73.5° | 73.0° | 72.5° |\n| C — Head tube length | 13.0 | 15.0 | 17.0 | 19.0 |\n| D — Head angle | 71.0° | 72.0° | 72.0° | 72.5° |\n| E — Effective top tube | 53.7 | 55.0 | 56.5 | 58.0 |\n| F — Bottom bracket height | 27.5 | 27.5 | 27.5 | 27.5 |\n| G — Bottom bracket drop | 7.3 | 7.3 | 7.3 | 7.3 |\n| H — Chainstay length | 41.0 | 41.0 | 41.0 | 41.0 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 6.0 | 6.0 | 6.0 | 5.8 |\n| K — Wheelbase | 98.2 | 99.1 | 100.1 | 101.0 |\n| L — Standover | 75.2 | 78.2 | 81.1 | 84.1 |\n| M — Frame reach | 37.5 | 38.3 | 39.1 | 39.9 |\n| N — Frame stack | 53.3 | 55.4 | 57.4 | 59.5 |", "price": 1799.99, "tags": [ "bicycle", "touring bike" ] }, { "name": "Velocity V9", "shortDescription": "Velocity V9 is a high-performance hybrid bike that combines speed and comfort for riders who demand the best of both worlds. The lightweight aluminum frame, along with the carbon fork and seat post, provide optimal stiffness and absorption to tackle any terrain. A 2x Shimano Deore drivetrain, hydraulic disc brakes, and 700c wheels with high-quality tires make it a versatile ride for commuters, fitness riders, and weekend adventurers alike.", "description": "## Overview\nIt's right for you if...\nYou want a fast, versatile bike that can handle anything from commuting to weekend adventures. You value comfort as much as speed and performance. You want a reliable and durable bike that will last for years to come.\n\nThe tech you get\nA lightweight aluminum frame with a carbon fork and seat post, a 2x Shimano Deore drivetrain with a wide range of gearing, hydraulic disc brakes, and 700c wheels with high-quality tires. The Velocity V9 is designed for riders who demand both performance and comfort in one package.\n\nThe final word\nThe Velocity V9 is the perfect bike for riders who want speed and performance without sacrificing comfort. The lightweight aluminum frame and carbon components provide optimal stiffness and absorption, while the 2x Shimano Deore drivetrain and hydraulic disc brakes ensure precise shifting and stopping power. Whether you're commuting, hitting the trails, or training for your next race, the Velocity V9 has everything you need to achieve your goals.\n\n## Features\n\n2x drivetrain\nA 2x drivetrain means more versatility and a wider range of gearing options. Whether you're climbing hills or sprinting on the flats, the Velocity V9 has the perfect gear for any situation.\n\nCarbon components\nThe Velocity V9 features a carbon fork and seat post to provide optimal stiffness and absorption. This means you can ride faster and more comfortably over any terrain.\n\nHydraulic disc brakes\nHydraulic disc brakes provide unparalleled stopping power and modulation in any weather condition. You'll feel confident and in control no matter where you ride.\n\n## Specifications\nFrameset\nFrame with Fork\tAluminum frame with carbon fork and seat post, internal cable routing, fender mounts, 135x5mm ThruSkew\nFork\tCarbon fork, hidden fender mounts, flat mount disc, 5x100mm thru-skew\n\nWheels\nWheel front\tDouble wall aluminum rims, 700c, quick release hub\nWheel rear\tDouble wall aluminum rims, 700c, quick release hub\nTire\tKenda Kwick Tendril, puncture resistant, reflective sidewall, 700x32c\nMax tire size\t700x35c without fenders, 700x32c with fenders\n\nDrivetrain\nShifter\tShimano Deore, 10 speed\nFront derailleur\tShimano Deore\nRear derailleur\tShimano Deore\nCrank\tShimano Deore, 46-30T, 170mm (S/M), 175mm (L/XL)\nBottom bracket\tShimano BB52, 68mm, threaded\nCassette\tShimano Deore, 11-36T, 10 speed\nChain\tShimano HG54, 10 speed\nPedal\tWellgo alloy platform\n\nComponents\nSaddle\tVelo VL-2158, steel rails\nSeatpost\tCarbon seat post, 27.2mm\nHandlebar\tAluminum, 31.8mm clamp, 15mm rise, 680mm width\nGrips\tVelo ergonomic grips\nStem\tAluminum, 31.8mm clamp, 7 degree, 90mm length\nBrake\tShimano hydraulic disc, MT200 lever, MT200 caliper\nBrake rotor\tShimano RT56, centerlock, 160mm\nRotor size\tMax brake rotor sizes: 160mm front & rear\n\nWeight\nWeight\tM - 11.5 kg / 25.35 lbs\nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| S | 155 - 165 cm 5'1\" - 5'5\" | 72 - 78 cm 28\" - 31\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n| XL | 186 - 197 cm 6'1\" - 6'6\" | 87 - 93 cm 34\" - 37\" |\n\n## Geometry\n| Frame size | S | M | L | XL |\n|--------------------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 44.0 | 48.0 | 52.0 | 56.0 |\n| B — Seat tube angle | 74.5° | 74.0° | 73.5° | 73.0° |\n| C — Head tube length | 14.5 | 16.0 | 18.0 | 20.0 |\n| D — Head angle | 71.0° | 71.0° | 71.5° | 71.5° |\n| E — Effective top tube | 56.5 | 57.5 | 58.5 | 59.5 |\n| F — Bottom bracket height | 27.0 | 27.0 | 27.0 | 27.0 |\n| G — Bottom bracket drop | 7.0 | 7.0 | 7.0 | 7.0 |\n| H — Chainstay length | 43.0 | 43.0 | 43.0 | 43.0 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 7.0 | 7.0 | 6.6 | 6.6 |\n| K — Wheelbase | 105.4 | 106.3 | 107.2 | 108.2 |\n| L — Standover | 73.2 | 77.1 | 81.2 | 85.1 |\n| M — Frame reach | 39.0 | 39.8 | 40.4 | 41.3 |\n| N — Frame stack | 57.0 | 58.5 | 60.0 | 61.5 |", "price": 2199.99, "tags": [ "bicycle", "electric bike", "mountain bike" ] }, { "name": "Aero Pro X", "shortDescription": "Aero Pro X is a high-end racing bike designed for serious cyclists who demand speed, agility, and superior performance. The lightweight carbon frame and fork, combined with the aerodynamic design, provide optimal stiffness and efficiency to maximize your speed. The bike features a 2x Shimano Ultegra drivetrain, hydraulic disc brakes, and 700c wheels with high-quality tires. Whether you're competing in a triathlon or climbing steep hills, Aero Pro X delivers exceptional performance and precision handling.", "description": "## Overview\nIt's right for you if...\nYou are a competitive cyclist looking for a bike that is designed for racing. You want a bike that delivers exceptional speed, agility, and precision handling. You demand superior performance and reliability from your equipment.\n\nThe tech you get\nA lightweight carbon frame with an aerodynamic design, a carbon fork with hidden fender mounts, a 2x Shimano Ultegra drivetrain with a wide range of gearing, hydraulic disc brakes, and 700c wheels with high-quality tires. Aero Pro X is designed for serious cyclists who demand nothing but the best.\n\nThe final word\nAero Pro X is the ultimate racing bike for serious cyclists. The lightweight carbon frame and aerodynamic design deliver maximum speed and efficiency, while the 2x Shimano Ultegra drivetrain and hydraulic disc brakes ensure precise shifting and stopping power. Whether you're competing in a triathlon or a criterium race, Aero Pro X delivers the performance you need to win.\n\n## Features\n\nAerodynamic design\nThe Aero Pro X features an aerodynamic design that reduces drag and maximizes efficiency. The bike is optimized for speed and agility, so you can ride faster and farther with less effort.\n\nHydraulic disc brakes\nHydraulic disc brakes provide unrivaled stopping power and modulation in any weather condition. You'll feel confident and in control no matter where you ride.\n\nCarbon components\nThe Aero Pro X features a carbon fork with hidden fender mounts to provide optimal stiffness and absorption. This means you can ride faster and more comfortably over any terrain.\n\n## Specifications\nFrameset\nFrame with Fork\tCarbon frame with an aerodynamic design, internal cable routing, 3s chain keeper, 142x12mm thru-axle\nFork\tCarbon fork with hidden fender mounts, flat mount disc, 100x12mm thru-axle\n\nWheels\nWheel front\tDouble wall carbon rims, 700c, thru-axle hub\nWheel rear\tDouble wall carbon rims, 700c, thru-axle hub\nTire\tContinental Grand Prix 5000, folding bead, 700x25c\nMax tire size\t700x28c without fenders, 700x25c with fenders\n\nDrivetrain\nShifter\tShimano Ultegra, 11 speed\nFront derailleur\tShimano Ultegra\nRear derailleur\tShimano Ultegra\nCrank\tShimano Ultegra, 52-36T, 170mm (S), 172.5mm (M), 175mm (L/XL)\nBottom bracket\tShimano BB72, 68mm, PressFit\nCassette\tShimano Ultegra, 11-30T, 11 speed\nChain\tShimano HG701, 11 speed\nPedal\tNot included\n\nComponents\nSaddle\tBontrager Montrose Elite, carbon rails, 138mm width\nSeatpost\tCarbon seat post, 27.2mm, 20mm offset\nHandlebar\tBontrager XXX Aero, carbon, 31.8mm clamp, 75mm reach, 125mm drop\nGrips\tBontrager Supertack Perf tape\nStem\tBontrager Pro, 31.8mm clamp, 7 degree, 90mm length\nBrake\tShimano hydraulic disc, Ultegra lever, Ultegra caliper\nBrake rotor\tShimano RT800, centerlock, 160mm\nRotor size\tMax brake rotor sizes: 160mm front & rear\n\nWeight\nWeight\tM - 8.36 kg / 18.42 lbs\nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 275 pounds (125 kg).\n\n## Sizing\n| Size | Rider Height |\n|:----:|:-------------------------:|\n| S | 155 - 165 cm 5'1\" - 5'5\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" |\n| XL | 186 - 197 cm 6'1\" - 6'6\" |\n\n## Geometry\n| Frame size | S | M | L | XL |\n|--------------------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 50.6 | 52.4 | 54.3 | 56.2 |\n| B — Seat tube angle | 75.5° | 74.5° | 73.5° | 72.5° |\n| C — Head tube length | 12.0 | 14.0 | 16.0 | 18.0 |\n| D — Head angle | 72.5° | 73.0° | 73.5° | 74.0° |\n| E — Effective top tube | 53.8 | 55.4 | 57.0 | 58.6 |\n| F — Bottom bracket height | 26.5 | 26.5 | 26.5 | 26.5 |\n| G — Bottom bracket drop | 7.0 | 7.0 | 7.0 | 7.0 |\n| H — Chainstay length | 41.0 | 41.0 | 41.0 | 41.0 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 6.0 | 6.0 | 6.0 | 6.0 |\n| K — Wheelbase | 97.1 | 98.7 | 100.2 | 101.8 |\n| L — Standover | 73.8 | 76.2 | 78.5 | 80.8 |\n| M — Frame reach | 38.8 | 39.5 | 40.2 | 40.9 |\n| N — Frame stack | 52.8 | 54.7 | 56.6 | 58.5 |", "price": 1599.99, "tags": [ "bicycle", "road bike" ] }, { "name": "Voltex+ Ultra Lowstep", "shortDescription": "Voltex+ Ultra Lowstep is a high-performance electric hybrid bike designed for riders who seek speed, comfort, and reliability during their everyday rides. Equipped with a powerful and efficient Voltex Drive Pro motor and a fully-integrated 600Wh battery, this e-bike allows you to cover longer distances on a single charge. The Voltex+ Ultra Lowstep comes with premium components that prioritize comfort and safety, such as a suspension seatpost, wide and stable tires, and integrated lights.", "description": "## Overview\n\nIt's right for you if...\nYou want an e-bike that provides a boost for faster rides and effortless usage. Durability is crucial, and you need a bike with one of the most powerful and efficient motors.\n\nThe tech you get\nA lightweight Delta Carbon Fiber frame with an ultra-lowstep design, a Voltex Drive Pro (350W, 75Nm) motor capable of maintaining speeds up to 30 mph, an extended range 600Wh battery integrated into the frame, and a Voltex Control Panel. Additionally, it features a 12-speed Shimano drivetrain, hydraulic disc brakes for optimal all-weather stopping power, a suspension seatpost, wide puncture-resistant tires for added stability, ergonomic grips, a kickstand, lights, and a cargo rack.\n\nThe final word\nThis bike offers enhanced enjoyment and ease of use on long commutes, leisure rides, and adventures. With its extended-range battery, powerful Voltex motor, user-friendly controller, and a seatpost that smooths out road vibrations, it guarantees an exceptional riding experience.\n\n## Features\n\nUltra-fast assistance\n\nExperience speeds up to 30 mph with the cutting-edge Voltex Drive Pro motor, allowing you to breeze through errands, commutes, and joyrides.\n\n## Specs\n\nFrameset\n- Frame: Delta Carbon Fiber, Removable Integrated Battery (RIB), sleek welds, rack & fender mounts, internal routing, kickstand mount, 135x5mm QR\n- Fork: Voltex Alloy, threaded steel steerer, rack mounts, post mount disc, 460mm axle-to-crown, ThruSkew 5mm QR\n- Max compatible fork travel: 50mm\n\nWheels\n- Hub front: Formula DC-20, alloy, 6-bolt, 5x100mm QR\n- Skewer front: 132x5mm QR, ThruSkew\n- Hub rear: Formula DC-22, alloy, 6-bolt, Shimano 8/9/10 freehub, 135x5mm QR\n- Skewer rear: 153x5mm bolt-on\n- Rim: Voltex Connection, double-wall, 32-hole, 20 mm width, Schrader valve\n- Tire: Voltex E6 Hard-Case Lite, reflective, wire bead, 60tpi, 700x50c\n- Max tire size: 700x50mm with or without fenders\n\nDrivetrain\n- Shifter: Shimano Deore XT M8100, 12-speed\n- Rear derailleur: Shimano Deore XT M8100, long cage\n- Crank: Voltex alloy, 170mm length\n- Chainring: FSA, 44T, aluminum with guard\n- Cassette: Shimano Deore XT M8100, 10-51, 12-speed\n- Chain: KMC E12 Turbo\n- Pedal: Voltex Urban pedals\n\nComponents\n- Saddle: Voltex Boulevard\n- Seatpost: Alloy, suspension, 31.6mm, 300mm length\n- Handlebar: Voltex alloy, 31.8mm, comfort sweep, 620mm width (XS, S, M), 660mm width (L)\n- Grips: Voltex Satellite Elite, alloy lock-on\n- Stem: Voltex alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 85mm length (XS, S), 105mm length (M, L)\n- Headset: VP sealed cartridge, 1-1/8'', threaded\n- Brake: Shimano MT520 hydraulic disc\n- Brake rotor: Shimano RT56, 6-bolt, 180mm (XS, S, M, L), 160mm (XS, S, M, L)\n\nAccessories\n- Battery: Voltex PowerTube 600Wh\n- Charger: Voltex compact 2A, 100-240V\n- Computer: Voltex Control Panel\n- Motor: Voltex Drive Pro, 75Nm, 30mph\n- Light: Voltex Solo for e-bike, taillight (XS, S, M, L), Voltex MR8, 180 lumen, 60 lux, LED, headlight (XS, S, M, L)\n- Kickstand: Adjustable length rear mount alloy kickstand\n- Cargo rack: Voltex-compatible alloy rear rack, maximum load 25 kg / 55 lbs\n- Fender: Voltex wide (XS, S, M, L), Voltex plastic (XS, S, M, L)\n\nWeight\n- Weight: M - 20.50 kg / 45.19 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 330 pounds (150 kg).\n\n## Sizing\n\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| XS | 147 - 155 cm 4'10\" - 5'1\" | 69 - 73 cm 27\" - 29\" |\n| S | 155 - 165 cm 5'1\" - 5'5\" | 72 - 78 cm 28\" - 31\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\n\nSizing table\n\n| Frame size number | 40 cm | 45 cm | 50 cm | 55 cm |\n|---------------------------|-------|-------|-------|-------|\n| Frame size letter | XS | S | M | L |\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 38.0 | 43.0 | 48.0 | 53.0 |\n| B — Seat tube angle | 70.5° | 70.5° | 70.5° | 70.5° |\n| C — Head tube length | 15.0 | 15.0 | 17.0 | 19.0 |\n| D — Head angle | 69.2° | 69.2° | 69.2° | 69.2° |\n| E — Effective top tube | 57.2 | 57.7 | 58.8 | 60.0 |\n| F — Bottom bracket height | 30.3 | 30.3 | 30.3 | 30.3 |\n| G — Bottom bracket drop | 6.0 | 6.0 | 6.0 | 6.0 |\n| H — Chainstay length | 48.5 | 48.5 | 48.5 | 48.5 |\n| I — Offset | 5.0 | 5.0 | 5.0 | 5.0 |\n| J — Trail | 9.0 | 9.0 | 9.0 | 9.0 |\n| K — Wheelbase | 111.8 | 112.3 | 113.6 | 114.8 |\n| L — Standover | 42.3 | 42.3 | 42.3 | 42.3 |\n| M — Frame reach | 36.0 | 38.0 | 38.0 | 38.0 |\n| N — Frame stack | 62.0 | 62.0 | 63.9 | 65.8 |\n| Stem length | 8.0 | 8.5 | 8.5 | 10.5 |\n\nPlease note that the specifications and features listed above are subject to change and may vary based on different models and versions of the Voltex+ Ultra Lowstep bike.", "price": 2999.99, "tags": [ "bicycle", "road bike", "professional" ] }, { "name": "SwiftRide Hybrid", "shortDescription": "SwiftRide Hybrid is a versatile and efficient bike designed for riders who want a smooth and enjoyable ride on various terrains. It incorporates advanced technology and high-quality components to provide a comfortable and reliable cycling experience.", "description": "## Overview\n\nIt's right for you if...\nYou are looking for a bike that combines the benefits of an electric bike with the versatility of a hybrid. You value durability, speed, and ease of use.\n\nThe tech you get\nThe SwiftRide Hybrid features a lightweight and durable aluminum frame, making it easy to handle and maneuver. It is equipped with a powerful electric motor that offers a speedy assist, helping you reach speeds of up to 25 mph. The bike comes with a removable and fully-integrated 500Wh battery, providing a long-range capacity for extended rides. It also includes a 10-speed Shimano drivetrain, hydraulic disc brakes for precise stopping power, wide puncture-resistant tires for stability, and integrated lights for enhanced visibility.\n\nThe final word\nThe SwiftRide Hybrid is designed for riders who want a bike that can handle daily commutes, recreational rides, and adventures. With its efficient motor, intuitive controls, and comfortable features, it offers an enjoyable and hassle-free riding experience.\n\n## Features\n\nEfficient electric assist\nExperience the thrill of effortless riding with the powerful electric motor that provides a speedy assist, making your everyday rides faster and more enjoyable.\n\n## Specs\n\nFrameset\n- Frame: Lightweight Aluminum, Removable Integrated Battery (RIB), rack & fender mounts, internal routing, 135x5mm QR\n- Fork: SwiftRide Alloy, threaded steel steerer, rack mounts, post mount disc, 460mm axle-to-crown, ThruSkew 5mm QR\n- Max compatible fork travel: 50mm\n\nWheels\n- Hub front: Formula DC-20, alloy, 6-bolt, 5x100mm QR\n- Skewer front: 132x5mm QR, ThruSkew\n- Hub rear: Formula DC-22, alloy, 6-bolt, Shimano 8/9/10 freehub, 135x5mm QR\n- Skewer rear: 153x5mm bolt-on\n- Rim: SwiftRide Connection, double-wall, 32-hole, 20 mm width, Schrader valve\n- Tire: SwiftRide E6 Hard-Case Lite, reflective, wire bead, 60tpi, 700x50c\n- Max tire size: 700x50mm with or without fenders\n\nDrivetrain\n- Shifter: Shimano Deore M4100, 10 speed\n- Rear derailleur: Shimano Deore M5120, long cage\n- Crank: ProWheel alloy, 170mm length\n- Chainring: FSA, 42T, steel w/guard\n- Cassette: Shimano Deore M4100, 11-42, 10 speed\n- Chain: KMC E10\n- Pedal: SwiftRide City pedals\n\nComponents\n- Saddle: SwiftRide Boulevard\n- Seatpost: Alloy, suspension, 31.6mm, 300mm length\n- Handlebar:\n - Size: XS, S, M - SwiftRide alloy, 31.8mm, comfort sweep, 620mm width\n - Size: L - SwiftRide alloy, 31.8mm, comfort sweep, 660mm width\n- Grips: SwiftRide Satellite Elite, alloy lock-on\n- Stem:\n - Size: XS, S - SwiftRide alloy quill, 31.8mm clamp, adjustable rise, 85mm length\n - Size: M, L - SwiftRide alloy quill, 31.8mm clamp, adjustable rise, 105mm length\n- Headset: VP sealed cartridge, 1-1/8'', threaded\n- Brake: Shimano MT200 hydraulic disc\n- Brake rotor:\n - Size: XS, S, M, L - Shimano RT26, 6-bolt, 180mm\n - Size: XS, S, M, L - Shimano RT26, 6-bolt, 160mm\n\nAccessories\n- Battery: SwiftRide PowerTube 500Wh\n- Charger: SwiftRide compact 2A, 100-240V\n- Computer: SwiftRide Purion\n- Motor: SwiftRide Performance Line Sport, 65Nm, 25mph\n- Light:\n - Size: XS, S, M, L - SwiftRide SOLO for e-bike, taillight\n - Size: XS, S, M, L - SwiftRide MR8, 180 lumen, 60 lux, LED, headlight\n- Kickstand: Adjustable length rear mount alloy kickstand\n- Cargo rack: SwiftRide-compatible alloy rear rack, maximum load 25 kg / 55 lbs\n- Fender:\n - Size: XS, S, M, L - SwiftRide wide\n - Size: XS, S, M, L - SwiftRide plastic\n\nWeight\n- Weight: M - 22.30 kg / 49.17 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| XS | 147 - 155 cm (4'10\" - 5'1\") | 69 - 73 cm (27\" - 29\") |\n| S | 155 - 165 cm (5'1\" - 5'5\") | 72 - 78 cm (28\" - 31\") |\n| M | 165 - 175 cm (5'5\" - 5'9\") | 77 - 83 cm (30\" - 33\") |\n| L | 175 - 186 cm (5'9\" - 6'1\") | 82 - 88 cm (32\" - 35\") |\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\n\nSizing table\n| Frame size number | 40 cm | 45 cm | 50 cm | 55 cm |\n|---------------------------|-------|-------|-------|-------|\n| Frame size letter | XS | S | M | L |\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 39.0 | 44.0 | 50.0 | 55.0 |\n| B — Seat tube angle | 71.0° | 71.0° | 71.0° | 71.0° |\n| C — Head tube length | 16.0 | 16.0 | 18.0 | 20.0 |\n| D — Head angle | 68.2° | 68.2° | 68.2° | 68.2° |\n| E — Effective top tube | 58.2 | 58.7 | 59.8 | 61.0 |\n| F — Bottom bracket height | 29.4 | 29.4 | 29.4 | 29.4 |\n| G — Bottom bracket drop | 6.5 | 6.5 | 6.5 | 6.5 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 9.5 | 9.5 | 9.5 | 9.5 |\n| K — Wheelbase | 112.2 | 112.7 | 114.0 | 115.2 |\n| L — Standover | 43.3 | 43.3 | 43.3 | 43.3 |\n| M — Frame reach | 36.5 | 38.5 | 38.5 | 38.5 |\n| N — Frame stack | 63.0 | 63.0 | 64.9 | 66.8 |\n| Stem length | 8.5 | 9.0 | 9.0 | 11.0 |", "price": 3999.99, "tags": [ "bicycle", "mountain bike", "professional" ] }, { "name": "RoadRunner E-Speed Lowstep", "shortDescription": "RoadRunner E-Speed Lowstep is a high-performance electric hybrid designed for riders seeking speed and excitement on their daily rides. It is equipped with a powerful and reliable ThunderBolt drive unit that offers exceptional acceleration. The bike features a fully-integrated 500Wh battery, allowing riders to cover longer distances on a single charge. With its comfortable and safe components, including a suspension seatpost, wide and stable tires, and integrated lights, the RoadRunner E-Speed Lowstep ensures a smooth and enjoyable ride.", "description": "## Overview\n\nIt's right for you if...\nYou're looking for an e-bike that provides an extra boost to reach your destination quickly and effortlessly. You prioritize durability and want a bike with one of the fastest motors available.\n\nThe tech you get\nA lightweight and sturdy ThunderBolt aluminum frame with a lowstep geometry. The bike is equipped with a ThunderBolt Performance Sport (250W, 65Nm) drive unit capable of reaching speeds up to 28 mph. It features a long-range 500Wh battery fully integrated into the frame and a ThunderBolt controller. Additionally, the bike has a 10-speed Shimano drivetrain, hydraulic disc brakes for reliable stopping power in all weather conditions, a suspension seatpost, wide puncture-resistant tires for stability, ergonomic grips, a kickstand, lights, and a rack and fenders.\n\nThe final word\nThe RoadRunner E-Speed Lowstep is designed to provide enjoyment and ease of use on longer commutes, recreational rides, and adventurous journeys. Its long-range battery, fast ThunderBolt motor, intuitive controller, and road-smoothing suspension seatpost make it the perfect choice for riders seeking both comfort and speed.\n\n## Features\n\nSuper speedy assist\n\nThe ThunderBolt Performance Sport drive unit allows you to accelerate up to 28mph, making errands, commutes, and joyrides a breeze.\n\n## Specs\n\nFrameset\n- Frame: ThunderBolt Smooth Aluminum, Removable Integrated Battery (RIB), sleek welds, rack & fender mounts, internal routing, kickstand mount, 135x5mm QR\n- Fork: RoadRunner Alloy, threaded steel steerer, rack mounts, post mount disc, 460mm axle-to-crown, ThruSkew 5mm QR\n- Max compatible fork travel: 50mm\n\nWheels\n- Hub front: ThunderBolt DC-20, alloy, 6-bolt, 5x100mm QR\n- Skewer front: 132x5mm QR, ThruSkew\n- Hub rear: ThunderBolt DC-22, alloy, 6-bolt, Shimano 8/9/10 freehub, 135x5mm QR\n- Skewer rear: 153x5mm bolt-on\n- Rim: ThunderBolt Connection, double-wall, 32-hole, 20 mm width, Schrader valve\n- Tire: ThunderBolt E6 Hard-Case Lite, reflective, wire bead, 60tpi, 700x50c\n- Max tire size: 700x50mm with or without fenders\n\nDrivetrain\n- Shifter: Shimano Deore M4100, 10 speed\n- Rear derailleur: Shimano Deore M5120, long cage\n- Crank: ProWheel alloy, 170mm length\n- Chainring: FSA, 42T, steel w/guard\n- Cassette: Shimano Deore M4100, 11-42, 10 speed\n- Chain: KMC E10\n- Pedal: RoadRunner City pedals\n\nComponents\n- Saddle: RoadRunner Boulevard\n- Seatpost: Alloy, suspension, 31.6mm, 300mm length\n- Handlebar:\n - Size: XS, S, M - RoadRunner alloy, 31.8mm, comfort sweep, 620mm width\n - Size: L - RoadRunner alloy, 31.8mm, comfort sweep, 660mm width\n- Grips: RoadRunner Satellite Elite, alloy lock-on\n- Stem:\n - Size: XS, S - RoadRunner alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 85mm length\n - Size: M, L - RoadRunner alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 105mm length\n- Headset: VP sealed cartridge, 1-1/8'', threaded\n- Brake: Shimano MT200 hydraulic disc\n- Brake rotor:\n - Size: XS, S, M, L - Shimano RT26, 6-bolt, 180mm\n - Size: XS, S, M, L - Shimano RT26, 6-bolt, 160mm\n\nAccessories\n- Battery: ThunderBolt PowerTube 500Wh\n- Charger: ThunderBolt compact 2A, 100-240V\n- Computer: ThunderBolt Purion\n- Motor: ThunderBolt Performance Line Sport, 65Nm, 28mph\n- Light:\n - Size: XS, S, M, L - ThunderBolt SOLO for e-bike, taillight\n - Size: XS, S, M, L - ThunderBolt MR8, 180 lumen, 60 lux, LED, headlight\n- Kickstand: Adjustable length rear mount alloy kickstand\n- Cargo rack: MIK-compatible alloy rear rack, maximum load 25 kg / 55 lbs\n- Fender:\n - Size: XS, S, M, L - RoadRunner wide\n - Size: XS, S, M, L - RoadRunner plastic\n\nWeight\n- Weight: M - 22.30 kg / 49.17 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| XS | 147 - 155 cm 4'10\" - 5'1\" | 69 - 73 cm 27\" - 29\" |\n| S | 155 - 165 cm 5'1\" - 5'5\" | 72 - 78 cm 28\" - 31\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\n\nSizing table\n| Frame size number | 40 cm | 45 cm | 50 cm | 55 cm |\n|---------------------------|-------|-------|-------|-------|\n| Frame size letter | XS | S | M | L |\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 39.0 | 44.0 | 50.0 | 55.0 |\n| B — Seat tube angle | 71.0° | 71.0° | 71.0° | 71.0° |\n| C — Head tube length | 16.0 | 16.0 | 18.0 | 20.0 |\n| D — Head angle | 68.2° | 68.2° | 68.2° | 68.2° |\n| E — Effective top tube | 58.2 | 58.7 | 59.8 | 61.0 |\n| F — Bottom bracket height | 29.4 | 29.4 | 29.4 | 29.4 |\n| G — Bottom bracket drop | 6.5 | 6.5 | 6.5 | 6.5 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 9.5 | 9.5 | 9.5 | 9.5 |\n| K — Wheelbase | 112.2 | 112.7 | 114.0 | 115.2 |\n| L — Standover | 43.3 | 43.3 | 43.3 | 43.3 |\n| M — Frame reach | 36.5 | 38.5 | 38.5 | 38.5 |\n| N — Frame stack | 63.0 | 63.0 | 64.9 | 66.8 |\n| Stem length | 8.5 | 9.0 | 9.0 | 11.0 |", "price": 4999.99, "tags": [ "bicycle", "road bike", "professional" ] }, { "name": "Hyperdrive Turbo X1", "shortDescription": "Hyperdrive Turbo X1 is a high-performance electric bike designed for riders seeking an exhilarating experience on their daily rides. It features a powerful and efficient Hyperdrive Sport drive unit and a sleek, integrated 500Wh battery for extended range. This e-bike is equipped with top-of-the-line components prioritizing comfort and safety, including a suspension seatpost, wide and stable tires, and integrated lights.", "description": "## Overview\n\nIt's right for you if...\nYou crave the thrill of an e-bike that can accelerate rapidly, reaching high speeds effortlessly. You value durability and are looking for a bike that is equipped with one of the fastest motors available.\n\nThe tech you get\nA lightweight Hyper Alloy frame with a lowstep geometry, a Hyperdrive Sport (300W, 70Nm) drive unit capable of maintaining speeds up to 30 mph, a long-range 500Wh battery seamlessly integrated into the frame, and an intuitive Hyper Control controller. Additionally, it features a 10-speed Shimano drivetrain, hydraulic disc brakes for reliable stopping power in all weather conditions, a suspension seatpost, wide puncture-resistant tires for enhanced stability, ergonomic grips, a kickstand, lights, and a rack and fenders.\n\nThe final word\nThis bike is designed for riders seeking enjoyment and convenience on longer commutes, recreational rides, and thrilling adventures. With its long-range battery, high-speed motor, user-friendly controller, and smooth-riding suspension seatpost, the Hyperdrive Turbo X1 guarantees an exceptional e-biking experience.\n\n## Features\n\nHyperboost Acceleration\nExperience adrenaline-inducing rides with the powerful Hyperdrive Sport drive unit that enables quick acceleration and effortless cruising through errands, commutes, and joyrides.\n\n## Specs\n\nFrameset\nFrame\tHyper Alloy, Removable Integrated Battery (RIB), seamless welds, rack & fender mounts, internal routing, kickstand mount, 135x5mm QR\nFork\tHyper Alloy, threaded steel steerer, rack mounts, post mount disc, 460mm axle-to-crown, ThruSkew 5mm QR\nMax compatible fork travel\t50mm\n\nWheels\nHub front\tFormula DC-20, alloy, 6-bolt, 5x100mm QR\nSkewer front\t132x5mm QR, ThruSkew\nHub rear\tFormula DC-22, alloy, 6-bolt, Shimano 8/9/10 freehub, 135x5mm QR\nSkewer rear\t153x5mm bolt-on\nRim\tHyper Connection, double-wall, 32-hole, 20 mm width, Schrader valve\nTire\tHyper E6 Hard-Case Lite, reflective, wire bead, 60tpi, 700x50c\nMax tire size\t700x50mm with or without fenders\n\nDrivetrain\nShifter\tShimano Deore M4100, 10 speed\nRear derailleur\tShimano Deore M5120, long cage\nCrank\tProWheel alloy, 170mm length\nChainring\tFSA, 42T, steel w/guard\nCassette\tShimano Deore M4100, 11-42, 10 speed\nChain\tKMC E10\nPedal\tHyper City pedals\n\nComponents\nSaddle\tHyper Boulevard\nSeatpost\tAlloy, suspension, 31.6mm, 300mm length\n*Handlebar\tSize: XS, S, M\nHyper alloy, 31.8mm, comfort sweep, 620mm width\nSize: L\nHyper alloy, 31.8mm, comfort sweep, 660mm width\nGrips\tHyper Satellite Elite, alloy lock-on\n*Stem\tSize: XS, S\nHyper alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 85mm length\nSize: M, L\nHyper alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 105mm length\nHeadset\tVP sealed cartridge, 1-1/8'', threaded\nBrake\tShimano MT200 hydraulic disc\n*Brake rotor\tSize: XS, S, M, L\nShimano RT26, 6-bolt,180mm\nSize: XS, S, M, L\nShimano RT26, 6-bolt,160mm\n\nAccessories\nBattery\tHyper PowerTube 500Wh\nCharger\tHyper compact 2A, 100-240V\nComputer\tHyper Control\nMotor\tHyperdrive Sport, 70Nm, 30mph\n*Light\tSize: XS, S, M, L\nSpanninga SOLO for e-bike, taillight\nSize: XS, S, M, L\nHerrmans MR8, 180 lumen, 60 lux, LED, headlight\nKickstand\tAdjustable length rear mount alloy kickstand\nCargo rack\tMIK-compatible alloy rear rack, maximum load 25 kg / 55 lbs\n*Fender\tSize: XS, S, M, L\nSKS wide\nSize: XS, S, M, L\nSKS plastic\n\nWeight\nWeight\tM - 22.30 kg / 49.17 lbs\nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| XS | 147 - 155 cm 4'10\" - 5'1\" | 69 - 73 cm 27\" - 29\" |\n| S | 155 - 165 cm 5'1\" - 5'5\" | 72 - 78 cm 28\" - 31\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\n\n| Frame size number | 40 cm | 45 cm | 50 cm | 55 cm |\n|---------------------------|-------|-------|-------|-------|\n| Frame size letter | XS | S | M | L |\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 39.0 | 44.0 | 50.0 | 55.0 |\n| B — Seat tube angle | 71.0° | 71.0° | 71.0° | 71.0° |\n| C — Head tube length | 16.0 | 16.0 | 18.0 | 20.0 |\n| D — Head angle | 68.2° | 68.2° | 68.2° | 68.2° |\n| E — Effective top tube | 58.2 | 58.7 | 59.8 | 61.0 |\n| F — Bottom bracket height | 29.4 | 29.4 | 29.4 | 29.4 |\n| G — Bottom bracket drop | 6.5 | 6.5 | 6.5 | 6.5 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 9.5 | 9.5 | 9.5 | 9.5 |\n| K — Wheelbase | 112.2 | 112.7 | 114.0 | 115.2 |\n| L — Standover | 43.3 | 43.3 | 43.3 | 43.3 |\n| M — Frame reach | 36.5 | 38.5 | 38.5 | 38.5 |\n| N — Frame stack | 63.0 | 63.0 | 64.9 | 66.8 |\n| Stem length | 8.5 | 9.0 | 9.0 | 11.0 |", "price": 1999.99, "tags": [ "bicycle", "city bike", "professional" ] }, { "name": "Horizon+ Evo Lowstep", "shortDescription": "The Horizon+ Evo Lowstep is a versatile electric hybrid bike designed for riders seeking a thrilling and efficient riding experience on a variety of terrains. With its powerful Bosch Performance Line Sport drive unit and integrated 500Wh battery, this e-bike enables riders to cover long distances with ease. Equipped with features prioritizing comfort and safety, such as a suspension seatpost, stable tires, and integrated lights, the Horizon+ Evo Lowstep is a reliable companion for everyday rides.", "description": "## Overview\n\nIt's right for you if...\nYou desire the convenience and speed of an e-bike to enhance your riding, and you want an intuitive and durable bicycle. You prioritize having one of the fastest motors developed by Bosch.\n\nThe tech you get\nA lightweight Alpha Smooth Aluminum frame with a lowstep geometry, a Bosch Performance Line Sport (250W, 65Nm) drive unit capable of sustaining speeds up to 28 mph, a fully encased 500Wh battery integrated into the frame, and a Bosch Purion controller. Additionally, it features a 10-speed Shimano drivetrain, hydraulic disc brakes for reliable stopping power in all weather conditions, a suspension seatpost, wide puncture-resistant tires for improved stability, ergonomic grips, a kickstand, lights, and a rack and fenders.\n\nThe final word\nThe Horizon+ Evo Lowstep offers an enjoyable and user-friendly riding experience for longer commutes, recreational rides, and adventures. It boasts an extended range battery, a high-performance Bosch motor, an intuitive controller, and a suspension seatpost for a smooth ride on various road surfaces.\n\n## Features\n\nSuper speedy assist\nExperience effortless cruising through errands, commutes, and joyrides with the new Bosch Performance Sport drive unit, allowing acceleration of up to 28 mph.\n\n## Specs\n\nFrameset\n- Frame: Alpha Platinum Aluminum, Removable Integrated Battery (RIB), smooth welds, rack & fender mounts, internal routing, kickstand mount, 135x5mm QR\n- Fork: Horizon Alloy, threaded steel steerer, rack mounts, post mount disc, 460mm axle-to-crown, ThruSkew 5mm QR\n- Max compatible fork travel: 50mm\n\nWheels\n- Front Hub: Formula DC-20, alloy, 6-bolt, 5x100mm QR\n- Front Skewer: 132x5mm QR, ThruSkew\n- Rear Hub: Formula DC-22, alloy, 6-bolt, Shimano 8/9/10 freehub, 135x5mm QR\n- Rear Skewer: 153x5mm bolt-on\n- Rim: Bontrager Connection, double-wall, 32-hole, 20mm width, Schrader valve\n- Tire: Bontrager E6 Hard-Case Lite, reflective, wire bead, 60tpi, 700x50c\n- Max tire size: 700x50mm with or without fenders\n\nDrivetrain\n- Shifter: Shimano Deore M4100, 10-speed\n- Rear Derailleur: Shimano Deore M5120, long cage\n- Crank: ProWheel alloy, 170mm length\n- Chainring: FSA, 42T, steel w/guard\n- Cassette: Shimano Deore M4100, 11-42, 10-speed\n- Chain: KMC E10\n- Pedal: Bontrager City pedals\n\nComponents\n- Saddle: Bontrager Boulevard\n- Seatpost: Alloy, suspension, 31.6mm, 300mm length\n- Handlebar:\n - Size: XS, S, M - Bontrager alloy, 31.8mm, comfort sweep, 620mm width\n - Size: L - Bontrager alloy, 31.8mm, comfort sweep, 660mm width\n- Grips: Bontrager Satellite Elite, alloy lock-on\n- Stem:\n - Size: XS, S - Bontrager alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 85mm length\n - Size: M, L - Bontrager alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 105mm length\n- Headset: VP sealed cartridge, 1-1/8\", threaded\n- Brake: Shimano MT200 hydraulic disc\n- Brake rotor:\n - Size: XS, S, M, L - Shimano RT26, 6-bolt, 180mm\n - Size: XS, S, M, L - Shimano RT26, 6-bolt, 160mm\n\nAccessories\n- Battery: Bosch PowerTube 500Wh\n- Charger: Bosch compact 2A, 100-240V\n- Computer: Bosch Purion\n- Motor: Bosch Performance Line Sport, 65Nm, 28mph\n- Light:\n - Size: XS, S, M, L - Spanninga SOLO for e-bike, taillight\n - Size: XS, S, M, L - Herrmans MR8, 180 lumen, 60 lux, LED, headlight\n- Kickstand: Adjustable length rear mount alloy kickstand\n- Cargo rack: MIK-compatible alloy rear rack, maximum load 25 kg / 55 lbs\n- Fender:\n - Size: XS, S, M, L - SKS wide\n - Size: XS, S, M, L - SKS plastic\n\nWeight\n- Weight: M - 22.30 kg / 49.17 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| XS | 147 - 155 cm 4'10\" - 5'1\" | 69 - 73 cm 27\" - 29\" |\n| S | 155 - 165 cm 5'1\" - 5'5\" | 72 - 78 cm 28\" - 31\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\nSizing table\n| Frame size number | 40 cm | 45 cm | 50 cm | 55 cm |\n|---------------------------|-------|-------|-------|-------|\n| Frame size letter | XS | S | M | L |\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 39.0 | 44.0 | 50.0 | 55.0 |\n| B — Seat tube angle | 71.0° | 71.0° | 71.0° | 71.0° |\n| C — Head tube length | 16.0 | 16.0 | 18.0 | 20.0 |\n| D — Head angle | 68.2° | 68.2° | 68.2° | 68.2° |\n| E — Effective top tube | 58.2 | 58.7 | 59.8 | 61.0 |\n| F — Bottom bracket height | 29.4 | 29.4 | 29.4 | 29.4 |\n| G — Bottom bracket drop | 6.5 | 6.5 | 6.5 | 6.5 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 9.5 | 9.5 | 9.5 | 9.5 |\n| K — Wheelbase | 112.2 | 112.7 | 114.0 | 115.2 |\n| L — Standover | 43.3 | 43.3 | 43.3 | 43.3 |\n| M — Frame reach | 36.5 | 38.5 | 38.5 | 38.5 |\n| N — Frame stack | 63.0 | 63.0 | 64.9 | 66.8 |\n| Stem length | 8.5 | 9.0 | 9.0 | 11.0 |", "price": 4499.99, "tags": [ "bicycle", "road bike", "professional" ] }, { "name": "FastRider X1", "shortDescription": "FastRider X1 is a high-performance e-bike designed for riders seeking speed and long-distance capabilities. Equipped with a powerful motor and a high-capacity battery, the FastRider X1 is perfect for daily commuters and e-bike enthusiasts. It boasts a sleek and functional design, making it a great alternative to car transportation. The bike also features a smartphone controller for easy navigation and entertainment options.", "description": "## Overview\nIt's right for you if...\nYou're looking for an e-bike that offers both speed and endurance. The FastRider X1 comes with a high-performance motor and a long-lasting battery, making it ideal for long-distance rides.\n\nThe tech you get\nThe FastRider X1 features a state-of-the-art motor and a spacious battery, ensuring a fast and efficient ride.\n\nThe final word\nWith the powerful motor and long-range battery, the FastRider X1 allows you to cover more distance at higher speeds.\n\n## Features\nConnect Your Ride with the FastRider App\nDownload the FastRider app and transform your smartphone into an on-board computer. Easily dock and charge your phone with the smartphone controller, and use the thumb pad on your handlebar to make calls, listen to music, get turn-by-turn directions, and more. The app also allows you to connect with fitness and health apps, syncing your routes and ride data.\n\nGoodbye, Car. Hello, Extended Range!\nWith the option to add the Range Boost feature, you can attach a second long-range battery to your FastRider X1, doubling the distance and time between charges. This enhancement allows you to ride longer, commute farther, and take on more adventurous routes.\n\nWhat is the range?\nTo estimate the distance you can travel on a single charge, use our range calculator tool. It automatically fills in the variables for this specific bike model and assumes an average rider, but you can adjust the settings to get the most accurate estimate for your needs.\n\n## Specifications\nFrameset\n- Frame: High-performance hydroformed alloy, Removable Integrated Battery, Range Boost-compatible, internal cable routing, Motor Armour, post-mount disc, 135x5 mm QR\n- Fork: FastRider rigid alloy fork, 1-1/8'' steel steerer, 100x15mm thru axle, post mount disc brake\n- Max compatible fork travel: 63mm\n\nWheels\n- Front Hub: FastRider sealed bearing, 32-hole 15mm alloy thru-axle\n- Front Skewer: FastRider Switch thru axle, removable lever\n- Rear Hub: FastRider alloy, sealed bearing, 6-bolt, 135x5mm QR\n- Rear Skewer: 148x5mm bolt-on\n- Rim: FastRider MD35, tubeless compatible, 32-hole, 35mm width, Presta valve\n- Spokes: Size: M, L, XL - 14g stainless steel, black\n- Tire: FastRider E6 Hard-Case Lite, reflective strip, 27.5x2.40''\n- Max tire size: 27.5x2.40\"\n\nDrivetrain\n- Shifter: Shimano Deore M4100, 10 speed\n- Rear derailleur: Size: M, L, XL - Shimano Deore M5120, long cage\n- Crank: Size: M - FastRider alloy, 170mm length / Size: L, XL - FastRider alloy, 175mm length\n- Chainring: FastRider 46T narrow/wide alloy, w/alloy guard\n- Cassette: Size: M, L, XL - Shimano Deore M4100, 11-42, 10 speed\n- Chain: Size: M, L, XL - KMC E10 / Size: M, L, XL - KMC X10e\n- Pedal: Size: M, L, XL - FastRider City pedals / Size: M, L, XL - Wellgo C157, boron axle, plastic body / Size: M, L, XL - slip-proof aluminum pedals with reflectors\n- Max chainring size: 1x: 48T\n\nComponents\n- Saddle: FastRider Commuter Comp\n- Seatpost: FastRider Comp, 6061 alloy, 31.6mm, 8mm offset, 330mm length\n- Handlebar: Size: M - FastRider alloy, 31.8mm, 15mm rise, 600mm width / Size: L, XL - FastRider alloy, 31.8mm, 15mm rise, 660mm width\n- Grips: FastRider Satellite Elite, alloy lock-on\n- Stem: Size: M - FastRider alloy, 31.8mm, Blendr compatible, 7-degree, 70mm length / Size: L - FastRider alloy, 31.8mm, Blendr compatible, 7-degree, 90mm length / Size: XL - FastRider alloy, 31.8mm, Blendr compatible, 7-degree, 100mm length\n- Headset: Size: M, L, XL - FSA IS-2 alloy, integrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom / Size: M, L, XL - FSA Integrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom\n- Brake: Shimano MT520 4-piston hydraulic disc, post-mount, 180mm rotor\n- Brake rotor: Shimano RT56, 6-bolt, 180mm\n- Rotor size: Max brake rotor sizes: 180mm front & rear\n\nAccessories\n- Battery: FastRider PowerTube 625Wh\n- Charger: FastRider standard 4A, 100-240V\n- Motor: FastRider Performance Speed, 85 Nm, 28 mph / 45 kph\n- Light: Size: M, L, XL - FastRider taillight, 50 lumens / Size: M, L, XL - FastRider headlight, 500 lumens\n- Kickstand: Size: M, L, XL - Rear mount, alloy / Size: M, L, XL - Adjustable length alloy kickstand\n- Cargo rack: FastRider integrated rear rack, aluminum\n- Fender: FastRider custom aluminum\n\nWeight\n- Weight: M - 25.54 kg / 56.3 lbs\n\nWeight limit\n- This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:------------------------:|:--------------------:|\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n| XL | 186 - 197 cm 6'1\" - 6'6\" | 87 - 93 cm 34\" - 37\" |\n\n## Geometry\n| Frame size letter | M | L | XL |\n|---------------------------|-------|-------|-------|\n| Wheel size | 27.5\" | 27.5\" | 27.5\" |\n| A — Seat tube | 44.6 | 49.1 | 53.4 |\n| B — Seat tube angle | 73.0° | 73.0° | 73.0° |\n| C — Head tube length | 16.5 | 19.5 | 23.0 |\n| D — Head angle | 69.5° | 70.0° | 70.5° |\n| E — Effective top tube | 59.5 | 60.7 | 62.2 |\n| F — Bottom bracket height | 29.5 | 29.5 | 29.5 |\n| G — Bottom bracket drop | 6.0 | 6.0 | 6.0 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.4 | 4.4 | 4.4 |\n| J — Trail | 8.6 | 8.1 | 7.9 |\n| K — Wheelbase | 114.6 | 115.0 | 116.4 |\n| L — Standover | 79.5 | 83.7 | 87.9 |\n| M — Frame reach | 40.5 | 40.8 | 41.2 |\n| N — Frame stack | 62.3 | 65.2 | 68.8 |", "price": 5499.99, "tags": [ "bicycle", "mountain bike", "professional" ] }, { "name": "SonicRide 8S", "shortDescription": "SonicRide 8S is a high-performance e-bike designed for riders who crave speed and long-distance capabilities. The advanced SonicDrive motor provides powerful assistance up to 28 mph, combined with a durable and long-lasting battery for extended rides. With its sleek design and thoughtful features, the SonicRide 8S is perfect for those who prefer the freedom of riding a bike over driving a car. Plus, it comes equipped with a smartphone controller for easy navigation, music, and more.", "description": "## Overview\nIt's right for you if...\nYou want a fast and efficient e-bike that can take you long distances. The SonicRide 8S features a hydroformed aluminum frame with a concealed 625Wh battery, a high-powered SonicDrive motor, and a Smartphone Controller. It also includes essential accessories such as lights, fenders, and a rear rack.\n\nThe tech you get\nThe SonicRide 8S is equipped with the fastest SonicDrive motor, ensuring exhilarating rides at high speeds. The long-range battery is perfect for commuters and riders looking to explore new horizons.\n\nThe final word\nWith the SonicDrive motor and long-lasting battery, you can enjoy extended rides at higher speeds.\n\n## Features\n\nConnect Your Ride with SonicRide App\nDownload the SonicRide app and transform your phone into an onboard computer. Simply attach it to the Smartphone Controller for docking and charging. Use the thumb pad on your handlebar to control calls, music, directions, and more. The Bluetooth® wireless technology allows you to connect with fitness and health apps, syncing your routes and ride data.\n\nSay Goodbye to Limited Range with Range Boost!\nExperience the convenience of Range Boost, an additional long-range 500Wh battery that seamlessly attaches to your bike's down tube. This upgrade allows you to double your distance and time between charges, enabling longer commutes and more adventurous rides. Range Boost is compatible with select SonicRide electric bike models.\n\nWhat is the range?\nFor an accurate estimate of how far you can ride on a single charge, use SonicRide's range calculator. We have pre-filled the variables for this specific bike model and the average rider, but you can adjust them to obtain the most accurate estimate.\n\n## Specifications\nFrameset\n- Frame: High-performance hydroformed alloy, Removable Integrated Battery, Range Boost-compatible, internal cable routing, Motor Armour, post-mount disc, 135x5 mm QR\n- Fork: SonicRide rigid alloy fork, 1-1/8'' steel steerer, 100x15mm thru axle, post mount disc brake\n- Max compatible fork travel: 63mm\n\nWheels\n- Front Hub: SonicRide sealed bearing, 32-hole 15mm alloy thru-axle\n- Front Skewer: SonicRide Switch thru axle, removable lever\n- Rear Hub: SonicRide alloy, sealed bearing, 6-bolt, 135x5mm QR\n- Rear Skewer: 148x5mm bolt-on\n- Rim: SonicRide MD35, tubeless compatible, 32-hole, 35mm width, Presta valve\n- Spokes: Size: M, L, XL - 14g stainless steel, black\n- Tire: SonicRide E6 Hard-Case Lite, reflective strip, 27.5x2.40''\n- Max tire size: 27.5x2.40\"\n\nDrivetrain\n- Shifter: Shimano Deore M4100, 10 speed\n- Rear Derailleur: Size: M, L, XL - Shimano Deore M5120, long cage\n- Crank: Size: M - SonicRide alloy, 170mm length; Size: L, XL - SonicRide alloy, 175mm length\n- Chainring: SonicRide 46T narrow/wide alloy, with alloy guard\n- Cassette: Size: M, L, XL - Shimano Deore M4100, 11-42, 10 speed\n- Chain: Size: M, L, XL - KMC E10; Size: M, L, XL - KMC X10e\n- Pedal: Size: M, L, XL - SonicRide City pedals; Size: M, L, XL - Wellgo C157, boron axle, plastic body; Size: M, L, XL - slip-proof aluminum pedals with reflectors\n- Max chainring size: 1x: 48T\n\nComponents\n- Saddle: SonicRide Commuter Comp\n- Seatpost: SonicRide Comp, 6061 alloy, 31.6mm, 8mm offset, 330mm length\n- Handlebar: Size: M - SonicRide alloy, 31.8mm, 15mm rise, 600mm width; Size: L, XL - SonicRide alloy, 31.8mm, 15mm rise, 660mm width\n- Grips: SonicRide Satellite Elite, alloy lock-on\n- Stem: Size: M - SonicRide alloy, 31.8mm, Blendr compatible, 7-degree, 70mm length; Size: L - SonicRide alloy, 31.8mm, Blendr compatible, 7-degree, 90mm length; Size: XL - SonicRide alloy, 31.8mm, Blendr compatible, 7-degree, 100mm length\n- Headset: Size: M, L, XL - SonicRide IS-2 alloy, integrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom; Size: M, L, XL - SonicRide Integrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom\n- Brake: Shimano MT520 4-piston hydraulic disc, post-mount, 180mm rotor\n- Brake rotor: Shimano RT56, 6-bolt, 180mm\n- Rotor size: Max brake rotor sizes: 180mm front & rear\n\nAccessories\n- Battery: SonicRide PowerTube 625Wh\n- Charger: SonicRide standard 4A, 100-240V\n- Motor: SonicRide Performance Speed, 85 Nm, 28 mph / 45 kph\n- Light: Size: M, L, XL - SonicRide Lync taillight, 50 lumens; Size: M, L, XL - SonicRide Lync headlight, 500 lumens\n- Kickstand: Size: M, L, XL - Rear mount, alloy; Size: M, L, XL - Adjustable length alloy kickstand\n- Cargo rack: SonicRide integrated rear rack, aluminum\n- Fender: SonicRide custom aluminum\n\nWeight\n- Weight: M - 25.54 kg / 56.3 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:------------------------:|:--------------------:|\n| M | 165 - 175 cm / 5'5\" - 5'9\" | 77 - 83 cm / 30\" - 33\" |\n| L | 175 - 186 cm / 5'9\" - 6'1\" | 82 - 88 cm / 32\" - 35\" |\n| XL | 186 - 197 cm / 6'1\" - 6'6\" | 87 - 93 cm / 34\" - 37\" |\n\n## Geometry\n| Frame size letter | M | L | XL |\n|---------------------------|-------|-------|-------|\n| Wheel size | 27.5\" | 27.5\" | 27.5\" |\n| A — Seat tube | 44.6 | 49.1 | 53.4 |\n| B — Seat tube angle | 73.0° | 73.0° | 73.0° |\n| C — Head tube length | 16.5 | 19.5 | 23.0 |\n| D — Head angle | 69.5° | 70.0° | 70.5° |\n| E — Effective top tube | 59.5 | 60.7 | 62.2 |\n| F — Bottom bracket height | 29.5 | 29.5 | 29.5 |\n| G — Bottom bracket drop | 6.0 | 6.0 | 6.0 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.4 | 4.4 | 4.4 |\n| J — Trail | 8.6 | 8.1 | 7.9 |\n| K — Wheelbase | 114.6 | 115.0 | 116.4 |\n| L — Standover | 79.5 | 83.7 | 87.9 |\n| M — Frame reach | 40.5 | 40.8 | 41.2 |", "price": 5999.99, "tags": [ "bicycle", "road bike", "professional" ] }, { "name": "SwiftVolt Pro", "shortDescription": "SwiftVolt Pro is a high-performance e-bike designed for riders seeking a thrilling and fast riding experience. Equipped with a powerful SwiftDrive motor that provides assistance up to 30 mph and a long-lasting battery, this bike is perfect for long-distance commuting and passionate e-bike enthusiasts. The sleek and innovative design features cater specifically to individuals who prioritize cycling over driving. Additionally, the bike is seamlessly integrated with your smartphone, allowing you to use it for navigation, music, and more.", "description": "## Overview\nThis bike is ideal for you if:\n- You desire a sleek and modern hydroformed aluminum frame that houses a 700Wh battery.\n- You want to maintain high speeds of up to 30 mph with the assistance of the SwiftDrive motor.\n- You appreciate the convenience of using your smartphone as a controller, which can be docked and charged on the handlebar.\n\n## Features\n\nConnect with SwiftSync App\nBy downloading the SwiftSync app, your smartphone becomes an interactive on-board computer. Attach it to the handlebar-mounted controller for easy access and charging. With the thumb pad, you can make calls, listen to music, receive turn-by-turn directions, and connect with fitness and health apps to track your routes and ride data via Bluetooth® wireless technology.\n\nEnhanced Range with BoostMax\nBoostMax offers the capability to attach a second 700Wh Swift battery to the downtube of your bike, effectively doubling the distance and time between charges. This allows for extended rides, longer commutes, and more significant adventures. BoostMax is compatible with select Swift electric bike models.\n\nRange Estimation\nFor an estimate of how far you can ride on a single charge, consult the Swift range calculator. The variables are automatically populated based on this bike model and the average rider, but you can modify them to obtain the most accurate estimate.\n\n## Specifications\nFrameset\n- Frame: Lightweight hydroformed alloy, Removable Integrated Battery, BoostMax-compatible, internal cable routing, post-mount disc, 135x5 mm QR\n- Fork: SwiftVolt rigid alloy fork, 1-1/8'' steel steerer, 100x15mm thru-axle, post-mount disc brake\n- Max compatible fork travel: 63mm\n\nWheels\n- Front Hub: Swift sealed bearing, 32-hole 15mm alloy thru-axle\n- Front Skewer: Swift Switch thru-axle, removable lever\n- Rear Hub: Swift alloy, sealed bearing, 6-bolt, 135x5mm QR\n- Rear Skewer: 148x5mm bolt-on\n- Rim: SwiftRim, tubeless compatible, 32-hole, 35mm width, Presta valve\n- Spokes: 14g stainless steel, black\n- Tire: Swift E6 Hard-Case Lite, reflective strip, 27.5x2.40''\n- Max tire size: 27.5x2.40\"\n\nDrivetrain\n- Shifter: Shimano Deore M4100, 10 speed\n- Rear Derailleur: Shimano Deore M5120, long cage\n- Crank: Swift alloy, 170mm length\n- Chainring: Swift 46T narrow/wide alloy, w/alloy guard\n- Cassette: Shimano Deore M4100, 11-42, 10 speed\n- Chain: KMC E10\n- Pedal: Swift City pedals\n- Max chainring size: 1x: 48T\n\nComponents\n- Saddle: Swift Commuter Comp\n- Seatpost: Swift Comp, 6061 alloy, 31.6mm, 8mm offset, 330mm length\n- Handlebar: Swift alloy, 31.8mm, 15mm rise, 600mm width (M), 660mm width (L, XL)\n- Grips: Swift Satellite Elite, alloy lock-on\n- Stem: Swift alloy, 31.8mm, Blendr compatible, 7 degree, 70mm length (M), 90mm length (L), 100mm length (XL)\n- Headset: FSA IS-2 alloy, integrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom\n- Brakes: Shimano MT520 4-piston hydraulic disc, post-mount, 180mm rotor\n- Brake Rotor: Shimano RT56, 6-bolt, 180mm\n- Rotor size: Max 180mm front & rear\n\nAccessories\n- Battery: Swift PowerTube 700Wh\n- Charger: Swift standard 4A, 100-240V\n- Motor: SwiftDrive, 90 Nm, 30 mph / 48 kph\n- Light: Swift Lync taillight, 50 lumens (M, L, XL), Swift Lync headlight, 500 lumens (M, L, XL)\n- Kickstand: Rear mount, alloy (M, L, XL), Adjustable length alloy kickstand (M, L, XL)\n- Cargo rack: SwiftVolt integrated rear rack, aluminum\n- Fender: Swift custom aluminum\n\nWeight\n- Weight: M - 25.54 kg / 56.3 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:---------------------:|:-------------:|\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n| XL | 186 - 197 cm 6'1\" - 6'6\" | 87 - 93 cm 34\" - 37\" |\n\n## Geometry\n| Frame size letter | M | L | XL |\n|---------------------------|-------|-------|-------|\n| Wheel size | 27.5\" | 27.5\" | 27.5\" |\n| A — Seat tube | 44.6 | 49.1 | 53.4 |\n| B — Seat tube angle | 73.0° | 73.0° | 73.0° |\n| C — Head tube length | 16.5 | 19.5 | 23.0 |\n| D — Head angle | 69.5° | 70.0° | 70.5° |\n| E — Effective top tube | 59.5 | 60.7 | 62.2 |\n| F — Bottom bracket height | 29.5 | 29.5 | 29.5 |\n| G — Bottom bracket drop | 6.0 | 6.0 | 6.0 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.4 | 4.4 | 4.4 |\n| J — Trail | 8.6 | 8.1 | 7.9 |\n| K — Wheelbase | 114.6 | 115.0 | 116.4 |\n| L — Standover | 79.5 | 83.7 | 87.9 |\n| M — Frame reach | 40.5 | 40.8 | 41.2 |\n| N — Frame stack | 62.3 | 65.2 | 68.8 |", "price": 2499.99, "tags": [ "bicycle", "city bike", "professional" ] }, { "name": "AgileEon 9X", "shortDescription": "AgileEon 9X is a high-performance e-bike designed for riders seeking speed and endurance. Equipped with a robust motor and an extended battery life, this bike is perfect for long-distance commuters and avid e-bike enthusiasts. It boasts innovative features tailored for individuals who prioritize cycling over driving. Additionally, the bike integrates seamlessly with your smartphone, allowing you to access navigation, music, and more.", "description": "## Overview\nIt's right for you if...\nYou crave speed and want to cover long distances efficiently. The AgileEon 9X features a sleek hydroformed aluminum frame that houses a powerful motor, along with a large-capacity battery for extended rides. It comes equipped with a 10-speed drivetrain, front and rear lighting, fenders, and a rear rack.\n\nThe tech you get\nDesigned for those constantly on the move, this bike includes a state-of-the-art motor and a high-capacity battery, making it an excellent choice for lengthy commutes.\n\nThe final word\nWith the AgileEon 9X, you can push your boundaries and explore new horizons thanks to its powerful motor and long-lasting battery.\n\n## Features\n\nConnect Your Ride with RideMate App\nMake use of the RideMate app to transform your smartphone into an onboard computer. Simply attach it to the RideMate controller to dock and charge, then utilize the thumb pad on your handlebar to make calls, listen to music, receive turn-by-turn directions, and more. The bike also supports Bluetooth® wireless technology, enabling seamless connectivity with fitness and health apps for route syncing and ride data.\n\nGoodbye, car. Hello, Extended Range!\nEnhance your riding experience with the Extended Range option, which allows for the attachment of an additional high-capacity 500Wh battery to your bike's downtube. This doubles the distance and time between charges, enabling longer rides, extended commutes, and more significant adventures. The Extended Range feature is compatible with select AgileEon electric bike models.\n\nWhat is the range?\nTo determine how far you can ride on a single charge, you can utilize the range calculator provided by AgileEon. We have pre-filled the variables for this specific model and an average rider, but adjustments can be made for a more accurate estimation.\n\n## Specifications\nFrameset\nFrame: High-performance hydroformed alloy, Removable Integrated Battery, Extended Range-compatible, internal cable routing, Motor Armor, post-mount disc, 135x5 mm QR\nFork: AgileEon rigid alloy fork, 1-1/8'' steel steerer, 100x15mm thru-axle, post-mount disc brake\nMax compatible fork travel: 63mm\n\nWheels\nFront Hub: AgileEon sealed bearing, 32-hole 15mm alloy thru-axle\nFront Skewer: AgileEon Switch thru-axle, removable lever\nRear Hub: AgileEon alloy, sealed bearing, 6-bolt, 135x5mm QR\nRear Skewer: 148x5mm bolt-on\nRim: AgileEon MD35, tubeless compatible, 32-hole, 35mm width, Presta valve\nSpokes:\n- Size: M, L, XL: 14g stainless steel, black\nTire: AgileEon E6 Hard-Case Lite, reflective strip, 27.5x2.40''\nMax tire size: 27.5x2.40\"\n\nDrivetrain\nShifter: Shimano Deore M4100, 10-speed\nRear derailleur:\n- Size: M, L, XL: Shimano Deore M5120, long cage\nCrank:\n- Size: M: AgileEon alloy, 170mm length\n- Size: L, XL: AgileEon alloy, 175mm length\nChainring: AgileEon 46T narrow/wide alloy, with alloy guard\nCassette:\n- Size: M, L, XL: Shimano Deore M4100, 11-42, 10-speed\nChain:\n- Size: M, L, XL: KMC E10\nPedal:\n- Size: M, L, XL: AgileEon City pedals\nMax chainring size: 1x: 48T\n\nComponents\nSaddle: AgileEon Commuter Comp\nSeatpost: AgileEon Comp, 6061 alloy, 31.6mm, 8mm offset, 330mm length\nHandlebar:\n- Size: M: AgileEon alloy, 31.8mm, 15mm rise, 600mm width\n- Size: L, XL: AgileEon alloy, 31.8mm, 15mm rise, 660mm width\nGrips: AgileEon Satellite Elite, alloy lock-on\nStem:\n- Size: M: AgileEon alloy, 31.8mm, Blendr compatible, 7-degree, 70mm length\n- Size: L: AgileEon alloy, 31.8mm, Blendr compatible, 7-degree, 90mm length\n- Size: XL: AgileEon alloy, 31.8mm, Blendr compatible, 7-degree, 100mm length\nHeadset:\n- Size: M, L, XL: AgileEon IS-2 alloy, integrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom\nBrake: Shimano MT520 4-piston hydraulic disc, post-mount, 180mm rotor\nBrake rotor: Shimano RT56, 6-bolt, 180mm\nRotor size: Max brake rotor sizes: 180mm front & rear\n\nAccessories\nBattery: AgileEon PowerTube 625Wh\nCharger: AgileEon standard 4A, 100-240V\nMotor: AgileEon Performance Speed, 85 Nm, 28 mph / 45 kph\nLight:\n- Size: M, L, XL: AgileEon taillight, 50 lumens\n- Size: M, L, XL: AgileEon headlight, 500 lumens\nKickstand:\n- Size: M, L, XL: Rear mount, alloy\n- Size: M, L, XL: Adjustable length alloy kickstand\nCargo rack: AgileEon integrated rear rack, aluminum\nFender: AgileEon custom aluminum\n\nWeight\nWeight: M - 25.54 kg / 56.3 lbs\nWeight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:------------------------:|:--------------------:|\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n| XL | 186 - 197 cm 6'1\" - 6'6\" | 87 - 93 cm 34\" - 37\" |\n\n## Geometry\n| Frame size letter | M | L | XL |\n|---------------------------|-------|-------|-------|\n| Wheel size | 27.5\" | 27.5\" | 27.5\" |\n| A — Seat tube | 44.6 | 49.1 | 53.4 |\n| B — Seat tube angle | 73.0° | 73.0° | 73.0° |\n| C — Head tube length | 16.5 | 19.5 | 23.0 |\n| D — Head angle | 69.5° | 70.0° | 70.5° |\n| E — Effective top tube | 59.5 | 60.7 | 62.2 |\n| F — Bottom bracket height | 29.5 | 29.5 | 29.5 |\n| G — Bottom bracket drop | 6.0 | 6.0 | 6.0 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.4 | 4.4 | 4.4 |\n| J — Trail | 8.6 | 8.1 | 7.9 |\n| K — Wheelbase | 114.6 | 115.0 | 116.4 |\n| L — Standover | 79.5 | 83.7 | 87.9 |\n| M — Frame reach | 40.5 | 40.8 | 41.2 |\n| N — Frame stack | 62.3 | 65.2 | 68.8 |", "price": 3499.99, "tags": [ "bicycle", "road bike", "professional" ] }, { "name": "Stealth R1X Pro", "shortDescription": "Stealth R1X Pro is a high-performance carbon road bike designed for riders who crave speed and exceptional handling. With its aerodynamic tube shaping, disc brakes, and lightweight carbon wheels, the Stealth R1X Pro offers unparalleled performance for competitive road cycling.", "description": "## Overview\nIt's right for you if...\nYou're a competitive cyclist looking for a road bike that offers superior performance in terms of speed, handling, and aerodynamics. You want a complete package that includes lightweight carbon wheels, without the need for future upgrades.\n\nThe tech you get\nThe Stealth R1X Pro features a lightweight and aerodynamic carbon frame, an advanced carbon fork, high-performance Shimano Ultegra 11-speed drivetrain, and powerful Ultegra disc brakes. The bike also comes equipped with cutting-edge Bontrager Aeolus Elite 35 carbon wheels.\n\nThe final word\nThe Stealth R1X Pro stands out with its combination of a fast and aerodynamic frame, high-end drivetrain, and top-of-the-line carbon wheels. Whether you're racing on local roads, participating in pro stage races, or engaging in hill climbing competitions, this bike is a formidable choice that delivers an exceptional riding experience.\n\n## Features\nSleek and aerodynamic design\nThe Stealth R1X Pro's aero tube shapes maximize speed and performance, making it faster on climbs and flats alike. The bike also features a streamlined Aeolus RSL bar/stem for improved front-end aerodynamics.\n\nDesigned for all riders\nThe Stealth R1X Pro is designed to provide an outstanding fit for riders of all genders, body types, riding styles, and abilities. It comes equipped with size-specific components to ensure a comfortable and efficient riding position for competitive riders.\n\n## Specifications\nFrameset\n- Frame: Ultralight carbon frame constructed with high-performance 500 Series ADV Carbon. It features Ride Tuned performance tube optimization, a tapered head tube, internal routing, DuoTrap S compatibility, flat mount disc brake mounts, and a 142x12mm thru axle.\n- Fork: Full carbon fork (Émonda SL) with a tapered carbon steerer, internal brake routing, flat mount disc brake mounts, and a 12x100mm thru axle.\n- Frame fit: H1.5 Race geometry.\n\nWheels\n- Front wheel: Bontrager Aeolus Elite 35 carbon wheel with a 35mm rim depth, ADV Carbon construction, Tubeless Ready compatibility, and a 100x12mm thru axle.\n- Rear wheel: Bontrager Aeolus Elite 35 carbon wheel with a 35mm rim depth, ADV Carbon construction, Tubeless Ready compatibility, Shimano 11/12-speed freehub, and a 142x12mm thru axle.\n- Front skewer: Bontrager Switch thru axle with a removable lever.\n- Rear skewer: Bontrager Switch thru axle with a removable lever.\n- Tire: Bontrager R2 Hard-Case Lite with an aramid bead, 60 tpi, and a size of 700x25c.\n- Maximum tire size: 28mm.\n\nDrivetrain\n- Shifter:\n - Size 47, 50, 52: Shimano Ultegra R8025 with short-reach levers, 11-speed.\n - Size 54, 56, 58, 60, 62: Shimano Ultegra R8020, 11-speed.\n- Front derailleur: Shimano Ultegra R8000, braze-on.\n- Rear derailleur: Shimano Ultegra R8000, short cage, with a maximum cog size of 30T.\n- Crank:\n - Size 47: Shimano Ultegra R8000 with 52/36 chainrings and a 165mm length.\n - Size 50, 52: Shimano Ultegra R8000 with 52/36 chainrings and a 170mm length.\n - Size 54, 56, 58: Shimano Ultegra R8000 with 52/36 chainrings and a 172.5mm length.\n - Size 60, 62: Shimano Ultegra R8000 with 52/36 chainrings and a 175mm length.\n- Bottom bracket: Praxis T47 threaded bottom bracket with internal bearings.\n- Cassette: Shimano Ultegra R8000, 11-30, 11-speed.\n- Chain: Shimano Ultegra HG701, 11-speed.\n- Maximum chainring size: 1x - 50T, 2x - 53/39.\n\nComponents\n- Saddle: Bontrager Aeolus Comp with steel rails and a width of 145mm.\n- Seatpost:\n - Size 47, 50, 52, 54: Bontrager carbon seatmast cap with a 20mm offset and a short length.\n - Size 56, 58, 60, 62: Bontrager carbon seatmast cap with a 20mm offset and a tall length.\n- Handlebar:\n - Size 47, 50: Bontrager Elite VR-C alloy handlebar with a 31.8mm clamp, 100mm reach, 124mm drop, and a width of 38cm.\n - Size 52: Bontrager Elite VR-C alloy handlebar with a 31.8mm clamp, 100mm reach, 124mm drop, and a width of 40cm.\n - Size 54, 56, 58: Bontrager Elite VR-C alloy handlebar with a 31.8mm clamp, 100mm reach, 124mm drop, and a width of 42cm.\n - Size 60, 62: Bontrager Elite VR-C alloy handlebar with a 31.8mm clamp, 100mm reach, 124mm drop, and a width of 44cm.\n- Handlebar tape: Bontrager Supertack Perf tape.\n- Stem:\n - Size 47: Bontrager Pro alloy stem with a 31.8mm clamp, Blendr compatibility, 7-degree rise, and a length of 70mm.\n - Size 50: Bontrager Pro alloy stem with a 31.8mm clamp, Blendr compatibility, 7-degree rise, and a length of 80mm.\n - Size 52, 54: Bontrager Pro alloy stem with a 31.8mm clamp, Blendr compatibility, 7-degree rise, and a length of 90mm.\n - Size 56: Bontrager Pro alloy stem with a 31.8mm clamp, Blendr compatibility, 7-degree rise, and a length of 100mm.\n - Size 58, 60, 62: Bontrager Pro alloy stem with a 31.8mm clamp, Blendr compatibility, 7-degree rise, and a length of 110mm.\n- Brake: Shimano Ultegra hydraulic disc brakes with flat mount calipers.\n- Brake rotor: Shimano RT800 with centerlock mounting, 160mm diameter.\n\nWeight\n- Weight: 8.03 kg (17.71 lbs) for the 56cm frame.\n- Weight limit: The bike has a maximum total weight limit (combined weight of the bicycle, rider, and cargo) of 275 pounds (125 kg).\n\n## Sizing\nPlease refer to the table below for the corresponding Stealth R1X Pro frame sizes, recommended rider height range, and inseam measurements:\n\n| Size | Rider Height | Inseam |\n|:----:|:---------------------:|:--------------:|\n| 47 | 152 - 158 cm (5'0\") | 71 - 75 cm |\n| 50 | 158 - 163 cm (5'2\") | 74 - 77 cm |\n| 52 | 163 - 168 cm (5'4\") | 76 - 79 cm |\n| 54 | 168 - 174 cm (5'6\") | 78 - 82 cm |\n| 56 | 174 - 180 cm (5'9\") | 81 - 85 cm |\n| 58 | 180 - 185 cm (5'11\") | 84 - 87 cm |\n| 60 | 185 - 190 cm (6'1\") | 86 - 90 cm |\n| 62 | 190 - 195 cm (6'3\") | 89 - 92 cm |\n\n## Geometry\nThe table below provides the geometry measurements for each frame size of the Stealth R1X Pro:\n\n| Frame size number | 47 cm | 50 cm | 52 cm | 54 cm | 56 cm | 58 cm | 60 cm | 62 cm |\n|-------------------------------|-------|-------|-------|-------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c | 700c | 700c | 700c | 700c |\n| A — Seat tube | 42.4 | 45.3 | 48.3 | 49.6 | 52.5 | 55.3 | 57.3 | 59.3 |\n| B — Seat tube angle | 74.6° | 74.6° | 74.2° | 73.7° | 73.3° | 73.0° | 72.8° | 72.5° |\n| C — Head tube length | 10.0 | 11.1 | 12.1 | 13.1 | 15.1 | 17.1 | 19.1 | 21.1 |\n| D — Head angle | 72.1° | 72.1° | 72.8° | 73.0° | 73.5° | 73.8° | 73.9° | 73.9° |\n| E — Effective top tube | 51.2 | 52.1 | 53.4 | 54.3 | 55.9 | 57.4 | 58.6 | 59.8 |\n| G — Bottom bracket drop | 7.2 | 7.2 | 7.2 | 7.0 | 7.0 | 6.8 | 6.8 | 6.8 |\n| H — Chainstay length | 41.0 | 41.0 | 41.0 | 41.0 | 41.0 | 41.1 | 41.1 | 41.2 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 | 4.0 | 4.0 | 4.0 | 4.0 |\n| J — Trail | 6.8 | 6.2 | 5.8 | 5.6 | 5.8 | 5.7 | 5.6 | 5.6 |\n| K — Wheelbase | 97.2 | 97.4 | 97.7 | 98.1 | 98.3 | 99.2 | 100.1 | 101.0 |\n| L — Standover | 69.2 | 71.1 | 73.2 | 74.4 | 76.8 | 79.3 | 81.1 | 82.9 |\n| M — Frame reach | 37.3 | 37.8 | 38.3 | 38.6 | 39.1 | 39.6 | 39.9 | 40.3 |\n| N — Frame stack | 50.7 | 52.1 | 53.3 | 54.1 | 56.3 | 58.1 | 60.1 | 62.0 |\n| Saddle rail height min (short mast) | 55.5 | 58.5 | 61.5 | 64.0 | 67.0 | 69.0 | 71.0 | 73.0 |\n| Saddle rail height max (short mast) | 61.5 | 64.5 | 67.5 | 70.0 | 73.0 | 75.0 | 77.0 | 79.0 |\n| Saddle rail height min (tall mast) | 59.0 | 62.0 | 65.0 | 67.5 | 70.5 | 72.5 | 74.5 | 76.5 |\n| Saddle rail height max (tall mast) | 65.0 | 68.0 | 71.0 | 73.5 | 76.5 | 78.5 | 80.5 | 82.5 |", "price": 2999.99, "tags": [ "bicycle", "mountain bike", "professional" ] }, { "name": "Avant SLR 6 Disc Pro", "shortDescription": "Avant SLR 6 Disc Pro is a high-performance carbon road bike designed for riders who prioritize speed and handling. With its aero tube shaping, disc brakes, and lightweight carbon wheels, it offers the perfect balance of speed and control.", "description": "## Overview\nIt's right for you if...\nYou're a rider who values exceptional performance on fast group rides and races, and you want a complete package that includes lightweight carbon wheels. The Avant SLR 6 Disc Pro is designed to provide the speed and aerodynamics you need to excel on any road.\n\nThe tech you get\nThe Avant SLR 6 Disc Pro features a lightweight 500 Series ADV Carbon frame and fork, Bontrager Aeolus Elite 35 carbon wheels, a full Shimano Ultegra 11-speed drivetrain, and powerful Ultegra disc brakes.\n\nThe final word\nThe standout feature of this bike is the combination of its aero frame, high-performance drivetrain, and top-quality carbon wheels. Whether you're racing, tackling challenging climbs, or participating in professional stage races, the Avant SLR 6 Disc Pro is a worthy choice that will enhance your performance.\n\n## Features\nAll-new aero design\nThe Avant SLR 6 Disc Pro features innovative aero tube shapes that provide an advantage in all riding conditions, whether it's climbing or riding on flat roads. Additionally, it is equipped with a sleek new Aeolus RSL bar/stem that enhances front-end aero performance.\n\nAwesome bikes for everyone\nThe Avant SLR 6 Disc Pro is designed with the belief that every rider, regardless of gender, body type, riding style, or ability, deserves a great bike. It is equipped with size-specific components that ensure a perfect fit for competitive riders of all genders.\n\n## Specifications\nFrameset\n- Frame: Ultralight 500 Series ADV Carbon, Ride Tuned performance tube optimization, tapered head tube, internal routing, DuoTrap S compatible, flat mount disc, 142x12mm thru axle\n- Fork: Avant SL full carbon, tapered carbon steerer, internal brake routing, flat mount disc, 12x100mm thru axle\n- Frame fit: H1.5 Race\n\nWheels\n- Front wheel: Bontrager Aeolus Elite 35, ADV Carbon, Tubeless Ready, 35mm rim depth, 100x12mm thru axle\n- Rear wheel: Bontrager Aeolus Elite 35, ADV Carbon, Tubeless Ready, 35mm rim depth, Shimano 11/12-speed freehub, 142x12mm thru axle\n- Front skewer: Bontrager Switch thru axle, removable lever\n- Rear skewer: Bontrager Switch thru axle, removable lever\n- Tire: Bontrager R2 Hard-Case Lite, aramid bead, 60 tpi, 700x25c\n- Max tire size: 28mm\n\nDrivetrain\n- Shifter: \n - Size 47, 50, 52: Shimano Ultegra R8025, short-reach lever, 11-speed\n - Size 54, 56, 58, 60, 62: Shimano Ultegra R8020, 11-speed\n- Front derailleur: Shimano Ultegra R8000, braze-on\n- Rear derailleur: Shimano Ultegra R8000, short cage, 30T max cog\n- Crank: \n - Size 47: Shimano Ultegra R8000, 52/36, 165mm length\n - Size 50, 52: Shimano Ultegra R8000, 52/36, 170mm length\n - Size 54, 56, 58: Shimano Ultegra R8000, 52/36, 172.5mm length\n - Size 60, 62: Shimano Ultegra R8000, 52/36, 175mm length\n- Bottom bracket: Praxis, T47 threaded, internal bearing\n- Cassette: Shimano Ultegra R8000, 11-30, 11-speed\n- Chain: Shimano Ultegra HG701, 11-speed\n- Max chainring size: 1x: 50T, 2x: 53/39\n\nComponents\n- Saddle: Bontrager Aeolus Comp, steel rails, 145mm width\n- Seatpost: \n - Size 47, 50, 52, 54: Bontrager carbon seatmast cap, 20mm offset, short length\n - Size 56, 58, 60, 62: Bontrager carbon seatmast cap, 20mm offset, tall length\n- Handlebar: \n - Size 47, 50: Bontrager Elite VR-C, alloy, 31.8mm, 100mm reach, 124mm drop, 38cm width\n - Size 52: Bontrager Elite VR-C, alloy, 31.8mm, 100mm reach, 124mm drop, 40cm width\n - Size 54, 56, 58: Bontrager Elite VR-C, alloy, 31.8mm, 100mm reach, 124mm drop, 42cm width\n - Size 60, 62: Bontrager Elite VR-C, alloy, 31.8mm, 100mm reach, 124mm drop, 44cm width\n- Handlebar tape: Bontrager Supertack Perf tape\n- Stem: \n - Size 47: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 70mm length\n - Size 50: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 80mm length\n - Size 52, 54: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 90mm length\n - Size 56: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 100mm length\n - Size 58, 60, 62: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 110mm length\n- Brake: Shimano Ultegra hydraulic disc, flat mount\n- Brake rotor: Shimano RT800, centerlock, 160mm\n\nWeight\n- Weight: 56 - 8.03 kg / 17.71 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 275 pounds (125 kg).\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| 47 | 152 - 158 cm 5'0\" - 5'2\" | 71 - 75 cm 28\" - 30\" |\n| 50 | 158 - 163 cm 5'2\" - 5'4\" | 74 - 77 cm 29\" - 30\" |\n| 52 | 163 - 168 cm 5'4\" - 5'6\" | 76 - 79 cm 30\" - 31\" |\n| 54 | 168 - 174 cm 5'6\" - 5'9\" | 78 - 82 cm 31\" - 32\" |\n| 56 | 174 - 180 cm 5'9\" - 5'11\" | 81 - 85 cm 32\" - 33\" |\n| 58 | 180 - 185 cm 5'11\" - 6'1\" | 84 - 87 cm 33\" - 34\" |\n| 60 | 185 - 190 cm 6'1\" - 6'3\" | 86 - 90 cm 34\" - 35\" |\n| 62 | 190 - 195 cm 6'3\" - 6'5\" | 89 - 92 cm 35\" - 36\" |\n\n## Geometry\n| Frame size number | 47 cm | 50 cm | 52 cm | 54 cm | 56 cm | 58 cm | 60 cm | 62 cm |\n|---------------------------------------|-------|-------|-------|-------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c | 700c | 700c | 700c | 700c |\n| A — Seat tube | 42.4 | 45.3 | 48.3 | 49.6 | 52.5 | 55.3 | 57.3 | 59.3 |\n| B — Seat tube angle | 74.6° | 74.6° | 74.2° | 73.7° | 73.3° | 73.0° | 72.8° | 72.5° |\n| C — Head tube length | 10.0 | 11.1 | 12.1 | 13.1 | 15.1 | 17.1 | 19.1 | 21.1 |\n| D — Head angle | 72.1° | 72.1° | 72.8° | 73.0° | 73.5° | 73.8° | 73.9° | 73.9° |\n| E — Effective top tube | 51.2 | 52.1 | 53.4 | 54.3 | 55.9 | 57.4 | 58.6 | 59.8 |\n| G — Bottom bracket drop | 7.2 | 7.2 | 7.2 | 7.0 | 7.0 | 6.8 | 6.8 | 6.8 |\n| H — Chainstay length | 41.0 | 41.0 | 41.0 | 41.0 | 41.0 | 41.1 | 41.1 | 41.2 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 | 4.0 | 4.0 | 4.0 | 4.0 |\n| J — Trail | 6.8 | 6.2 | 5.8 | 5.6 | 5.8 | 5.7 | 5.6 | 5.6 |\n| K — Wheelbase | 97.2 | 97.4 | 97.7 | 98.1 | 98.3 | 99.2 | 100.1 | 101.0 |\n| L — Standover | 69.2 | 71.1 | 73.2 | 74.4 | 76.8 | 79.3 | 81.1 | 82.9 |\n| M — Frame reach | 37.3 | 37.8 | 38.3 | 38.6 | 39.1 | 39.6 | 39.9 | 40.3 |\n| N — Frame stack | 50.7 | 52.1 | 53.3 | 54.1 | 56.3 | 58.1 | 60.1 | 62.0 |\n| Saddle rail height min (w/short mast) | 55.5 | 58.5 | 61.5 | 64.0 | 67.0 | 69.0 | 71.0 | 73.0 |\n| Saddle rail height max (w/short mast) | 61.5 | 64.5 | 67.5 | 70.0 | 73.0 | 75.0 | 77.0 | 79.0 |\n| Saddle rail height min (w/tall mast) | 59.0 | 62.0 | 65.0 | 67.5 | 70.5 | 72.5 | 74.5 | 76.5 |\n| Saddle rail height max (w/tall mast) | 65.0 | 68.0 | 71.0 | 73.5 | 76.5 | 78.5 | 80.5 | 82.5 |", "price": 999.99, "tags": [ "bicycle", "city bike", "professional" ] } ] --- ### Models/Spring Ai Openai/Src/Test/Resources/Prompts/System Only Cache Prompt (models/spring-ai-openai/src/test/resources/prompts/system-only-cache-prompt.txt) You are an expert software architect specializing in distributed systems and cloud-native applications. Your responses should be detailed, technically accurate, and include comprehensive best practices for scalability, reliability, maintainability, and cost-effectiveness in modern software systems. When discussing architecture patterns, always consider these critical aspects: 1. Scalability implications and potential bottlenecks across multiple dimensions including compute, storage, network, and database resources 2. Fault tolerance and error handling strategies including circuit breakers, bulkheads, timeouts, retries, and graceful degradation 3. Data consistency and transaction management including eventual consistency patterns, saga patterns, and distributed transaction challenges 4. Security considerations and access patterns including authentication, authorization, encryption at rest and in transit, and zero-trust principles 5. Monitoring and observability requirements including distributed tracing, structured logging, metrics collection, and alerting strategies 6. Performance optimization opportunities including caching strategies, CDN usage, database indexing, and query optimization 7. Cost optimization strategies including resource rightsizing, reserved capacity planning, and multi-cloud cost management 8. Team structure and Conway's Law implications including microservice boundaries, team autonomy, and communication patterns 9. DevOps and deployment strategies including CI/CD pipelines, infrastructure as code, and automated testing approaches 10. Compliance and governance requirements including data privacy regulations, audit trails, and regulatory compliance frameworks ## Detailed Architecture Guidelines for System-Only Caching ### Microservices Design Patterns When designing microservices, implement these essential patterns: - API Gateway pattern for centralized request routing and cross-cutting concerns - Service mesh for inter-service communication, security, and observability - Event sourcing for maintaining audit trails and enabling event-driven architectures - CQRS (Command Query Responsibility Segregation) for optimal read/write performance - Bulkhead pattern to isolate critical resources and prevent cascade failures - Circuit breaker pattern with exponential backoff for external service resilience - Saga pattern for distributed transaction management across service boundaries ### Data Management Strategies Implement robust data management approaches: - Database per service pattern to ensure data encapsulation and service autonomy - Event-driven data synchronization using message queues and event streams - Polyglot persistence choosing optimal data stores for specific use cases - Read replicas and sharding strategies for horizontal scaling - Data versioning and schema evolution strategies for backward compatibility - Distributed caching with Redis or similar for improved performance - Data governance frameworks ensuring data quality, lineage, and compliance ### Security Best Practices Implement defense-in-depth security measures: - OAuth 2.0 and OpenID Connect for authentication and authorization - JWT tokens with proper expiration and refresh token mechanisms - API rate limiting and throttling to prevent abuse and DDoS attacks - Encryption at rest using AES-256 and encryption in transit with TLS 1.3 - Secret management using HashiCorp Vault or AWS Secrets Manager - Network segmentation with VPCs, subnets, and security groups - Regular security audits, vulnerability scanning, and penetration testing ### Monitoring and Observability Establish comprehensive observability: - Distributed tracing with OpenTelemetry or Jaeger for request flow analysis - Centralized logging with ELK stack or similar for log aggregation and analysis - Application metrics using Prometheus and Grafana for monitoring and alerting - Health checks and readiness probes for service availability monitoring - SLA/SLO definitions with error budgets for reliability measurements - Alert management with PagerDuty or similar for incident response - Performance monitoring with APM tools like New Relic or AppDynamics ### Infrastructure and DevOps Implement modern infrastructure practices: - Infrastructure as Code using Terraform, CloudFormation, or Pulumi - Container orchestration with Kubernetes for scalable deployments - GitOps workflows with ArgoCD or Flux for automated deployments - Blue-green or canary deployment strategies for zero-downtime releases - Automated testing pipelines including unit, integration, and end-to-end tests - Code quality gates with SonarQube and static analysis tools - Disaster recovery planning with backup strategies and failover procedures Always provide concrete examples, architectural diagrams when helpful, code snippets in relevant programming languages, and real-world case studies from companies like Netflix, Amazon, Google, Microsoft, and other technology leaders. Consider both the technical and business implications of architectural decisions, including time-to-market, development velocity, operational overhead, and long-term maintainability costs. This system prompt is specifically designed for testing system-only caching strategies and contains sufficient tokens to trigger OpenAI's prompt caching mechanism with gpt-4o-mini (1024+ token threshold). --- ### Models/Spring Ai Postgresml/README (models/spring-ai-postgresml/README.md) [PostgresML Embedding Documentation](https://docs.spring.io/spring-ai/reference/api/embeddings/postgresml-embeddings.html) --- ### Models/Spring Ai Stability Ai/README (models/spring-ai-stability-ai/README.md) [Stability AI Image Generation](https://docs.spring.io/spring-ai/reference/api/image/stabilityai-image.html) --- ### Models/Spring Ai Transformers/README (models/spring-ai-transformers/README.md) [Transformers Embedding Documentation](https://docs.spring.io/spring-ai/reference/api/embeddings/onnx.html) --- ### Models/Spring Ai Transformers/Src/Main/Resources/Onnx/All MiniLM L6 V2/Tokenizer.Json (models/spring-ai-transformers/src/main/resources/onnx/all-MiniLM-L6-v2/tokenizer.json) { "version": "1.0", "truncation": { "direction": "Right", "max_length": 128, "strategy": "LongestFirst", "stride": 0 }, "padding": { "strategy": { "Fixed": 128 }, "direction": "Right", "pad_to_multiple_of": null, "pad_id": 0, "pad_type_id": 0, "pad_token": "[PAD]" }, "added_tokens": [ { "id": 0, "content": "[PAD]", "single_word": false, "lstrip": false, "rstrip": false, "normalized": false, "special": true }, { "id": 100, "content": "[UNK]", "single_word": false, "lstrip": false, "rstrip": false, "normalized": false, "special": true }, { "id": 101, "content": "[CLS]", "single_word": false, "lstrip": false, "rstrip": false, "normalized": false, "special": true }, { "id": 102, "content": "[SEP]", "single_word": false, "lstrip": false, "rstrip": false, "normalized": false, "special": true }, { "id": 103, "content": "[MASK]", "single_word": false, "lstrip": false, "rstrip": false, "normalized": false, "special": true } ], "normalizer": { "type": "BertNormalizer", "clean_text": true, "handle_chinese_chars": true, "strip_accents": null, "lowercase": true }, "pre_tokenizer": { "type": "BertPreTokenizer" }, "post_processor": { "type": "TemplateProcessing", "single": [ { "SpecialToken": { "id": "[CLS]", "type_id": 0 } }, { "Sequence": { "id": "A", "type_id": 0 } }, { "SpecialToken": { "id": "[SEP]", "type_id": 0 } } ], "pair": [ { "SpecialToken": { "id": "[CLS]", "type_id": 0 } }, { "Sequence": { "id": "A", "type_id": 0 } }, { "SpecialToken": { "id": "[SEP]", "type_id": 0 } }, { "Sequence": { "id": "B", "type_id": 1 } }, { "SpecialToken": { "id": "[SEP]", "type_id": 1 } } ], "special_tokens": { "[CLS]": { "id": "[CLS]", "ids": [ 101 ], "tokens": [ "[CLS]" ] }, "[SEP]": { "id": "[SEP]", "ids": [ 102 ], "tokens": [ "[SEP]" ] } } }, "decoder": { "type": "WordPiece", "prefix": "##", "cleanup": true }, "model": { "type": "WordPiece", "unk_token": "[UNK]", "continuing_subword_prefix": "##", "max_input_chars_per_word": 100, "vocab": { "[PAD]": 0, "[unused0]": 1, "[unused1]": 2, "[unused2]": 3, "[unused3]": 4, "[unused4]": 5, "[unused5]": 6, "[unused6]": 7, "[unused7]": 8, "[unused8]": 9, "[unused9]": 10, "[unused10]": 11, "[unused11]": 12, "[unused12]": 13, "[unused13]": 14, "[unused14]": 15, "[unused15]": 16, "[unused16]": 17, "[unused17]": 18, "[unused18]": 19, "[unused19]": 20, "[unused20]": 21, "[unused21]": 22, "[unused22]": 23, "[unused23]": 24, "[unused24]": 25, "[unused25]": 26, "[unused26]": 27, "[unused27]": 28, "[unused28]": 29, "[unused29]": 30, "[unused30]": 31, "[unused31]": 32, "[unused32]": 33, "[unused33]": 34, "[unused34]": 35, "[unused35]": 36, "[unused36]": 37, "[unused37]": 38, "[unused38]": 39, "[unused39]": 40, "[unused40]": 41, "[unused41]": 42, "[unused42]": 43, "[unused43]": 44, "[unused44]": 45, "[unused45]": 46, "[unused46]": 47, "[unused47]": 48, "[unused48]": 49, "[unused49]": 50, "[unused50]": 51, "[unused51]": 52, "[unused52]": 53, "[unused53]": 54, "[unused54]": 55, "[unused55]": 56, "[unused56]": 57, "[unused57]": 58, "[unused58]": 59, "[unused59]": 60, "[unused60]": 61, "[unused61]": 62, "[unused62]": 63, "[unused63]": 64, "[unused64]": 65, "[unused65]": 66, "[unused66]": 67, "[unused67]": 68, "[unused68]": 69, "[unused69]": 70, "[unused70]": 71, "[unused71]": 72, "[unused72]": 73, "[unused73]": 74, "[unused74]": 75, "[unused75]": 76, "[unused76]": 77, "[unused77]": 78, "[unused78]": 79, "[unused79]": 80, "[unused80]": 81, "[unused81]": 82, "[unused82]": 83, "[unused83]": 84, "[unused84]": 85, "[unused85]": 86, "[unused86]": 87, "[unused87]": 88, "[unused88]": 89, "[unused89]": 90, "[unused90]": 91, "[unused91]": 92, "[unused92]": 93, "[unused93]": 94, "[unused94]": 95, "[unused95]": 96, "[unused96]": 97, "[unused97]": 98, "[unused98]": 99, "[UNK]": 100, "[CLS]": 101, "[SEP]": 102, "[MASK]": 103, "[unused99]": 104, "[unused100]": 105, "[unused101]": 106, "[unused102]": 107, "[unused103]": 108, "[unused104]": 109, "[unused105]": 110, "[unused106]": 111, "[unused107]": 112, "[unused108]": 113, "[unused109]": 114, "[unused110]": 115, "[unused111]": 116, "[unused112]": 117, "[unused113]": 118, "[unused114]": 119, "[unused115]": 120, "[unused116]": 121, "[unused117]": 122, "[unused118]": 123, "[unused119]": 124, "[unused120]": 125, "[unused121]": 126, "[unused122]": 127, "[unused123]": 128, "[unused124]": 129, "[unused125]": 130, "[unused126]": 131, "[unused127]": 132, "[unused128]": 133, "[unused129]": 134, "[unused130]": 135, "[unused131]": 136, "[unused132]": 137, "[unused133]": 138, "[unused134]": 139, "[unused135]": 140, "[unused136]": 141, "[unused137]": 142, "[unused138]": 143, "[unused139]": 144, "[unused140]": 145, "[unused141]": 146, "[unused142]": 147, "[unused143]": 148, "[unused144]": 149, "[unused145]": 150, "[unused146]": 151, "[unused147]": 152, "[unused148]": 153, "[unused149]": 154, "[unused150]": 155, "[unused151]": 156, "[unused152]": 157, "[unused153]": 158, "[unused154]": 159, "[unused155]": 160, "[unused156]": 161, "[unused157]": 162, "[unused158]": 163, "[unused159]": 164, "[unused160]": 165, "[unused161]": 166, "[unused162]": 167, "[unused163]": 168, "[unused164]": 169, "[unused165]": 170, "[unused166]": 171, "[unused167]": 172, "[unused168]": 173, "[unused169]": 174, "[unused170]": 175, "[unused171]": 176, "[unused172]": 177, "[unused173]": 178, "[unused174]": 179, "[unused175]": 180, "[unused176]": 181, "[unused177]": 182, "[unused178]": 183, "[unused179]": 184, "[unused180]": 185, "[unused181]": 186, "[unused182]": 187, "[unused183]": 188, "[unused184]": 189, "[unused185]": 190, "[unused186]": 191, "[unused187]": 192, "[unused188]": 193, "[unused189]": 194, "[unused190]": 195, "[unused191]": 196, "[unused192]": 197, "[unused193]": 198, "[unused194]": 199, "[unused195]": 200, "[unused196]": 201, "[unused197]": 202, "[unused198]": 203, "[unused199]": 204, "[unused200]": 205, "[unused201]": 206, "[unused202]": 207, "[unused203]": 208, "[unused204]": 209, "[unused205]": 210, "[unused206]": 211, "[unused207]": 212, "[unused208]": 213, "[unused209]": 214, "[unused210]": 215, "[unused211]": 216, "[unused212]": 217, "[unused213]": 218, "[unused214]": 219, "[unused215]": 220, "[unused216]": 221, "[unused217]": 222, "[unused218]": 223, "[unused219]": 224, "[unused220]": 225, "[unused221]": 226, "[unused222]": 227, "[unused223]": 228, "[unused224]": 229, "[unused225]": 230, "[unused226]": 231, "[unused227]": 232, "[unused228]": 233, "[unused229]": 234, "[unused230]": 235, "[unused231]": 236, "[unused232]": 237, "[unused233]": 238, "[unused234]": 239, "[unused235]": 240, "[unused236]": 241, "[unused237]": 242, "[unused238]": 243, "[unused239]": 244, "[unused240]": 245, "[unused241]": 246, "[unused242]": 247, "[unused243]": 248, "[unused244]": 249, "[unused245]": 250, "[unused246]": 251, "[unused247]": 252, "[unused248]": 253, "[unused249]": 254, "[unused250]": 255, "[unused251]": 256, "[unused252]": 257, "[unused253]": 258, "[unused254]": 259, "[unused255]": 260, "[unused256]": 261, "[unused257]": 262, "[unused258]": 263, "[unused259]": 264, "[unused260]": 265, "[unused261]": 266, "[unused262]": 267, "[unused263]": 268, "[unused264]": 269, "[unused265]": 270, "[unused266]": 271, "[unused267]": 272, "[unused268]": 273, "[unused269]": 274, "[unused270]": 275, "[unused271]": 276, "[unused272]": 277, "[unused273]": 278, "[unused274]": 279, "[unused275]": 280, "[unused276]": 281, "[unused277]": 282, "[unused278]": 283, "[unused279]": 284, "[unused280]": 285, "[unused281]": 286, "[unused282]": 287, "[unused283]": 288, "[unused284]": 289, "[unused285]": 290, "[unused286]": 291, "[unused287]": 292, "[unused288]": 293, "[unused289]": 294, "[unused290]": 295, "[unused291]": 296, "[unused292]": 297, "[unused293]": 298, "[unused294]": 299, "[unused295]": 300, "[unused296]": 301, "[unused297]": 302, "[unused298]": 303, "[unused299]": 304, "[unused300]": 305, "[unused301]": 306, "[unused302]": 307, "[unused303]": 308, "[unused304]": 309, "[unused305]": 310, "[unused306]": 311, "[unused307]": 312, "[unused308]": 313, "[unused309]": 314, "[unused310]": 315, "[unused311]": 316, "[unused312]": 317, "[unused313]": 318, "[unused314]": 319, "[unused315]": 320, "[unused316]": 321, "[unused317]": 322, "[unused318]": 323, "[unused319]": 324, "[unused320]": 325, "[unused321]": 326, "[unused322]": 327, "[unused323]": 328, "[unused324]": 329, "[unused325]": 330, "[unused326]": 331, "[unused327]": 332, "[unused328]": 333, "[unused329]": 334, "[unused330]": 335, "[unused331]": 336, "[unused332]": 337, "[unused333]": 338, "[unused334]": 339, "[unused335]": 340, "[unused336]": 341, "[unused337]": 342, "[unused338]": 343, "[unused339]": 344, "[unused340]": 345, "[unused341]": 346, "[unused342]": 347, "[unused343]": 348, "[unused344]": 349, "[unused345]": 350, "[unused346]": 351, "[unused347]": 352, "[unused348]": 353, "[unused349]": 354, "[unused350]": 355, "[unused351]": 356, "[unused352]": 357, "[unused353]": 358, "[unused354]": 359, "[unused355]": 360, "[unused356]": 361, "[unused357]": 362, "[unused358]": 363, "[unused359]": 364, "[unused360]": 365, "[unused361]": 366, "[unused362]": 367, "[unused363]": 368, "[unused364]": 369, "[unused365]": 370, "[unused366]": 371, "[unused367]": 372, "[unused368]": 373, "[unused369]": 374, "[unused370]": 375, "[unused371]": 376, "[unused372]": 377, "[unused373]": 378, "[unused374]": 379, "[unused375]": 380, "[unused376]": 381, "[unused377]": 382, "[unused378]": 383, "[unused379]": 384, "[unused380]": 385, "[unused381]": 386, "[unused382]": 387, "[unused383]": 388, "[unused384]": 389, "[unused385]": 390, "[unused386]": 391, "[unused387]": 392, "[unused388]": 393, "[unused389]": 394, "[unused390]": 395, "[unused391]": 396, "[unused392]": 397, "[unused393]": 398, "[unused394]": 399, "[unused395]": 400, "[unused396]": 401, "[unused397]": 402, "[unused398]": 403, "[unused399]": 404, "[unused400]": 405, "[unused401]": 406, "[unused402]": 407, "[unused403]": 408, "[unused404]": 409, "[unused405]": 410, "[unused406]": 411, "[unused407]": 412, "[unused408]": 413, "[unused409]": 414, "[unused410]": 415, "[unused411]": 416, "[unused412]": 417, "[unused413]": 418, "[unused414]": 419, "[unused415]": 420, "[unused416]": 421, "[unused417]": 422, "[unused418]": 423, "[unused419]": 424, "[unused420]": 425, "[unused421]": 426, "[unused422]": 427, "[unused423]": 428, "[unused424]": 429, "[unused425]": 430, "[unused426]": 431, "[unused427]": 432, "[unused428]": 433, "[unused429]": 434, "[unused430]": 435, "[unused431]": 436, "[unused432]": 437, "[unused433]": 438, "[unused434]": 439, "[unused435]": 440, "[unused436]": 441, "[unused437]": 442, "[unused438]": 443, "[unused439]": 444, "[unused440]": 445, "[unused441]": 446, "[unused442]": 447, "[unused443]": 448, "[unused444]": 449, "[unused445]": 450, "[unused446]": 451, "[unused447]": 452, "[unused448]": 453, "[unused449]": 454, "[unused450]": 455, "[unused451]": 456, "[unused452]": 457, "[unused453]": 458, "[unused454]": 459, "[unused455]": 460, "[unused456]": 461, "[unused457]": 462, "[unused458]": 463, "[unused459]": 464, "[unused460]": 465, "[unused461]": 466, "[unused462]": 467, "[unused463]": 468, "[unused464]": 469, "[unused465]": 470, "[unused466]": 471, "[unused467]": 472, "[unused468]": 473, "[unused469]": 474, "[unused470]": 475, "[unused471]": 476, "[unused472]": 477, "[unused473]": 478, "[unused474]": 479, "[unused475]": 480, "[unused476]": 481, "[unused477]": 482, "[unused478]": 483, "[unused479]": 484, "[unused480]": 485, "[unused481]": 486, "[unused482]": 487, "[unused483]": 488, "[unused484]": 489, "[unused485]": 490, "[unused486]": 491, "[unused487]": 492, "[unused488]": 493, "[unused489]": 494, "[unused490]": 495, "[unused491]": 496, "[unused492]": 497, "[unused493]": 498, "[unused494]": 499, "[unused495]": 500, "[unused496]": 501, "[unused497]": 502, "[unused498]": 503, "[unused499]": 504, "[unused500]": 505, "[unused501]": 506, "[unused502]": 507, "[unused503]": 508, "[unused504]": 509, "[unused505]": 510, "[unused506]": 511, "[unused507]": 512, "[unused508]": 513, "[unused509]": 514, "[unused510]": 515, "[unused511]": 516, "[unused512]": 517, "[unused513]": 518, "[unused514]": 519, "[unused515]": 520, "[unused516]": 521, "[unused517]": 522, "[unused518]": 523, "[unused519]": 524, "[unused520]": 525, "[unused521]": 526, "[unused522]": 527, "[unused523]": 528, "[unused524]": 529, "[unused525]": 530, "[unused526]": 531, "[unused527]": 532, "[unused528]": 533, "[unused529]": 534, "[unused530]": 535, "[unused531]": 536, "[unused532]": 537, "[unused533]": 538, "[unused534]": 539, "[unused535]": 540, "[unused536]": 541, "[unused537]": 542, "[unused538]": 543, "[unused539]": 544, "[unused540]": 545, "[unused541]": 546, "[unused542]": 547, "[unused543]": 548, "[unused544]": 549, "[unused545]": 550, "[unused546]": 551, "[unused547]": 552, "[unused548]": 553, "[unused549]": 554, "[unused550]": 555, "[unused551]": 556, "[unused552]": 557, "[unused553]": 558, "[unused554]": 559, "[unused555]": 560, "[unused556]": 561, "[unused557]": 562, "[unused558]": 563, "[unused559]": 564, "[unused560]": 565, "[unused561]": 566, "[unused562]": 567, "[unused563]": 568, "[unused564]": 569, "[unused565]": 570, "[unused566]": 571, "[unused567]": 572, "[unused568]": 573, "[unused569]": 574, "[unused570]": 575, "[unused571]": 576, "[unused572]": 577, "[unused573]": 578, "[unused574]": 579, "[unused575]": 580, "[unused576]": 581, "[unused577]": 582, "[unused578]": 583, "[unused579]": 584, "[unused580]": 585, "[unused581]": 586, "[unused582]": 587, "[unused583]": 588, "[unused584]": 589, "[unused585]": 590, "[unused586]": 591, "[unused587]": 592, "[unused588]": 593, "[unused589]": 594, "[unused590]": 595, "[unused591]": 596, "[unused592]": 597, "[unused593]": 598, "[unused594]": 599, "[unused595]": 600, "[unused596]": 601, "[unused597]": 602, "[unused598]": 603, "[unused599]": 604, "[unused600]": 605, "[unused601]": 606, "[unused602]": 607, "[unused603]": 608, "[unused604]": 609, "[unused605]": 610, "[unused606]": 611, "[unused607]": 612, "[unused608]": 613, "[unused609]": 614, "[unused610]": 615, "[unused611]": 616, "[unused612]": 617, "[unused613]": 618, "[unused614]": 619, "[unused615]": 620, "[unused616]": 621, "[unused617]": 622, "[unused618]": 623, "[unused619]": 624, "[unused620]": 625, "[unused621]": 626, "[unused622]": 627, "[unused623]": 628, "[unused624]": 629, "[unused625]": 630, "[unused626]": 631, "[unused627]": 632, "[unused628]": 633, "[unused629]": 634, "[unused630]": 635, "[unused631]": 636, "[unused632]": 637, "[unused633]": 638, "[unused634]": 639, "[unused635]": 640, "[unused636]": 641, "[unused637]": 642, "[unused638]": 643, "[unused639]": 644, "[unused640]": 645, "[unused641]": 646, "[unused642]": 647, "[unused643]": 648, "[unused644]": 649, "[unused645]": 650, "[unused646]": 651, "[unused647]": 652, "[unused648]": 653, "[unused649]": 654, "[unused650]": 655, "[unused651]": 656, "[unused652]": 657, "[unused653]": 658, "[unused654]": 659, "[unused655]": 660, "[unused656]": 661, "[unused657]": 662, "[unused658]": 663, "[unused659]": 664, "[unused660]": 665, "[unused661]": 666, "[unused662]": 667, "[unused663]": 668, "[unused664]": 669, "[unused665]": 670, "[unused666]": 671, "[unused667]": 672, "[unused668]": 673, "[unused669]": 674, "[unused670]": 675, "[unused671]": 676, "[unused672]": 677, "[unused673]": 678, "[unused674]": 679, "[unused675]": 680, "[unused676]": 681, "[unused677]": 682, "[unused678]": 683, "[unused679]": 684, "[unused680]": 685, "[unused681]": 686, "[unused682]": 687, "[unused683]": 688, "[unused684]": 689, "[unused685]": 690, "[unused686]": 691, "[unused687]": 692, "[unused688]": 693, "[unused689]": 694, "[unused690]": 695, "[unused691]": 696, "[unused692]": 697, "[unused693]": 698, "[unused694]": 699, "[unused695]": 700, "[unused696]": 701, "[unused697]": 702, "[unused698]": 703, "[unused699]": 704, "[unused700]": 705, "[unused701]": 706, "[unused702]": 707, "[unused703]": 708, "[unused704]": 709, "[unused705]": 710, "[unused706]": 711, "[unused707]": 712, "[unused708]": 713, "[unused709]": 714, "[unused710]": 715, "[unused711]": 716, "[unused712]": 717, "[unused713]": 718, "[unused714]": 719, "[unused715]": 720, "[unused716]": 721, "[unused717]": 722, "[unused718]": 723, "[unused719]": 724, "[unused720]": 725, "[unused721]": 726, "[unused722]": 727, "[unused723]": 728, "[unused724]": 729, "[unused725]": 730, "[unused726]": 731, "[unused727]": 732, "[unused728]": 733, "[unused729]": 734, "[unused730]": 735, "[unused731]": 736, "[unused732]": 737, "[unused733]": 738, "[unused734]": 739, "[unused735]": 740, "[unused736]": 741, "[unused737]": 742, "[unused738]": 743, "[unused739]": 744, "[unused740]": 745, "[unused741]": 746, "[unused742]": 747, "[unused743]": 748, "[unused744]": 749, "[unused745]": 750, "[unused746]": 751, "[unused747]": 752, "[unused748]": 753, "[unused749]": 754, "[unused750]": 755, "[unused751]": 756, "[unused752]": 757, "[unused753]": 758, "[unused754]": 759, "[unused755]": 760, "[unused756]": 761, "[unused757]": 762, "[unused758]": 763, "[unused759]": 764, "[unused760]": 765, "[unused761]": 766, "[unused762]": 767, "[unused763]": 768, "[unused764]": 769, "[unused765]": 770, "[unused766]": 771, "[unused767]": 772, "[unused768]": 773, "[unused769]": 774, "[unused770]": 775, "[unused771]": 776, "[unused772]": 777, "[unused773]": 778, "[unused774]": 779, "[unused775]": 780, "[unused776]": 781, "[unused777]": 782, "[unused778]": 783, "[unused779]": 784, "[unused780]": 785, "[unused781]": 786, "[unused782]": 787, "[unused783]": 788, "[unused784]": 789, "[unused785]": 790, "[unused786]": 791, "[unused787]": 792, "[unused788]": 793, "[unused789]": 794, "[unused790]": 795, "[unused791]": 796, "[unused792]": 797, "[unused793]": 798, "[unused794]": 799, "[unused795]": 800, "[unused796]": 801, "[unused797]": 802, "[unused798]": 803, "[unused799]": 804, "[unused800]": 805, "[unused801]": 806, "[unused802]": 807, "[unused803]": 808, "[unused804]": 809, "[unused805]": 810, "[unused806]": 811, "[unused807]": 812, "[unused808]": 813, "[unused809]": 814, "[unused810]": 815, "[unused811]": 816, "[unused812]": 817, "[unused813]": 818, "[unused814]": 819, "[unused815]": 820, "[unused816]": 821, "[unused817]": 822, "[unused818]": 823, "[unused819]": 824, "[unused820]": 825, "[unused821]": 826, "[unused822]": 827, "[unused823]": 828, "[unused824]": 829, "[unused825]": 830, "[unused826]": 831, "[unused827]": 832, "[unused828]": 833, "[unused829]": 834, "[unused830]": 835, "[unused831]": 836, "[unused832]": 837, "[unused833]": 838, "[unused834]": 839, "[unused835]": 840, "[unused836]": 841, "[unused837]": 842, "[unused838]": 843, "[unused839]": 844, "[unused840]": 845, "[unused841]": 846, "[unused842]": 847, "[unused843]": 848, "[unused844]": 849, "[unused845]": 850, "[unused846]": 851, "[unused847]": 852, "[unused848]": 853, "[unused849]": 854, "[unused850]": 855, "[unused851]": 856, "[unused852]": 857, "[unused853]": 858, "[unused854]": 859, "[unused855]": 860, "[unused856]": 861, "[unused857]": 862, "[unused858]": 863, "[unused859]": 864, "[unused860]": 865, "[unused861]": 866, "[unused862]": 867, "[unused863]": 868, "[unused864]": 869, "[unused865]": 870, "[unused866]": 871, "[unused867]": 872, "[unused868]": 873, "[unused869]": 874, "[unused870]": 875, "[unused871]": 876, "[unused872]": 877, "[unused873]": 878, "[unused874]": 879, "[unused875]": 880, "[unused876]": 881, "[unused877]": 882, "[unused878]": 883, "[unused879]": 884, "[unused880]": 885, "[unused881]": 886, "[unused882]": 887, "[unused883]": 888, "[unused884]": 889, "[unused885]": 890, "[unused886]": 891, "[unused887]": 892, "[unused888]": 893, "[unused889]": 894, "[unused890]": 895, "[unused891]": 896, "[unused892]": 897, "[unused893]": 898, "[unused894]": 899, "[unused895]": 900, "[unused896]": 901, "[unused897]": 902, "[unused898]": 903, "[unused899]": 904, "[unused900]": 905, "[unused901]": 906, "[unused902]": 907, "[unused903]": 908, "[unused904]": 909, "[unused905]": 910, "[unused906]": 911, "[unused907]": 912, "[unused908]": 913, "[unused909]": 914, "[unused910]": 915, "[unused911]": 916, "[unused912]": 917, "[unused913]": 918, "[unused914]": 919, "[unused915]": 920, "[unused916]": 921, "[unused917]": 922, "[unused918]": 923, "[unused919]": 924, "[unused920]": 925, "[unused921]": 926, "[unused922]": 927, "[unused923]": 928, "[unused924]": 929, "[unused925]": 930, "[unused926]": 931, "[unused927]": 932, "[unused928]": 933, "[unused929]": 934, "[unused930]": 935, "[unused931]": 936, "[unused932]": 937, "[unused933]": 938, "[unused934]": 939, "[unused935]": 940, "[unused936]": 941, "[unused937]": 942, "[unused938]": 943, "[unused939]": 944, "[unused940]": 945, "[unused941]": 946, "[unused942]": 947, "[unused943]": 948, "[unused944]": 949, "[unused945]": 950, "[unused946]": 951, "[unused947]": 952, "[unused948]": 953, "[unused949]": 954, "[unused950]": 955, "[unused951]": 956, "[unused952]": 957, "[unused953]": 958, "[unused954]": 959, "[unused955]": 960, "[unused956]": 961, "[unused957]": 962, "[unused958]": 963, "[unused959]": 964, "[unused960]": 965, "[unused961]": 966, "[unused962]": 967, "[unused963]": 968, "[unused964]": 969, "[unused965]": 970, "[unused966]": 971, "[unused967]": 972, "[unused968]": 973, "[unused969]": 974, "[unused970]": 975, "[unused971]": 976, "[unused972]": 977, "[unused973]": 978, "[unused974]": 979, "[unused975]": 980, "[unused976]": 981, "[unused977]": 982, "[unused978]": 983, "[unused979]": 984, "[unused980]": 985, "[unused981]": 986, "[unused982]": 987, "[unused983]": 988, "[unused984]": 989, "[unused985]": 990, "[unused986]": 991, "[unused987]": 992, "[unused988]": 993, "[unused989]": 994, "[unused990]": 995, "[unused991]": 996, "[unused992]": 997, "[unused993]": 998, "!": 999, "\"": 1000, "#": 1001, "$": 1002, "%": 1003, "&": 1004, "'": 1005, "(": 1006, ")": 1007, "*": 1008, "+": 1009, ",": 1010, "-": 1011, ".": 1012, "/": 1013, "0": 1014, "1": 1015, "2": 1016, "3": 1017, "4": 1018, "5": 1019, "6": 1020, "7": 1021, "8": 1022, "9": 1023, ":": 1024, ";": 1025, "<": 1026, "=": 1027, ">": 1028, "?": 1029, "@": 1030, "[": 1031, "\\": 1032, "]": 1033, "^": 1034, "_": 1035, "`": 1036, "a": 1037, "b": 1038, "c": 1039, "d": 1040, "e": 1041, "f": 1042, "g": 1043, "h": 1044, "i": 1045, "j": 1046, "k": 1047, "l": 1048, "m": 1049, "n": 1050, "o": 1051, "p": 1052, "q": 1053, "r": 1054, "s": 1055, "t": 1056, "u": 1057, "v": 1058, "w": 1059, "x": 1060, "y": 1061, "z": 1062, "{": 1063, "|": 1064, "}": 1065, "~": 1066, "¡": 1067, "¢": 1068, "£": 1069, "¤": 1070, "¥": 1071, "¦": 1072, "§": 1073, "¨": 1074, "©": 1075, "ª": 1076, "«": 1077, "¬": 1078, "®": 1079, "°": 1080, "±": 1081, "²": 1082, "³": 1083, "´": 1084, "µ": 1085, "¶": 1086, "·": 1087, "¹": 1088, "º": 1089, "»": 1090, "¼": 1091, "½": 1092, "¾": 1093, "¿": 1094, "×": 1095, "ß": 1096, "æ": 1097, "ð": 1098, "÷": 1099, "ø": 1100, "þ": 1101, "đ": 1102, "ħ": 1103, "ı": 1104, "ł": 1105, "ŋ": 1106, "œ": 1107, "ƒ": 1108, "ɐ": 1109, "ɑ": 1110, "ɒ": 1111, "ɔ": 1112, "ɕ": 1113, "ə": 1114, "ɛ": 1115, "ɡ": 1116, "ɣ": 1117, "ɨ": 1118, "ɪ": 1119, "ɫ": 1120, "ɬ": 1121, "ɯ": 1122, "ɲ": 1123, "ɴ": 1124, "ɹ": 1125, "ɾ": 1126, "ʀ": 1127, "ʁ": 1128, "ʂ": 1129, "ʃ": 1130, "ʉ": 1131, "ʊ": 1132, "ʋ": 1133, "ʌ": 1134, "ʎ": 1135, "ʐ": 1136, "ʑ": 1137, "ʒ": 1138, "ʔ": 1139, "ʰ": 1140, "ʲ": 1141, "ʳ": 1142, "ʷ": 1143, "ʸ": 1144, "ʻ": 1145, "ʼ": 1146, "ʾ": 1147, "ʿ": 1148, "ˈ": 1149, "ː": 1150, "ˡ": 1151, "ˢ": 1152, "ˣ": 1153, "ˤ": 1154, "α": 1155, "β": 1156, "γ": 1157, "δ": 1158, "ε": 1159, "ζ": 1160, "η": 1161, "θ": 1162, "ι": 1163, "κ": 1164, "λ": 1165, "μ": 1166, "ν": 1167, "ξ": 1168, "ο": 1169, "π": 1170, "ρ": 1171, "ς": 1172, "σ": 1173, "τ": 1174, "υ": 1175, "φ": 1176, "χ": 1177, "ψ": 1178, "ω": 1179, "а": 1180, "б": 1181, "в": 1182, "г": 1183, "д": 1184, "е": 1185, "ж": 1186, "з": 1187, "и": 1188, "к": 1189, "л": 1190, "м": 1191, "н": 1192, "о": 1193, "п": 1194, "р": 1195, "с": 1196, "т": 1197, "у": 1198, "ф": 1199, "х": 1200, "ц": 1201, "ч": 1202, "ш": 1203, "щ": 1204, "ъ": 1205, "ы": 1206, "ь": 1207, "э": 1208, "ю": 1209, "я": 1210, "ђ": 1211, "є": 1212, "і": 1213, "ј": 1214, "љ": 1215, "њ": 1216, "ћ": 1217, "ӏ": 1218, "ա": 1219, "բ": 1220, "գ": 1221, "դ": 1222, "ե": 1223, "թ": 1224, "ի": 1225, "լ": 1226, "կ": 1227, "հ": 1228, "մ": 1229, "յ": 1230, "ն": 1231, "ո": 1232, "պ": 1233, "ս": 1234, "վ": 1235, "տ": 1236, "ր": 1237, "ւ": 1238, "ք": 1239, "־": 1240, "א": 1241, "ב": 1242, "ג": 1243, "ד": 1244, "ה": 1245, "ו": 1246, "ז": 1247, "ח": 1248, "ט": 1249, "י": 1250, "ך": 1251, "כ": 1252, "ל": 1253, "ם": 1254, "מ": 1255, "ן": 1256, "נ": 1257, "ס": 1258, "ע": 1259, "ף": 1260, "פ": 1261, "ץ": 1262, "צ": 1263, "ק": 1264, "ר": 1265, "ש": 1266, "ת": 1267, "،": 1268, "ء": 1269, "ا": 1270, "ب": 1271, "ة": 1272, "ت": 1273, "ث": 1274, "ج": 1275, "ح": 1276, "خ": 1277, "د": 1278, "ذ": 1279, "ر": 1280, "ز": 1281, "س": 1282, "ش": 1283, "ص": 1284, "ض": 1285, "ط": 1286, "ظ": 1287, "ع": 1288, "غ": 1289, "ـ": 1290, "ف": 1291, "ق": 1292, "ك": 1293, "ل": 1294, "م": 1295, "ن": 1296, "ه": 1297, "و": 1298, "ى": 1299, "ي": 1300, "ٹ": 1301, "پ": 1302, "چ": 1303, "ک": 1304, "گ": 1305, "ں": 1306, "ھ": 1307, "ہ": 1308, "ی": 1309, "ے": 1310, "अ": 1311, "आ": 1312, "उ": 1313, "ए": 1314, "क": 1315, "ख": 1316, "ग": 1317, "च": 1318, "ज": 1319, "ट": 1320, "ड": 1321, "ण": 1322, "त": 1323, "थ": 1324, "द": 1325, "ध": 1326, "न": 1327, "प": 1328, "ब": 1329, "भ": 1330, "म": 1331, "य": 1332, "र": 1333, "ल": 1334, "व": 1335, "श": 1336, "ष": 1337, "स": 1338, "ह": 1339, "ा": 1340, "ि": 1341, "ी": 1342, "ो": 1343, "।": 1344, "॥": 1345, "ং": 1346, "অ": 1347, "আ": 1348, "ই": 1349, "উ": 1350, "এ": 1351, "ও": 1352, "ক": 1353, "খ": 1354, "গ": 1355, "চ": 1356, "ছ": 1357, "জ": 1358, "ট": 1359, "ড": 1360, "ণ": 1361, "ত": 1362, "থ": 1363, "দ": 1364, "ধ": 1365, "ন": 1366, "প": 1367, "ব": 1368, "ভ": 1369, "ম": 1370, "য": 1371, "র": 1372, "ল": 1373, "শ": 1374, "ষ": 1375, "স": 1376, "হ": 1377, "া": 1378, "ি": 1379, "ী": 1380, "ে": 1381, "க": 1382, "ச": 1383, "ட": 1384, "த": 1385, "ந": 1386, "ன": 1387, "ப": 1388, "ம": 1389, "ய": 1390, "ர": 1391, "ல": 1392, "ள": 1393, "வ": 1394, "ா": 1395, "ி": 1396, "ு": 1397, "ே": 1398, "ை": 1399, "ನ": 1400, "ರ": 1401, "ಾ": 1402, "ක": 1403, "ය": 1404, "ර": 1405, "ල": 1406, "ව": 1407, "ා": 1408, "ก": 1409, "ง": 1410, "ต": 1411, "ท": 1412, "น": 1413, "พ": 1414, "ม": 1415, "ย": 1416, "ร": 1417, "ล": 1418, "ว": 1419, "ส": 1420, "อ": 1421, "า": 1422, "เ": 1423, "་": 1424, "།": 1425, "ག": 1426, "ང": 1427, "ད": 1428, "ན": 1429, "པ": 1430, "བ": 1431, "མ": 1432, "འ": 1433, "ར": 1434, "ལ": 1435, "ས": 1436, "မ": 1437, "ა": 1438, "ბ": 1439, "გ": 1440, "დ": 1441, "ე": 1442, "ვ": 1443, "თ": 1444, "ი": 1445, "კ": 1446, "ლ": 1447, "მ": 1448, "ნ": 1449, "ო": 1450, "რ": 1451, "ს": 1452, "ტ": 1453, "უ": 1454, "ᄀ": 1455, "ᄂ": 1456, "ᄃ": 1457, "ᄅ": 1458, "ᄆ": 1459, "ᄇ": 1460, "ᄉ": 1461, "ᄊ": 1462, "ᄋ": 1463, "ᄌ": 1464, "ᄎ": 1465, "ᄏ": 1466, "ᄐ": 1467, "ᄑ": 1468, "ᄒ": 1469, "ᅡ": 1470, "ᅢ": 1471, "ᅥ": 1472, "ᅦ": 1473, "ᅧ": 1474, "ᅩ": 1475, "ᅪ": 1476, "ᅭ": 1477, "ᅮ": 1478, "ᅯ": 1479, "ᅲ": 1480, "ᅳ": 1481, "ᅴ": 1482, "ᅵ": 1483, "ᆨ": 1484, "ᆫ": 1485, "ᆯ": 1486, "ᆷ": 1487, "ᆸ": 1488, "ᆼ": 1489, "ᴬ": 1490, "ᴮ": 1491, "ᴰ": 1492, "ᴵ": 1493, "ᴺ": 1494, "ᵀ": 1495, "ᵃ": 1496, "ᵇ": 1497, "ᵈ": 1498, "ᵉ": 1499, "ᵍ": 1500, "ᵏ": 1501, "ᵐ": 1502, "ᵒ": 1503, "ᵖ": 1504, "ᵗ": 1505, "ᵘ": 1506, "ᵢ": 1507, "ᵣ": 1508, "ᵤ": 1509, "ᵥ": 1510, "ᶜ": 1511, "ᶠ": 1512, "‐": 1513, "‑": 1514, "‒": 1515, "–": 1516, "—": 1517, "―": 1518, "‖": 1519, "‘": 1520, "’": 1521, "‚": 1522, "“": 1523, "”": 1524, "„": 1525, "†": 1526, "‡": 1527, "•": 1528, "…": 1529, "‰": 1530, "′": 1531, "″": 1532, "›": 1533, "‿": 1534, "⁄": 1535, "⁰": 1536, "ⁱ": 1537, "⁴": 1538, "⁵": 1539, "⁶": 1540, "⁷": 1541, "⁸": 1542, "⁹": 1543, "⁺": 1544, "⁻": 1545, "ⁿ": 1546, "₀": 1547, "₁": 1548, "₂": 1549, "₃": 1550, "₄": 1551, "₅": 1552, "₆": 1553, "₇": 1554, "₈": 1555, "₉": 1556, "₊": 1557, "₍": 1558, "₎": 1559, "ₐ": 1560, "ₑ": 1561, "ₒ": 1562, "ₓ": 1563, "ₕ": 1564, "ₖ": 1565, "ₗ": 1566, "ₘ": 1567, "ₙ": 1568, "ₚ": 1569, "ₛ": 1570, "ₜ": 1571, "₤": 1572, "₩": 1573, "€": 1574, "₱": 1575, "₹": 1576, "ℓ": 1577, "№": 1578, "ℝ": 1579, "™": 1580, "⅓": 1581, "⅔": 1582, "←": 1583, "↑": 1584, "→": 1585, "↓": 1586, "↔": 1587, "↦": 1588, "⇄": 1589, "⇌": 1590, "⇒": 1591, "∂": 1592, "∅": 1593, "∆": 1594, "∇": 1595, "∈": 1596, "−": 1597, "∗": 1598, "∘": 1599, "√": 1600, "∞": 1601, "∧": 1602, "∨": 1603, "∩": 1604, "∪": 1605, "≈": 1606, "≡": 1607, "≤": 1608, "≥": 1609, "⊂": 1610, "⊆": 1611, "⊕": 1612, "⊗": 1613, "⋅": 1614, "─": 1615, "│": 1616, "■": 1617, "▪": 1618, "●": 1619, "★": 1620, "☆": 1621, "☉": 1622, "♠": 1623, "♣": 1624, "♥": 1625, "♦": 1626, "♭": 1627, "♯": 1628, "⟨": 1629, "⟩": 1630, "ⱼ": 1631, "⺩": 1632, "⺼": 1633, "⽥": 1634, "、": 1635, "。": 1636, "〈": 1637, "〉": 1638, "《": 1639, "》": 1640, "「": 1641, "」": 1642, "『": 1643, "』": 1644, "〜": 1645, "あ": 1646, "い": 1647, "う": 1648, "え": 1649, "お": 1650, "か": 1651, "き": 1652, "く": 1653, "け": 1654, "こ": 1655, "さ": 1656, "し": 1657, "す": 1658, "せ": 1659, "そ": 1660, "た": 1661, "ち": 1662, "っ": 1663, "つ": 1664, "て": 1665, "と": 1666, "な": 1667, "に": 1668, "ぬ": 1669, "ね": 1670, "の": 1671, "は": 1672, "ひ": 1673, "ふ": 1674, "へ": 1675, "ほ": 1676, "ま": 1677, "み": 1678, "む": 1679, "め": 1680, "も": 1681, "や": 1682, "ゆ": 1683, "よ": 1684, "ら": 1685, "り": 1686, "る": 1687, "れ": 1688, "ろ": 1689, "を": 1690, "ん": 1691, "ァ": 1692, "ア": 1693, "ィ": 1694, "イ": 1695, "ウ": 1696, "ェ": 1697, "エ": 1698, "オ": 1699, "カ": 1700, "キ": 1701, "ク": 1702, "ケ": 1703, "コ": 1704, "サ": 1705, "シ": 1706, "ス": 1707, "セ": 1708, "タ": 1709, "チ": 1710, "ッ": 1711, "ツ": 1712, "テ": 1713, "ト": 1714, "ナ": 1715, "ニ": 1716, "ノ": 1717, "ハ": 1718, "ヒ": 1719, "フ": 1720, "ヘ": 1721, "ホ": 1722, "マ": 1723, "ミ": 1724, "ム": 1725, "メ": 1726, "モ": 1727, "ャ": 1728, "ュ": 1729, "ョ": 1730, "ラ": 1731, "リ": 1732, "ル": 1733, "レ": 1734, "ロ": 1735, "ワ": 1736, "ン": 1737, "・": 1738, "ー": 1739, "一": 1740, "三": 1741, "上": 1742, "下": 1743, "不": 1744, "世": 1745, "中": 1746, "主": 1747, "久": 1748, "之": 1749, "也": 1750, "事": 1751, "二": 1752, "五": 1753, "井": 1754, "京": 1755, "人": 1756, "亻": 1757, "仁": 1758, "介": 1759, "代": 1760, "仮": 1761, "伊": 1762, "会": 1763, "佐": 1764, "侍": 1765, "保": 1766, "信": 1767, "健": 1768, "元": 1769, "光": 1770, "八": 1771, "公": 1772, "内": 1773, "出": 1774, "分": 1775, "前": 1776, "劉": 1777, "力": 1778, "加": 1779, "勝": 1780, "北": 1781, "区": 1782, "十": 1783, "千": 1784, "南": 1785, "博": 1786, "原": 1787, "口": 1788, "古": 1789, "史": 1790, "司": 1791, "合": 1792, "吉": 1793, "同": 1794, "名": 1795, "和": 1796, "囗": 1797, "四": 1798, "国": 1799, "國": 1800, "土": 1801, "地": 1802, "坂": 1803, "城": 1804, "堂": 1805, "場": 1806, "士": 1807, "夏": 1808, "外": 1809, "大": 1810, "天": 1811, "太": 1812, "夫": 1813, "奈": 1814, "女": 1815, "子": 1816, "学": 1817, "宀": 1818, "宇": 1819, "安": 1820, "宗": 1821, "定": 1822, "宣": 1823, "宮": 1824, "家": 1825, "宿": 1826, "寺": 1827, "將": 1828, "小": 1829, "尚": 1830, "山": 1831, "岡": 1832, "島": 1833, "崎": 1834, "川": 1835, "州": 1836, "巿": 1837, "帝": 1838, "平": 1839, "年": 1840, "幸": 1841, "广": 1842, "弘": 1843, "張": 1844, "彳": 1845, "後": 1846, "御": 1847, "德": 1848, "心": 1849, "忄": 1850, "志": 1851, "忠": 1852, "愛": 1853, "成": 1854, "我": 1855, "戦": 1856, "戸": 1857, "手": 1858, "扌": 1859, "政": 1860, "文": 1861, "新": 1862, "方": 1863, "日": 1864, "明": 1865, "星": 1866, "春": 1867, "昭": 1868, "智": 1869, "曲": 1870, "書": 1871, "月": 1872, "有": 1873, "朝": 1874, "木": 1875, "本": 1876, "李": 1877, "村": 1878, "東": 1879, "松": 1880, "林": 1881, "森": 1882, "楊": 1883, "樹": 1884, "橋": 1885, "歌": 1886, "止": 1887, "正": 1888, "武": 1889, "比": 1890, "氏": 1891, "民": 1892, "水": 1893, "氵": 1894, "氷": 1895, "永": 1896, "江": 1897, "沢": 1898, "河": 1899, "治": 1900, "法": 1901, "海": 1902, "清": 1903, "漢": 1904, "瀬": 1905, "火": 1906, "版": 1907, "犬": 1908, "王": 1909, "生": 1910, "田": 1911, "男": 1912, "疒": 1913, "発": 1914, "白": 1915, "的": 1916, "皇": 1917, "目": 1918, "相": 1919, "省": 1920, "真": 1921, "石": 1922, "示": 1923, "社": 1924, "神": 1925, "福": 1926, "禾": 1927, "秀": 1928, "秋": 1929, "空": 1930, "立": 1931, "章": 1932, "竹": 1933, "糹": 1934, "美": 1935, "義": 1936, "耳": 1937, "良": 1938, "艹": 1939, "花": 1940, "英": 1941, "華": 1942, "葉": 1943, "藤": 1944, "行": 1945, "街": 1946, "西": 1947, "見": 1948, "訁": 1949, "語": 1950, "谷": 1951, "貝": 1952, "貴": 1953, "車": 1954, "軍": 1955, "辶": 1956, "道": 1957, "郎": 1958, "郡": 1959, "部": 1960, "都": 1961, "里": 1962, "野": 1963, "金": 1964, "鈴": 1965, "镇": 1966, "長": 1967, "門": 1968, "間": 1969, "阝": 1970, "阿": 1971, "陳": 1972, "陽": 1973, "雄": 1974, "青": 1975, "面": 1976, "風": 1977, "食": 1978, "香": 1979, "馬": 1980, "高": 1981, "龍": 1982, "龸": 1983, "fi": 1984, "fl": 1985, "!": 1986, "(": 1987, ")": 1988, ",": 1989, "-": 1990, ".": 1991, "/": 1992, ":": 1993, "?": 1994, "~": 1995, "the": 1996, "of": 1997, "and": 1998, "in": 1999, "to": 2000, "was": 2001, "he": 2002, "is": 2003, "as": 2004, "for": 2005, "on": 2006, "with": 2007, "that": 2008, "it": 2009, "his": 2010, "by": 2011, "at": 2012, "from": 2013, "her": 2014, "##s": 2015, "she": 2016, "you": 2017, "had": 2018, "an": 2019, "were": 2020, "but": 2021, "be": 2022, "this": 2023, "are": 2024, "not": 2025, "my": 2026, "they": 2027, "one": 2028, "which": 2029, "or": 2030, "have": 2031, "him": 2032, "me": 2033, "first": 2034, "all": 2035, "also": 2036, "their": 2037, "has": 2038, "up": 2039, "who": 2040, "out": 2041, "been": 2042, "when": 2043, "after": 2044, "there": 2045, "into": 2046, "new": 2047, "two": 2048, "its": 2049, "##a": 2050, "time": 2051, "would": 2052, "no": 2053, "what": 2054, "about": 2055, "said": 2056, "we": 2057, "over": 2058, "then": 2059, "other": 2060, "so": 2061, "more": 2062, "##e": 2063, "can": 2064, "if": 2065, "like": 2066, "back": 2067, "them": 2068, "only": 2069, "some": 2070, "could": 2071, "##i": 2072, "where": 2073, "just": 2074, "##ing": 2075, "during": 2076, "before": 2077, "##n": 2078, "do": 2079, "##o": 2080, "made": 2081, "school": 2082, "through": 2083, "than": 2084, "now": 2085, "years": 2086, "most": 2087, "world": 2088, "may": 2089, "between": 2090, "down": 2091, "well": 2092, "three": 2093, "##d": 2094, "year": 2095, "while": 2096, "will": 2097, "##ed": 2098, "##r": 2099, "##y": 2100, "later": 2101, "##t": 2102, "city": 2103, "under": 2104, "around": 2105, "did": 2106, "such": 2107, "being": 2108, "used": 2109, "state": 2110, "people": 2111, "part": 2112, "know": 2113, "against": 2114, "your": 2115, "many": 2116, "second": 2117, "university": 2118, "both": 2119, "national": 2120, "##er": 2121, "these": 2122, "don": 2123, "known": 2124, "off": 2125, "way": 2126, "until": 2127, "re": 2128, "how": 2129, "even": 2130, "get": 2131, "head": 2132, "...": 2133, "didn": 2134, "##ly": 2135, "team": 2136, "american": 2137, "because": 2138, "de": 2139, "##l": 2140, "born": 2141, "united": 2142, "film": 2143, "since": 2144, "still": 2145, "long": 2146, "work": 2147, "south": 2148, "us": 2149, "became": 2150, "any": 2151, "high": 2152, "again": 2153, "day": 2154, "family": 2155, "see": 2156, "right": 2157, "man": 2158, "eyes": 2159, "house": 2160, "season": 2161, "war": 2162, "states": 2163, "including": 2164, "took": 2165, "life": 2166, "north": 2167, "same": 2168, "each": 2169, "called": 2170, "name": 2171, "much": 2172, "place": 2173, "however": 2174, "go": 2175, "four": 2176, "group": 2177, "another": 2178, "found": 2179, "won": 2180, "area": 2181, "here": 2182, "going": 2183, "10": 2184, "away": 2185, "series": 2186, "left": 2187, "home": 2188, "music": 2189, "best": 2190, "make": 2191, "hand": 2192, "number": 2193, "company": 2194, "several": 2195, "never": 2196, "last": 2197, "john": 2198, "000": 2199, "very": 2200, "album": 2201, "take": 2202, "end": 2203, "good": 2204, "too": 2205, "following": 2206, "released": 2207, "game": 2208, "played": 2209, "little": 2210, "began": 2211, "district": 2212, "##m": 2213, "old": 2214, "want": 2215, "those": 2216, "side": 2217, "held": 2218, "own": 2219, "early": 2220, "county": 2221, "ll": 2222, "league": 2223, "use": 2224, "west": 2225, "##u": 2226, "face": 2227, "think": 2228, "##es": 2229, "2010": 2230, "government": 2231, "##h": 2232, "march": 2233, "came": 2234, "small": 2235, "general": 2236, "town": 2237, "june": 2238, "##on": 2239, "line": 2240, "based": 2241, "something": 2242, "##k": 2243, "september": 2244, "thought": 2245, "looked": 2246, "along": 2247, "international": 2248, "2011": 2249, "air": 2250, "july": 2251, "club": 2252, "went": 2253, "january": 2254, "october": 2255, "our": 2256, "august": 2257, "april": 2258, "york": 2259, "12": 2260, "few": 2261, "2012": 2262, "2008": 2263, "east": 2264, "show": 2265, "member": 2266, "college": 2267, "2009": 2268, "father": 2269, "public": 2270, "##us": 2271, "come": 2272, "men": 2273, "five": 2274, "set": 2275, "station": 2276, "church": 2277, "##c": 2278, "next": 2279, "former": 2280, "november": 2281, "room": 2282, "party": 2283, "located": 2284, "december": 2285, "2013": 2286, "age": 2287, "got": 2288, "2007": 2289, "##g": 2290, "system": 2291, "let": 2292, "love": 2293, "2006": 2294, "though": 2295, "every": 2296, "2014": 2297, "look": 2298, "song": 2299, "water": 2300, "century": 2301, "without": 2302, "body": 2303, "black": 2304, "night": 2305, "within": 2306, "great": 2307, "women": 2308, "single": 2309, "ve": 2310, "building": 2311, "large": 2312, "population": 2313, "river": 2314, "named": 2315, "band": 2316, "white": 2317, "started": 2318, "##an": 2319, "once": 2320, "15": 2321, "20": 2322, "should": 2323, "18": 2324, "2015": 2325, "service": 2326, "top": 2327, "built": 2328, "british": 2329, "open": 2330, "death": 2331, "king": 2332, "moved": 2333, "local": 2334, "times": 2335, "children": 2336, "february": 2337, "book": 2338, "why": 2339, "11": 2340, "door": 2341, "need": 2342, "president": 2343, "order": 2344, "final": 2345, "road": 2346, "wasn": 2347, "although": 2348, "due": 2349, "major": 2350, "died": 2351, "village": 2352, "third": 2353, "knew": 2354, "2016": 2355, "asked": 2356, "turned": 2357, "st": 2358, "wanted": 2359, "say": 2360, "##p": 2361, "together": 2362, "received": 2363, "main": 2364, "son": 2365, "served": 2366, "different": 2367, "##en": 2368, "behind": 2369, "himself": 2370, "felt": 2371, "members": 2372, "power": 2373, "football": 2374, "law": 2375, "voice": 2376, "play": 2377, "##in": 2378, "near": 2379, "park": 2380, "history": 2381, "30": 2382, "having": 2383, "2005": 2384, "16": 2385, "##man": 2386, "saw": 2387, "mother": 2388, "##al": 2389, "army": 2390, "point": 2391, "front": 2392, "help": 2393, "english": 2394, "street": 2395, "art": 2396, "late": 2397, "hands": 2398, "games": 2399, "award": 2400, "##ia": 2401, "young": 2402, "14": 2403, "put": 2404, "published": 2405, "country": 2406, "division": 2407, "across": 2408, "told": 2409, "13": 2410, "often": 2411, "ever": 2412, "french": 2413, "london": 2414, "center": 2415, "six": 2416, "red": 2417, "2017": 2418, "led": 2419, "days": 2420, "include": 2421, "light": 2422, "25": 2423, "find": 2424, "tell": 2425, "among": 2426, "species": 2427, "really": 2428, "according": 2429, "central": 2430, "half": 2431, "2004": 2432, "form": 2433, "original": 2434, "gave": 2435, "office": 2436, "making": 2437, "enough": 2438, "lost": 2439, "full": 2440, "opened": 2441, "must": 2442, "included": 2443, "live": 2444, "given": 2445, "german": 2446, "player": 2447, "run": 2448, "business": 2449, "woman": 2450, "community": 2451, "cup": 2452, "might": 2453, "million": 2454, "land": 2455, "2000": 2456, "court": 2457, "development": 2458, "17": 2459, "short": 2460, "round": 2461, "ii": 2462, "km": 2463, "seen": 2464, "class": 2465, "story": 2466, "always": 2467, "become": 2468, "sure": 2469, "research": 2470, "almost": 2471, "director": 2472, "council": 2473, "la": 2474, "##2": 2475, "career": 2476, "things": 2477, "using": 2478, "island": 2479, "##z": 2480, "couldn": 2481, "car": 2482, "##is": 2483, "24": 2484, "close": 2485, "force": 2486, "##1": 2487, "better": 2488, "free": 2489, "support": 2490, "control": 2491, "field": 2492, "students": 2493, "2003": 2494, "education": 2495, "married": 2496, "##b": 2497, "nothing": 2498, "worked": 2499, "others": 2500, "record": 2501, "big": 2502, "inside": 2503, "level": 2504, "anything": 2505, "continued": 2506, "give": 2507, "james": 2508, "##3": 2509, "military": 2510, "established": 2511, "non": 2512, "returned": 2513, "feel": 2514, "does": 2515, "title": 2516, "written": 2517, "thing": 2518, "feet": 2519, "william": 2520, "far": 2521, "co": 2522, "association": 2523, "hard": 2524, "already": 2525, "2002": 2526, "##ra": 2527, "championship": 2528, "human": 2529, "western": 2530, "100": 2531, "##na": 2532, "department": 2533, "hall": 2534, "role": 2535, "various": 2536, "production": 2537, "21": 2538, "19": 2539, "heart": 2540, "2001": 2541, "living": 2542, "fire": 2543, "version": 2544, "##ers": 2545, "##f": 2546, "television": 2547, "royal": 2548, "##4": 2549, "produced": 2550, "working": 2551, "act": 2552, "case": 2553, "society": 2554, "region": 2555, "present": 2556, "radio": 2557, "period": 2558, "looking": 2559, "least": 2560, "total": 2561, "keep": 2562, "england": 2563, "wife": 2564, "program": 2565, "per": 2566, "brother": 2567, "mind": 2568, "special": 2569, "22": 2570, "##le": 2571, "am": 2572, "works": 2573, "soon": 2574, "##6": 2575, "political": 2576, "george": 2577, "services": 2578, "taken": 2579, "created": 2580, "##7": 2581, "further": 2582, "able": 2583, "reached": 2584, "david": 2585, "union": 2586, "joined": 2587, "upon": 2588, "done": 2589, "important": 2590, "social": 2591, "information": 2592, "either": 2593, "##ic": 2594, "##x": 2595, "appeared": 2596, "position": 2597, "ground": 2598, "lead": 2599, "rock": 2600, "dark": 2601, "election": 2602, "23": 2603, "board": 2604, "france": 2605, "hair": 2606, "course": 2607, "arms": 2608, "site": 2609, "police": 2610, "girl": 2611, "instead": 2612, "real": 2613, "sound": 2614, "##v": 2615, "words": 2616, "moment": 2617, "##te": 2618, "someone": 2619, "##8": 2620, "summer": 2621, "project": 2622, "announced": 2623, "san": 2624, "less": 2625, "wrote": 2626, "past": 2627, "followed": 2628, "##5": 2629, "blue": 2630, "founded": 2631, "al": 2632, "finally": 2633, "india": 2634, "taking": 2635, "records": 2636, "america": 2637, "##ne": 2638, "1999": 2639, "design": 2640, "considered": 2641, "northern": 2642, "god": 2643, "stop": 2644, "battle": 2645, "toward": 2646, "european": 2647, "outside": 2648, "described": 2649, "track": 2650, "today": 2651, "playing": 2652, "language": 2653, "28": 2654, "call": 2655, "26": 2656, "heard": 2657, "professional": 2658, "low": 2659, "australia": 2660, "miles": 2661, "california": 2662, "win": 2663, "yet": 2664, "green": 2665, "##ie": 2666, "trying": 2667, "blood": 2668, "##ton": 2669, "southern": 2670, "science": 2671, "maybe": 2672, "everything": 2673, "match": 2674, "square": 2675, "27": 2676, "mouth": 2677, "video": 2678, "race": 2679, "recorded": 2680, "leave": 2681, "above": 2682, "##9": 2683, "daughter": 2684, "points": 2685, "space": 2686, "1998": 2687, "museum": 2688, "change": 2689, "middle": 2690, "common": 2691, "##0": 2692, "move": 2693, "tv": 2694, "post": 2695, "##ta": 2696, "lake": 2697, "seven": 2698, "tried": 2699, "elected": 2700, "closed": 2701, "ten": 2702, "paul": 2703, "minister": 2704, "##th": 2705, "months": 2706, "start": 2707, "chief": 2708, "return": 2709, "canada": 2710, "person": 2711, "sea": 2712, "release": 2713, "similar": 2714, "modern": 2715, "brought": 2716, "rest": 2717, "hit": 2718, "formed": 2719, "mr": 2720, "##la": 2721, "1997": 2722, "floor": 2723, "event": 2724, "doing": 2725, "thomas": 2726, "1996": 2727, "robert": 2728, "care": 2729, "killed": 2730, "training": 2731, "star": 2732, "week": 2733, "needed": 2734, "turn": 2735, "finished": 2736, "railway": 2737, "rather": 2738, "news": 2739, "health": 2740, "sent": 2741, "example": 2742, "ran": 2743, "term": 2744, "michael": 2745, "coming": 2746, "currently": 2747, "yes": 2748, "forces": 2749, "despite": 2750, "gold": 2751, "areas": 2752, "50": 2753, "stage": 2754, "fact": 2755, "29": 2756, "dead": 2757, "says": 2758, "popular": 2759, "2018": 2760, "originally": 2761, "germany": 2762, "probably": 2763, "developed": 2764, "result": 2765, "pulled": 2766, "friend": 2767, "stood": 2768, "money": 2769, "running": 2770, "mi": 2771, "signed": 2772, "word": 2773, "songs": 2774, "child": 2775, "eventually": 2776, "met": 2777, "tour": 2778, "average": 2779, "teams": 2780, "minutes": 2781, "festival": 2782, "current": 2783, "deep": 2784, "kind": 2785, "1995": 2786, "decided": 2787, "usually": 2788, "eastern": 2789, "seemed": 2790, "##ness": 2791, "episode": 2792, "bed": 2793, "added": 2794, "table": 2795, "indian": 2796, "private": 2797, "charles": 2798, "route": 2799, "available": 2800, "idea": 2801, "throughout": 2802, "centre": 2803, "addition": 2804, "appointed": 2805, "style": 2806, "1994": 2807, "books": 2808, "eight": 2809, "construction": 2810, "press": 2811, "mean": 2812, "wall": 2813, "friends": 2814, "remained": 2815, "schools": 2816, "study": 2817, "##ch": 2818, "##um": 2819, "institute": 2820, "oh": 2821, "chinese": 2822, "sometimes": 2823, "events": 2824, "possible": 2825, "1992": 2826, "australian": 2827, "type": 2828, "brown": 2829, "forward": 2830, "talk": 2831, "process": 2832, "food": 2833, "debut": 2834, "seat": 2835, "performance": 2836, "committee": 2837, "features": 2838, "character": 2839, "arts": 2840, "herself": 2841, "else": 2842, "lot": 2843, "strong": 2844, "russian": 2845, "range": 2846, "hours": 2847, "peter": 2848, "arm": 2849, "##da": 2850, "morning": 2851, "dr": 2852, "sold": 2853, "##ry": 2854, "quickly": 2855, "directed": 2856, "1993": 2857, "guitar": 2858, "china": 2859, "##w": 2860, "31": 2861, "list": 2862, "##ma": 2863, "performed": 2864, "media": 2865, "uk": 2866, "players": 2867, "smile": 2868, "##rs": 2869, "myself": 2870, "40": 2871, "placed": 2872, "coach": 2873, "province": 2874, "towards": 2875, "wouldn": 2876, "leading": 2877, "whole": 2878, "boy": 2879, "official": 2880, "designed": 2881, "grand": 2882, "census": 2883, "##el": 2884, "europe": 2885, "attack": 2886, "japanese": 2887, "henry": 2888, "1991": 2889, "##re": 2890, "##os": 2891, "cross": 2892, "getting": 2893, "alone": 2894, "action": 2895, "lower": 2896, "network": 2897, "wide": 2898, "washington": 2899, "japan": 2900, "1990": 2901, "hospital": 2902, "believe": 2903, "changed": 2904, "sister": 2905, "##ar": 2906, "hold": 2907, "gone": 2908, "sir": 2909, "hadn": 2910, "ship": 2911, "##ka": 2912, "studies": 2913, "academy": 2914, "shot": 2915, "rights": 2916, "below": 2917, "base": 2918, "bad": 2919, "involved": 2920, "kept": 2921, "largest": 2922, "##ist": 2923, "bank": 2924, "future": 2925, "especially": 2926, "beginning": 2927, "mark": 2928, "movement": 2929, "section": 2930, "female": 2931, "magazine": 2932, "plan": 2933, "professor": 2934, "lord": 2935, "longer": 2936, "##ian": 2937, "sat": 2938, "walked": 2939, "hill": 2940, "actually": 2941, "civil": 2942, "energy": 2943, "model": 2944, "families": 2945, "size": 2946, "thus": 2947, "aircraft": 2948, "completed": 2949, "includes": 2950, "data": 2951, "captain": 2952, "##or": 2953, "fight": 2954, "vocals": 2955, "featured": 2956, "richard": 2957, "bridge": 2958, "fourth": 2959, "1989": 2960, "officer": 2961, "stone": 2962, "hear": 2963, "##ism": 2964, "means": 2965, "medical": 2966, "groups": 2967, "management": 2968, "self": 2969, "lips": 2970, "competition": 2971, "entire": 2972, "lived": 2973, "technology": 2974, "leaving": 2975, "federal": 2976, "tournament": 2977, "bit": 2978, "passed": 2979, "hot": 2980, "independent": 2981, "awards": 2982, "kingdom": 2983, "mary": 2984, "spent": 2985, "fine": 2986, "doesn": 2987, "reported": 2988, "##ling": 2989, "jack": 2990, "fall": 2991, "raised": 2992, "itself": 2993, "stay": 2994, "true": 2995, "studio": 2996, "1988": 2997, "sports": 2998, "replaced": 2999, "paris": 3000, "systems": 3001, "saint": 3002, "leader": 3003, "theatre": 3004, "whose": 3005, "market": 3006, "capital": 3007, "parents": 3008, "spanish": 3009, "canadian": 3010, "earth": 3011, "##ity": 3012, "cut": 3013, "degree": 3014, "writing": 3015, "bay": 3016, "christian": 3017, "awarded": 3018, "natural": 3019, "higher": 3020, "bill": 3021, "##as": 3022, "coast": 3023, "provided": 3024, "previous": 3025, "senior": 3026, "ft": 3027, "valley": 3028, "organization": 3029, "stopped": 3030, "onto": 3031, "countries": 3032, "parts": 3033, "conference": 3034, "queen": 3035, "security": 3036, "interest": 3037, "saying": 3038, "allowed": 3039, "master": 3040, "earlier": 3041, "phone": 3042, "matter": 3043, "smith": 3044, "winning": 3045, "try": 3046, "happened": 3047, "moving": 3048, "campaign": 3049, "los": 3050, "##ley": 3051, "breath": 3052, "nearly": 3053, "mid": 3054, "1987": 3055, "certain": 3056, "girls": 3057, "date": 3058, "italian": 3059, "african": 3060, "standing": 3061, "fell": 3062, "artist": 3063, "##ted": 3064, "shows": 3065, "deal": 3066, "mine": 3067, "industry": 3068, "1986": 3069, "##ng": 3070, "everyone": 3071, "republic": 3072, "provide": 3073, "collection": 3074, "library": 3075, "student": 3076, "##ville": 3077, "primary": 3078, "owned": 3079, "older": 3080, "via": 3081, "heavy": 3082, "1st": 3083, "makes": 3084, "##able": 3085, "attention": 3086, "anyone": 3087, "africa": 3088, "##ri": 3089, "stated": 3090, "length": 3091, "ended": 3092, "fingers": 3093, "command": 3094, "staff": 3095, "skin": 3096, "foreign": 3097, "opening": 3098, "governor": 3099, "okay": 3100, "medal": 3101, "kill": 3102, "sun": 3103, "cover": 3104, "job": 3105, "1985": 3106, "introduced": 3107, "chest": 3108, "hell": 3109, "feeling": 3110, "##ies": 3111, "success": 3112, "meet": 3113, "reason": 3114, "standard": 3115, "meeting": 3116, "novel": 3117, "1984": 3118, "trade": 3119, "source": 3120, "buildings": 3121, "##land": 3122, "rose": 3123, "guy": 3124, "goal": 3125, "##ur": 3126, "chapter": 3127, "native": 3128, "husband": 3129, "previously": 3130, "unit": 3131, "limited": 3132, "entered": 3133, "weeks": 3134, "producer": 3135, "operations": 3136, "mountain": 3137, "takes": 3138, "covered": 3139, "forced": 3140, "related": 3141, "roman": 3142, "complete": 3143, "successful": 3144, "key": 3145, "texas": 3146, "cold": 3147, "##ya": 3148, "channel": 3149, "1980": 3150, "traditional": 3151, "films": 3152, "dance": 3153, "clear": 3154, "approximately": 3155, "500": 3156, "nine": 3157, "van": 3158, "prince": 3159, "question": 3160, "active": 3161, "tracks": 3162, "ireland": 3163, "regional": 3164, "silver": 3165, "author": 3166, "personal": 3167, "sense": 3168, "operation": 3169, "##ine": 3170, "economic": 3171, "1983": 3172, "holding": 3173, "twenty": 3174, "isbn": 3175, "additional": 3176, "speed": 3177, "hour": 3178, "edition": 3179, "regular": 3180, "historic": 3181, "places": 3182, "whom": 3183, "shook": 3184, "movie": 3185, "km²": 3186, "secretary": 3187, "prior": 3188, "report": 3189, "chicago": 3190, "read": 3191, "foundation": 3192, "view": 3193, "engine": 3194, "scored": 3195, "1982": 3196, "units": 3197, "ask": 3198, "airport": 3199, "property": 3200, "ready": 3201, "immediately": 3202, "lady": 3203, "month": 3204, "listed": 3205, "contract": 3206, "##de": 3207, "manager": 3208, "themselves": 3209, "lines": 3210, "##ki": 3211, "navy": 3212, "writer": 3213, "meant": 3214, "##ts": 3215, "runs": 3216, "##ro": 3217, "practice": 3218, "championships": 3219, "singer": 3220, "glass": 3221, "commission": 3222, "required": 3223, "forest": 3224, "starting": 3225, "culture": 3226, "generally": 3227, "giving": 3228, "access": 3229, "attended": 3230, "test": 3231, "couple": 3232, "stand": 3233, "catholic": 3234, "martin": 3235, "caught": 3236, "executive": 3237, "##less": 3238, "eye": 3239, "##ey": 3240, "thinking": 3241, "chair": 3242, "quite": 3243, "shoulder": 3244, "1979": 3245, "hope": 3246, "decision": 3247, "plays": 3248, "defeated": 3249, "municipality": 3250, "whether": 3251, "structure": 3252, "offered": 3253, "slowly": 3254, "pain": 3255, "ice": 3256, "direction": 3257, "##ion": 3258, "paper": 3259, "mission": 3260, "1981": 3261, "mostly": 3262, "200": 3263, "noted": 3264, "individual": 3265, "managed": 3266, "nature": 3267, "lives": 3268, "plant": 3269, "##ha": 3270, "helped": 3271, "except": 3272, "studied": 3273, "computer": 3274, "figure": 3275, "relationship": 3276, "issue": 3277, "significant": 3278, "loss": 3279, "die": 3280, "smiled": 3281, "gun": 3282, "ago": 3283, "highest": 3284, "1972": 3285, "##am": 3286, "male": 3287, "bring": 3288, "goals": 3289, "mexico": 3290, "problem": 3291, "distance": 3292, "commercial": 3293, "completely": 3294, "location": 3295, "annual": 3296, "famous": 3297, "drive": 3298, "1976": 3299, "neck": 3300, "1978": 3301, "surface": 3302, "caused": 3303, "italy": 3304, "understand": 3305, "greek": 3306, "highway": 3307, "wrong": 3308, "hotel": 3309, "comes": 3310, "appearance": 3311, "joseph": 3312, "double": 3313, "issues": 3314, "musical": 3315, "companies": 3316, "castle": 3317, "income": 3318, "review": 3319, "assembly": 3320, "bass": 3321, "initially": 3322, "parliament": 3323, "artists": 3324, "experience": 3325, "1974": 3326, "particular": 3327, "walk": 3328, "foot": 3329, "engineering": 3330, "talking": 3331, "window": 3332, "dropped": 3333, "##ter": 3334, "miss": 3335, "baby": 3336, "boys": 3337, "break": 3338, "1975": 3339, "stars": 3340, "edge": 3341, "remember": 3342, "policy": 3343, "carried": 3344, "train": 3345, "stadium": 3346, "bar": 3347, "sex": 3348, "angeles": 3349, "evidence": 3350, "##ge": 3351, "becoming": 3352, "assistant": 3353, "soviet": 3354, "1977": 3355, "upper": 3356, "step": 3357, "wing": 3358, "1970": 3359, "youth": 3360, "financial": 3361, "reach": 3362, "##ll": 3363, "actor": 3364, "numerous": 3365, "##se": 3366, "##st": 3367, "nodded": 3368, "arrived": 3369, "##ation": 3370, "minute": 3371, "##nt": 3372, "believed": 3373, "sorry": 3374, "complex": 3375, "beautiful": 3376, "victory": 3377, "associated": 3378, "temple": 3379, "1968": 3380, "1973": 3381, "chance": 3382, "perhaps": 3383, "metal": 3384, "##son": 3385, "1945": 3386, "bishop": 3387, "##et": 3388, "lee": 3389, "launched": 3390, "particularly": 3391, "tree": 3392, "le": 3393, "retired": 3394, "subject": 3395, "prize": 3396, "contains": 3397, "yeah": 3398, "theory": 3399, "empire": 3400, "##ce": 3401, "suddenly": 3402, "waiting": 3403, "trust": 3404, "recording": 3405, "##to": 3406, "happy": 3407, "terms": 3408, "camp": 3409, "champion": 3410, "1971": 3411, "religious": 3412, "pass": 3413, "zealand": 3414, "names": 3415, "2nd": 3416, "port": 3417, "ancient": 3418, "tom": 3419, "corner": 3420, "represented": 3421, "watch": 3422, "legal": 3423, "anti": 3424, "justice": 3425, "cause": 3426, "watched": 3427, "brothers": 3428, "45": 3429, "material": 3430, "changes": 3431, "simply": 3432, "response": 3433, "louis": 3434, "fast": 3435, "##ting": 3436, "answer": 3437, "60": 3438, "historical": 3439, "1969": 3440, "stories": 3441, "straight": 3442, "create": 3443, "feature": 3444, "increased": 3445, "rate": 3446, "administration": 3447, "virginia": 3448, "el": 3449, "activities": 3450, "cultural": 3451, "overall": 3452, "winner": 3453, "programs": 3454, "basketball": 3455, "legs": 3456, "guard": 3457, "beyond": 3458, "cast": 3459, "doctor": 3460, "mm": 3461, "flight": 3462, "results": 3463, "remains": 3464, "cost": 3465, "effect": 3466, "winter": 3467, "##ble": 3468, "larger": 3469, "islands": 3470, "problems": 3471, "chairman": 3472, "grew": 3473, "commander": 3474, "isn": 3475, "1967": 3476, "pay": 3477, "failed": 3478, "selected": 3479, "hurt": 3480, "fort": 3481, "box": 3482, "regiment": 3483, "majority": 3484, "journal": 3485, "35": 3486, "edward": 3487, "plans": 3488, "##ke": 3489, "##ni": 3490, "shown": 3491, "pretty": 3492, "irish": 3493, "characters": 3494, "directly": 3495, "scene": 3496, "likely": 3497, "operated": 3498, "allow": 3499, "spring": 3500, "##j": 3501, "junior": 3502, "matches": 3503, "looks": 3504, "mike": 3505, "houses": 3506, "fellow": 3507, "##tion": 3508, "beach": 3509, "marriage": 3510, "##ham": 3511, "##ive": 3512, "rules": 3513, "oil": 3514, "65": 3515, "florida": 3516, "expected": 3517, "nearby": 3518, "congress": 3519, "sam": 3520, "peace": 3521, "recent": 3522, "iii": 3523, "wait": 3524, "subsequently": 3525, "cell": 3526, "##do": 3527, "variety": 3528, "serving": 3529, "agreed": 3530, "please": 3531, "poor": 3532, "joe": 3533, "pacific": 3534, "attempt": 3535, "wood": 3536, "democratic": 3537, "piece": 3538, "prime": 3539, "##ca": 3540, "rural": 3541, "mile": 3542, "touch": 3543, "appears": 3544, "township": 3545, "1964": 3546, "1966": 3547, "soldiers": 3548, "##men": 3549, "##ized": 3550, "1965": 3551, "pennsylvania": 3552, "closer": 3553, "fighting": 3554, "claimed": 3555, "score": 3556, "jones": 3557, "physical": 3558, "editor": 3559, "##ous": 3560, "filled": 3561, "genus": 3562, "specific": 3563, "sitting": 3564, "super": 3565, "mom": 3566, "##va": 3567, "therefore": 3568, "supported": 3569, "status": 3570, "fear": 3571, "cases": 3572, "store": 3573, "meaning": 3574, "wales": 3575, "minor": 3576, "spain": 3577, "tower": 3578, "focus": 3579, "vice": 3580, "frank": 3581, "follow": 3582, "parish": 3583, "separate": 3584, "golden": 3585, "horse": 3586, "fifth": 3587, "remaining": 3588, "branch": 3589, "32": 3590, "presented": 3591, "stared": 3592, "##id": 3593, "uses": 3594, "secret": 3595, "forms": 3596, "##co": 3597, "baseball": 3598, "exactly": 3599, "##ck": 3600, "choice": 3601, "note": 3602, "discovered": 3603, "travel": 3604, "composed": 3605, "truth": 3606, "russia": 3607, "ball": 3608, "color": 3609, "kiss": 3610, "dad": 3611, "wind": 3612, "continue": 3613, "ring": 3614, "referred": 3615, "numbers": 3616, "digital": 3617, "greater": 3618, "##ns": 3619, "metres": 3620, "slightly": 3621, "direct": 3622, "increase": 3623, "1960": 3624, "responsible": 3625, "crew": 3626, "rule": 3627, "trees": 3628, "troops": 3629, "##no": 3630, "broke": 3631, "goes": 3632, "individuals": 3633, "hundred": 3634, "weight": 3635, "creek": 3636, "sleep": 3637, "memory": 3638, "defense": 3639, "provides": 3640, "ordered": 3641, "code": 3642, "value": 3643, "jewish": 3644, "windows": 3645, "1944": 3646, "safe": 3647, "judge": 3648, "whatever": 3649, "corps": 3650, "realized": 3651, "growing": 3652, "pre": 3653, "##ga": 3654, "cities": 3655, "alexander": 3656, "gaze": 3657, "lies": 3658, "spread": 3659, "scott": 3660, "letter": 3661, "showed": 3662, "situation": 3663, "mayor": 3664, "transport": 3665, "watching": 3666, "workers": 3667, "extended": 3668, "##li": 3669, "expression": 3670, "normal": 3671, "##ment": 3672, "chart": 3673, "multiple": 3674, "border": 3675, "##ba": 3676, "host": 3677, "##ner": 3678, "daily": 3679, "mrs": 3680, "walls": 3681, "piano": 3682, "##ko": 3683, "heat": 3684, "cannot": 3685, "##ate": 3686, "earned": 3687, "products": 3688, "drama": 3689, "era": 3690, "authority": 3691, "seasons": 3692, "join": 3693, "grade": 3694, "##io": 3695, "sign": 3696, "difficult": 3697, "machine": 3698, "1963": 3699, "territory": 3700, "mainly": 3701, "##wood": 3702, "stations": 3703, "squadron": 3704, "1962": 3705, "stepped": 3706, "iron": 3707, "19th": 3708, "##led": 3709, "serve": 3710, "appear": 3711, "sky": 3712, "speak": 3713, "broken": 3714, "charge": 3715, "knowledge": 3716, "kilometres": 3717, "removed": 3718, "ships": 3719, "article": 3720, "campus": 3721, "simple": 3722, "##ty": 3723, "pushed": 3724, "britain": 3725, "##ve": 3726, "leaves": 3727, "recently": 3728, "cd": 3729, "soft": 3730, "boston": 3731, "latter": 3732, "easy": 3733, "acquired": 3734, "poland": 3735, "##sa": 3736, "quality": 3737, "officers": 3738, "presence": 3739, "planned": 3740, "nations": 3741, "mass": 3742, "broadcast": 3743, "jean": 3744, "share": 3745, "image": 3746, "influence": 3747, "wild": 3748, "offer": 3749, "emperor": 3750, "electric": 3751, "reading": 3752, "headed": 3753, "ability": 3754, "promoted": 3755, "yellow": 3756, "ministry": 3757, "1942": 3758, "throat": 3759, "smaller": 3760, "politician": 3761, "##by": 3762, "latin": 3763, "spoke": 3764, "cars": 3765, "williams": 3766, "males": 3767, "lack": 3768, "pop": 3769, "80": 3770, "##ier": 3771, "acting": 3772, "seeing": 3773, "consists": 3774, "##ti": 3775, "estate": 3776, "1961": 3777, "pressure": 3778, "johnson": 3779, "newspaper": 3780, "jr": 3781, "chris": 3782, "olympics": 3783, "online": 3784, "conditions": 3785, "beat": 3786, "elements": 3787, "walking": 3788, "vote": 3789, "##field": 3790, "needs": 3791, "carolina": 3792, "text": 3793, "featuring": 3794, "global": 3795, "block": 3796, "shirt": 3797, "levels": 3798, "francisco": 3799, "purpose": 3800, "females": 3801, "et": 3802, "dutch": 3803, "duke": 3804, "ahead": 3805, "gas": 3806, "twice": 3807, "safety": 3808, "serious": 3809, "turning": 3810, "highly": 3811, "lieutenant": 3812, "firm": 3813, "maria": 3814, "amount": 3815, "mixed": 3816, "daniel": 3817, "proposed": 3818, "perfect": 3819, "agreement": 3820, "affairs": 3821, "3rd": 3822, "seconds": 3823, "contemporary": 3824, "paid": 3825, "1943": 3826, "prison": 3827, "save": 3828, "kitchen": 3829, "label": 3830, "administrative": 3831, "intended": 3832, "constructed": 3833, "academic": 3834, "nice": 3835, "teacher": 3836, "races": 3837, "1956": 3838, "formerly": 3839, "corporation": 3840, "ben": 3841, "nation": 3842, "issued": 3843, "shut": 3844, "1958": 3845, "drums": 3846, "housing": 3847, "victoria": 3848, "seems": 3849, "opera": 3850, "1959": 3851, "graduated": 3852, "function": 3853, "von": 3854, "mentioned": 3855, "picked": 3856, "build": 3857, "recognized": 3858, "shortly": 3859, "protection": 3860, "picture": 3861, "notable": 3862, "exchange": 3863, "elections": 3864, "1980s": 3865, "loved": 3866, "percent": 3867, "racing": 3868, "fish": 3869, "elizabeth": 3870, "garden": 3871, "volume": 3872, "hockey": 3873, "1941": 3874, "beside": 3875, "settled": 3876, "##ford": 3877, "1940": 3878, "competed": 3879, "replied": 3880, "drew": 3881, "1948": 3882, "actress": 3883, "marine": 3884, "scotland": 3885, "steel": 3886, "glanced": 3887, "farm": 3888, "steve": 3889, "1957": 3890, "risk": 3891, "tonight": 3892, "positive": 3893, "magic": 3894, "singles": 3895, "effects": 3896, "gray": 3897, "screen": 3898, "dog": 3899, "##ja": 3900, "residents": 3901, "bus": 3902, "sides": 3903, "none": 3904, "secondary": 3905, "literature": 3906, "polish": 3907, "destroyed": 3908, "flying": 3909, "founder": 3910, "households": 3911, "1939": 3912, "lay": 3913, "reserve": 3914, "usa": 3915, "gallery": 3916, "##ler": 3917, "1946": 3918, "industrial": 3919, "younger": 3920, "approach": 3921, "appearances": 3922, "urban": 3923, "ones": 3924, "1950": 3925, "finish": 3926, "avenue": 3927, "powerful": 3928, "fully": 3929, "growth": 3930, "page": 3931, "honor": 3932, "jersey": 3933, "projects": 3934, "advanced": 3935, "revealed": 3936, "basic": 3937, "90": 3938, "infantry": 3939, "pair": 3940, "equipment": 3941, "visit": 3942, "33": 3943, "evening": 3944, "search": 3945, "grant": 3946, "effort": 3947, "solo": 3948, "treatment": 3949, "buried": 3950, "republican": 3951, "primarily": 3952, "bottom": 3953, "owner": 3954, "1970s": 3955, "israel": 3956, "gives": 3957, "jim": 3958, "dream": 3959, "bob": 3960, "remain": 3961, "spot": 3962, "70": 3963, "notes": 3964, "produce": 3965, "champions": 3966, "contact": 3967, "ed": 3968, "soul": 3969, "accepted": 3970, "ways": 3971, "del": 3972, "##ally": 3973, "losing": 3974, "split": 3975, "price": 3976, "capacity": 3977, "basis": 3978, "trial": 3979, "questions": 3980, "##ina": 3981, "1955": 3982, "20th": 3983, "guess": 3984, "officially": 3985, "memorial": 3986, "naval": 3987, "initial": 3988, "##ization": 3989, "whispered": 3990, "median": 3991, "engineer": 3992, "##ful": 3993, "sydney": 3994, "##go": 3995, "columbia": 3996, "strength": 3997, "300": 3998, "1952": 3999, "tears": 4000, "senate": 4001, "00": 4002, "card": 4003, "asian": 4004, "agent": 4005, "1947": 4006, "software": 4007, "44": 4008, "draw": 4009, "warm": 4010, "supposed": 4011, "com": 4012, "pro": 4013, "##il": 4014, "transferred": 4015, "leaned": 4016, "##at": 4017, "candidate": 4018, "escape": 4019, "mountains": 4020, "asia": 4021, "potential": 4022, "activity": 4023, "entertainment": 4024, "seem": 4025, "traffic": 4026, "jackson": 4027, "murder": 4028, "36": 4029, "slow": 4030, "product": 4031, "orchestra": 4032, "haven": 4033, "agency": 4034, "bbc": 4035, "taught": 4036, "website": 4037, "comedy": 4038, "unable": 4039, "storm": 4040, "planning": 4041, "albums": 4042, "rugby": 4043, "environment": 4044, "scientific": 4045, "grabbed": 4046, "protect": 4047, "##hi": 4048, "boat": 4049, "typically": 4050, "1954": 4051, "1953": 4052, "damage": 4053, "principal": 4054, "divided": 4055, "dedicated": 4056, "mount": 4057, "ohio": 4058, "##berg": 4059, "pick": 4060, "fought": 4061, "driver": 4062, "##der": 4063, "empty": 4064, "shoulders": 4065, "sort": 4066, "thank": 4067, "berlin": 4068, "prominent": 4069, "account": 4070, "freedom": 4071, "necessary": 4072, "efforts": 4073, "alex": 4074, "headquarters": 4075, "follows": 4076, "alongside": 4077, "des": 4078, "simon": 4079, "andrew": 4080, "suggested": 4081, "operating": 4082, "learning": 4083, "steps": 4084, "1949": 4085, "sweet": 4086, "technical": 4087, "begin": 4088, "easily": 4089, "34": 4090, "teeth": 4091, "speaking": 4092, "settlement": 4093, "scale": 4094, "##sh": 4095, "renamed": 4096, "ray": 4097, "max": 4098, "enemy": 4099, "semi": 4100, "joint": 4101, "compared": 4102, "##rd": 4103, "scottish": 4104, "leadership": 4105, "analysis": 4106, "offers": 4107, "georgia": 4108, "pieces": 4109, "captured": 4110, "animal": 4111, "deputy": 4112, "guest": 4113, "organized": 4114, "##lin": 4115, "tony": 4116, "combined": 4117, "method": 4118, "challenge": 4119, "1960s": 4120, "huge": 4121, "wants": 4122, "battalion": 4123, "sons": 4124, "rise": 4125, "crime": 4126, "types": 4127, "facilities": 4128, "telling": 4129, "path": 4130, "1951": 4131, "platform": 4132, "sit": 4133, "1990s": 4134, "##lo": 4135, "tells": 4136, "assigned": 4137, "rich": 4138, "pull": 4139, "##ot": 4140, "commonly": 4141, "alive": 4142, "##za": 4143, "letters": 4144, "concept": 4145, "conducted": 4146, "wearing": 4147, "happen": 4148, "bought": 4149, "becomes": 4150, "holy": 4151, "gets": 4152, "ocean": 4153, "defeat": 4154, "languages": 4155, "purchased": 4156, "coffee": 4157, "occurred": 4158, "titled": 4159, "##q": 4160, "declared": 4161, "applied": 4162, "sciences": 4163, "concert": 4164, "sounds": 4165, "jazz": 4166, "brain": 4167, "##me": 4168, "painting": 4169, "fleet": 4170, "tax": 4171, "nick": 4172, "##ius": 4173, "michigan": 4174, "count": 4175, "animals": 4176, "leaders": 4177, "episodes": 4178, "##line": 4179, "content": 4180, "##den": 4181, "birth": 4182, "##it": 4183, "clubs": 4184, "64": 4185, "palace": 4186, "critical": 4187, "refused": 4188, "fair": 4189, "leg": 4190, "laughed": 4191, "returning": 4192, "surrounding": 4193, "participated": 4194, "formation": 4195, "lifted": 4196, "pointed": 4197, "connected": 4198, "rome": 4199, "medicine": 4200, "laid": 4201, "taylor": 4202, "santa": 4203, "powers": 4204, "adam": 4205, "tall": 4206, "shared": 4207, "focused": 4208, "knowing": 4209, "yards": 4210, "entrance": 4211, "falls": 4212, "##wa": 4213, "calling": 4214, "##ad": 4215, "sources": 4216, "chosen": 4217, "beneath": 4218, "resources": 4219, "yard": 4220, "##ite": 4221, "nominated": 4222, "silence": 4223, "zone": 4224, "defined": 4225, "##que": 4226, "gained": 4227, "thirty": 4228, "38": 4229, "bodies": 4230, "moon": 4231, "##ard": 4232, "adopted": 4233, "christmas": 4234, "widely": 4235, "register": 4236, "apart": 4237, "iran": 4238, "premier": 4239, "serves": 4240, "du": 4241, "unknown": 4242, "parties": 4243, "##les": 4244, "generation": 4245, "##ff": 4246, "continues": 4247, "quick": 4248, "fields": 4249, "brigade": 4250, "quiet": 4251, "teaching": 4252, "clothes": 4253, "impact": 4254, "weapons": 4255, "partner": 4256, "flat": 4257, "theater": 4258, "supreme": 4259, "1938": 4260, "37": 4261, "relations": 4262, "##tor": 4263, "plants": 4264, "suffered": 4265, "1936": 4266, "wilson": 4267, "kids": 4268, "begins": 4269, "##age": 4270, "1918": 4271, "seats": 4272, "armed": 4273, "internet": 4274, "models": 4275, "worth": 4276, "laws": 4277, "400": 4278, "communities": 4279, "classes": 4280, "background": 4281, "knows": 4282, "thanks": 4283, "quarter": 4284, "reaching": 4285, "humans": 4286, "carry": 4287, "killing": 4288, "format": 4289, "kong": 4290, "hong": 4291, "setting": 4292, "75": 4293, "architecture": 4294, "disease": 4295, "railroad": 4296, "inc": 4297, "possibly": 4298, "wish": 4299, "arthur": 4300, "thoughts": 4301, "harry": 4302, "doors": 4303, "density": 4304, "##di": 4305, "crowd": 4306, "illinois": 4307, "stomach": 4308, "tone": 4309, "unique": 4310, "reports": 4311, "anyway": 4312, "##ir": 4313, "liberal": 4314, "der": 4315, "vehicle": 4316, "thick": 4317, "dry": 4318, "drug": 4319, "faced": 4320, "largely": 4321, "facility": 4322, "theme": 4323, "holds": 4324, "creation": 4325, "strange": 4326, "colonel": 4327, "##mi": 4328, "revolution": 4329, "bell": 4330, "politics": 4331, "turns": 4332, "silent": 4333, "rail": 4334, "relief": 4335, "independence": 4336, "combat": 4337, "shape": 4338, "write": 4339, "determined": 4340, "sales": 4341, "learned": 4342, "4th": 4343, "finger": 4344, "oxford": 4345, "providing": 4346, "1937": 4347, "heritage": 4348, "fiction": 4349, "situated": 4350, "designated": 4351, "allowing": 4352, "distribution": 4353, "hosted": 4354, "##est": 4355, "sight": 4356, "interview": 4357, "estimated": 4358, "reduced": 4359, "##ria": 4360, "toronto": 4361, "footballer": 4362, "keeping": 4363, "guys": 4364, "damn": 4365, "claim": 4366, "motion": 4367, "sport": 4368, "sixth": 4369, "stayed": 4370, "##ze": 4371, "en": 4372, "rear": 4373, "receive": 4374, "handed": 4375, "twelve": 4376, "dress": 4377, "audience": 4378, "granted": 4379, "brazil": 4380, "##well": 4381, "spirit": 4382, "##ated": 4383, "noticed": 4384, "etc": 4385, "olympic": 4386, "representative": 4387, "eric": 4388, "tight": 4389, "trouble": 4390, "reviews": 4391, "drink": 4392, "vampire": 4393, "missing": 4394, "roles": 4395, "ranked": 4396, "newly": 4397, "household": 4398, "finals": 4399, "wave": 4400, "critics": 4401, "##ee": 4402, "phase": 4403, "massachusetts": 4404, "pilot": 4405, "unlike": 4406, "philadelphia": 4407, "bright": 4408, "guns": 4409, "crown": 4410, "organizations": 4411, "roof": 4412, "42": 4413, "respectively": 4414, "clearly": 4415, "tongue": 4416, "marked": 4417, "circle": 4418, "fox": 4419, "korea": 4420, "bronze": 4421, "brian": 4422, "expanded": 4423, "sexual": 4424, "supply": 4425, "yourself": 4426, "inspired": 4427, "labour": 4428, "fc": 4429, "##ah": 4430, "reference": 4431, "vision": 4432, "draft": 4433, "connection": 4434, "brand": 4435, "reasons": 4436, "1935": 4437, "classic": 4438, "driving": 4439, "trip": 4440, "jesus": 4441, "cells": 4442, "entry": 4443, "1920": 4444, "neither": 4445, "trail": 4446, "claims": 4447, "atlantic": 4448, "orders": 4449, "labor": 4450, "nose": 4451, "afraid": 4452, "identified": 4453, "intelligence": 4454, "calls": 4455, "cancer": 4456, "attacked": 4457, "passing": 4458, "stephen": 4459, "positions": 4460, "imperial": 4461, "grey": 4462, "jason": 4463, "39": 4464, "sunday": 4465, "48": 4466, "swedish": 4467, "avoid": 4468, "extra": 4469, "uncle": 4470, "message": 4471, "covers": 4472, "allows": 4473, "surprise": 4474, "materials": 4475, "fame": 4476, "hunter": 4477, "##ji": 4478, "1930": 4479, "citizens": 4480, "figures": 4481, "davis": 4482, "environmental": 4483, "confirmed": 4484, "shit": 4485, "titles": 4486, "di": 4487, "performing": 4488, "difference": 4489, "acts": 4490, "attacks": 4491, "##ov": 4492, "existing": 4493, "votes": 4494, "opportunity": 4495, "nor": 4496, "shop": 4497, "entirely": 4498, "trains": 4499, "opposite": 4500, "pakistan": 4501, "##pa": 4502, "develop": 4503, "resulted": 4504, "representatives": 4505, "actions": 4506, "reality": 4507, "pressed": 4508, "##ish": 4509, "barely": 4510, "wine": 4511, "conversation": 4512, "faculty": 4513, "northwest": 4514, "ends": 4515, "documentary": 4516, "nuclear": 4517, "stock": 4518, "grace": 4519, "sets": 4520, "eat": 4521, "alternative": 4522, "##ps": 4523, "bag": 4524, "resulting": 4525, "creating": 4526, "surprised": 4527, "cemetery": 4528, "1919": 4529, "drop": 4530, "finding": 4531, "sarah": 4532, "cricket": 4533, "streets": 4534, "tradition": 4535, "ride": 4536, "1933": 4537, "exhibition": 4538, "target": 4539, "ear": 4540, "explained": 4541, "rain": 4542, "composer": 4543, "injury": 4544, "apartment": 4545, "municipal": 4546, "educational": 4547, "occupied": 4548, "netherlands": 4549, "clean": 4550, "billion": 4551, "constitution": 4552, "learn": 4553, "1914": 4554, "maximum": 4555, "classical": 4556, "francis": 4557, "lose": 4558, "opposition": 4559, "jose": 4560, "ontario": 4561, "bear": 4562, "core": 4563, "hills": 4564, "rolled": 4565, "ending": 4566, "drawn": 4567, "permanent": 4568, "fun": 4569, "##tes": 4570, "##lla": 4571, "lewis": 4572, "sites": 4573, "chamber": 4574, "ryan": 4575, "##way": 4576, "scoring": 4577, "height": 4578, "1934": 4579, "##house": 4580, "lyrics": 4581, "staring": 4582, "55": 4583, "officials": 4584, "1917": 4585, "snow": 4586, "oldest": 4587, "##tic": 4588, "orange": 4589, "##ger": 4590, "qualified": 4591, "interior": 4592, "apparently": 4593, "succeeded": 4594, "thousand": 4595, "dinner": 4596, "lights": 4597, "existence": 4598, "fans": 4599, "heavily": 4600, "41": 4601, "greatest": 4602, "conservative": 4603, "send": 4604, "bowl": 4605, "plus": 4606, "enter": 4607, "catch": 4608, "##un": 4609, "economy": 4610, "duty": 4611, "1929": 4612, "speech": 4613, "authorities": 4614, "princess": 4615, "performances": 4616, "versions": 4617, "shall": 4618, "graduate": 4619, "pictures": 4620, "effective": 4621, "remembered": 4622, "poetry": 4623, "desk": 4624, "crossed": 4625, "starring": 4626, "starts": 4627, "passenger": 4628, "sharp": 4629, "##ant": 4630, "acres": 4631, "ass": 4632, "weather": 4633, "falling": 4634, "rank": 4635, "fund": 4636, "supporting": 4637, "check": 4638, "adult": 4639, "publishing": 4640, "heads": 4641, "cm": 4642, "southeast": 4643, "lane": 4644, "##burg": 4645, "application": 4646, "bc": 4647, "##ura": 4648, "les": 4649, "condition": 4650, "transfer": 4651, "prevent": 4652, "display": 4653, "ex": 4654, "regions": 4655, "earl": 4656, "federation": 4657, "cool": 4658, "relatively": 4659, "answered": 4660, "besides": 4661, "1928": 4662, "obtained": 4663, "portion": 4664, "##town": 4665, "mix": 4666, "##ding": 4667, "reaction": 4668, "liked": 4669, "dean": 4670, "express": 4671, "peak": 4672, "1932": 4673, "##tte": 4674, "counter": 4675, "religion": 4676, "chain": 4677, "rare": 4678, "miller": 4679, "convention": 4680, "aid": 4681, "lie": 4682, "vehicles": 4683, "mobile": 4684, "perform": 4685, "squad": 4686, "wonder": 4687, "lying": 4688, "crazy": 4689, "sword": 4690, "##ping": 4691, "attempted": 4692, "centuries": 4693, "weren": 4694, "philosophy": 4695, "category": 4696, "##ize": 4697, "anna": 4698, "interested": 4699, "47": 4700, "sweden": 4701, "wolf": 4702, "frequently": 4703, "abandoned": 4704, "kg": 4705, "literary": 4706, "alliance": 4707, "task": 4708, "entitled": 4709, "##ay": 4710, "threw": 4711, "promotion": 4712, "factory": 4713, "tiny": 4714, "soccer": 4715, "visited": 4716, "matt": 4717, "fm": 4718, "achieved": 4719, "52": 4720, "defence": 4721, "internal": 4722, "persian": 4723, "43": 4724, "methods": 4725, "##ging": 4726, "arrested": 4727, "otherwise": 4728, "cambridge": 4729, "programming": 4730, "villages": 4731, "elementary": 4732, "districts": 4733, "rooms": 4734, "criminal": 4735, "conflict": 4736, "worry": 4737, "trained": 4738, "1931": 4739, "attempts": 4740, "waited": 4741, "signal": 4742, "bird": 4743, "truck": 4744, "subsequent": 4745, "programme": 4746, "##ol": 4747, "ad": 4748, "49": 4749, "communist": 4750, "details": 4751, "faith": 4752, "sector": 4753, "patrick": 4754, "carrying": 4755, "laugh": 4756, "##ss": 4757, "controlled": 4758, "korean": 4759, "showing": 4760, "origin": 4761, "fuel": 4762, "evil": 4763, "1927": 4764, "##ent": 4765, "brief": 4766, "identity": 4767, "darkness": 4768, "address": 4769, "pool": 4770, "missed": 4771, "publication": 4772, "web": 4773, "planet": 4774, "ian": 4775, "anne": 4776, "wings": 4777, "invited": 4778, "##tt": 4779, "briefly": 4780, "standards": 4781, "kissed": 4782, "##be": 4783, "ideas": 4784, "climate": 4785, "causing": 4786, "walter": 4787, "worse": 4788, "albert": 4789, "articles": 4790, "winners": 4791, "desire": 4792, "aged": 4793, "northeast": 4794, "dangerous": 4795, "gate": 4796, "doubt": 4797, "1922": 4798, "wooden": 4799, "multi": 4800, "##ky": 4801, "poet": 4802, "rising": 4803, "funding": 4804, "46": 4805, "communications": 4806, "communication": 4807, "violence": 4808, "copies": 4809, "prepared": 4810, "ford": 4811, "investigation": 4812, "skills": 4813, "1924": 4814, "pulling": 4815, "electronic": 4816, "##ak": 4817, "##ial": 4818, "##han": 4819, "containing": 4820, "ultimately": 4821, "offices": 4822, "singing": 4823, "understanding": 4824, "restaurant": 4825, "tomorrow": 4826, "fashion": 4827, "christ": 4828, "ward": 4829, "da": 4830, "pope": 4831, "stands": 4832, "5th": 4833, "flow": 4834, "studios": 4835, "aired": 4836, "commissioned": 4837, "contained": 4838, "exist": 4839, "fresh": 4840, "americans": 4841, "##per": 4842, "wrestling": 4843, "approved": 4844, "kid": 4845, "employed": 4846, "respect": 4847, "suit": 4848, "1925": 4849, "angel": 4850, "asking": 4851, "increasing": 4852, "frame": 4853, "angry": 4854, "selling": 4855, "1950s": 4856, "thin": 4857, "finds": 4858, "##nd": 4859, "temperature": 4860, "statement": 4861, "ali": 4862, "explain": 4863, "inhabitants": 4864, "towns": 4865, "extensive": 4866, "narrow": 4867, "51": 4868, "jane": 4869, "flowers": 4870, "images": 4871, "promise": 4872, "somewhere": 4873, "object": 4874, "fly": 4875, "closely": 4876, "##ls": 4877, "1912": 4878, "bureau": 4879, "cape": 4880, "1926": 4881, "weekly": 4882, "presidential": 4883, "legislative": 4884, "1921": 4885, "##ai": 4886, "##au": 4887, "launch": 4888, "founding": 4889, "##ny": 4890, "978": 4891, "##ring": 4892, "artillery": 4893, "strike": 4894, "un": 4895, "institutions": 4896, "roll": 4897, "writers": 4898, "landing": 4899, "chose": 4900, "kevin": 4901, "anymore": 4902, "pp": 4903, "##ut": 4904, "attorney": 4905, "fit": 4906, "dan": 4907, "billboard": 4908, "receiving": 4909, "agricultural": 4910, "breaking": 4911, "sought": 4912, "dave": 4913, "admitted": 4914, "lands": 4915, "mexican": 4916, "##bury": 4917, "charlie": 4918, "specifically": 4919, "hole": 4920, "iv": 4921, "howard": 4922, "credit": 4923, "moscow": 4924, "roads": 4925, "accident": 4926, "1923": 4927, "proved": 4928, "wear": 4929, "struck": 4930, "hey": 4931, "guards": 4932, "stuff": 4933, "slid": 4934, "expansion": 4935, "1915": 4936, "cat": 4937, "anthony": 4938, "##kin": 4939, "melbourne": 4940, "opposed": 4941, "sub": 4942, "southwest": 4943, "architect": 4944, "failure": 4945, "plane": 4946, "1916": 4947, "##ron": 4948, "map": 4949, "camera": 4950, "tank": 4951, "listen": 4952, "regarding": 4953, "wet": 4954, "introduction": 4955, "metropolitan": 4956, "link": 4957, "ep": 4958, "fighter": 4959, "inch": 4960, "grown": 4961, "gene": 4962, "anger": 4963, "fixed": 4964, "buy": 4965, "dvd": 4966, "khan": 4967, "domestic": 4968, "worldwide": 4969, "chapel": 4970, "mill": 4971, "functions": 4972, "examples": 4973, "##head": 4974, "developing": 4975, "1910": 4976, "turkey": 4977, "hits": 4978, "pocket": 4979, "antonio": 4980, "papers": 4981, "grow": 4982, "unless": 4983, "circuit": 4984, "18th": 4985, "concerned": 4986, "attached": 4987, "journalist": 4988, "selection": 4989, "journey": 4990, "converted": 4991, "provincial": 4992, "painted": 4993, "hearing": 4994, "aren": 4995, "bands": 4996, "negative": 4997, "aside": 4998, "wondered": 4999, "knight": 5000, "lap": 5001, "survey": 5002, "ma": 5003, "##ow": 5004, "noise": 5005, "billy": 5006, "##ium": 5007, "shooting": 5008, "guide": 5009, "bedroom": 5010, "priest": 5011, "resistance": 5012, "motor": 5013, "homes": 5014, "sounded": 5015, "giant": 5016, "##mer": 5017, "150": 5018, "scenes": 5019, "equal": 5020, "comic": 5021, "patients": 5022, "hidden": 5023, "solid": 5024, "actual": 5025, "bringing": 5026, "afternoon": 5027, "touched": 5028, "funds": 5029, "wedding": 5030, "consisted": 5031, "marie": 5032, "canal": 5033, "sr": 5034, "kim": 5035, "treaty": 5036, "turkish": 5037, "recognition": 5038, "residence": 5039, "cathedral": 5040, "broad": 5041, "knees": 5042, "incident": 5043, "shaped": 5044, "fired": 5045, "norwegian": 5046, "handle": 5047, "cheek": 5048, "contest": 5049, "represent": 5050, "##pe": 5051, "representing": 5052, "beauty": 5053, "##sen": 5054, "birds": 5055, "advantage": 5056, "emergency": 5057, "wrapped": 5058, "drawing": 5059, "notice": 5060, "pink": 5061, "broadcasting": 5062, "##ong": 5063, "somehow": 5064, "bachelor": 5065, "seventh": 5066, "collected": 5067, "registered": 5068, "establishment": 5069, "alan": 5070, "assumed": 5071, "chemical": 5072, "personnel": 5073, "roger": 5074, "retirement": 5075, "jeff": 5076, "portuguese": 5077, "wore": 5078, "tied": 5079, "device": 5080, "threat": 5081, "progress": 5082, "advance": 5083, "##ised": 5084, "banks": 5085, "hired": 5086, "manchester": 5087, "nfl": 5088, "teachers": 5089, "structures": 5090, "forever": 5091, "##bo": 5092, "tennis": 5093, "helping": 5094, "saturday": 5095, "sale": 5096, "applications": 5097, "junction": 5098, "hip": 5099, "incorporated": 5100, "neighborhood": 5101, "dressed": 5102, "ceremony": 5103, "##ds": 5104, "influenced": 5105, "hers": 5106, "visual": 5107, "stairs": 5108, "decades": 5109, "inner": 5110, "kansas": 5111, "hung": 5112, "hoped": 5113, "gain": 5114, "scheduled": 5115, "downtown": 5116, "engaged": 5117, "austria": 5118, "clock": 5119, "norway": 5120, "certainly": 5121, "pale": 5122, "protected": 5123, "1913": 5124, "victor": 5125, "employees": 5126, "plate": 5127, "putting": 5128, "surrounded": 5129, "##ists": 5130, "finishing": 5131, "blues": 5132, "tropical": 5133, "##ries": 5134, "minnesota": 5135, "consider": 5136, "philippines": 5137, "accept": 5138, "54": 5139, "retrieved": 5140, "1900": 5141, "concern": 5142, "anderson": 5143, "properties": 5144, "institution": 5145, "gordon": 5146, "successfully": 5147, "vietnam": 5148, "##dy": 5149, "backing": 5150, "outstanding": 5151, "muslim": 5152, "crossing": 5153, "folk": 5154, "producing": 5155, "usual": 5156, "demand": 5157, "occurs": 5158, "observed": 5159, "lawyer": 5160, "educated": 5161, "##ana": 5162, "kelly": 5163, "string": 5164, "pleasure": 5165, "budget": 5166, "items": 5167, "quietly": 5168, "colorado": 5169, "philip": 5170, "typical": 5171, "##worth": 5172, "derived": 5173, "600": 5174, "survived": 5175, "asks": 5176, "mental": 5177, "##ide": 5178, "56": 5179, "jake": 5180, "jews": 5181, "distinguished": 5182, "ltd": 5183, "1911": 5184, "sri": 5185, "extremely": 5186, "53": 5187, "athletic": 5188, "loud": 5189, "thousands": 5190, "worried": 5191, "shadow": 5192, "transportation": 5193, "horses": 5194, "weapon": 5195, "arena": 5196, "importance": 5197, "users": 5198, "tim": 5199, "objects": 5200, "contributed": 5201, "dragon": 5202, "douglas": 5203, "aware": 5204, "senator": 5205, "johnny": 5206, "jordan": 5207, "sisters": 5208, "engines": 5209, "flag": 5210, "investment": 5211, "samuel": 5212, "shock": 5213, "capable": 5214, "clark": 5215, "row": 5216, "wheel": 5217, "refers": 5218, "session": 5219, "familiar": 5220, "biggest": 5221, "wins": 5222, "hate": 5223, "maintained": 5224, "drove": 5225, "hamilton": 5226, "request": 5227, "expressed": 5228, "injured": 5229, "underground": 5230, "churches": 5231, "walker": 5232, "wars": 5233, "tunnel": 5234, "passes": 5235, "stupid": 5236, "agriculture": 5237, "softly": 5238, "cabinet": 5239, "regarded": 5240, "joining": 5241, "indiana": 5242, "##ea": 5243, "##ms": 5244, "push": 5245, "dates": 5246, "spend": 5247, "behavior": 5248, "woods": 5249, "protein": 5250, "gently": 5251, "chase": 5252, "morgan": 5253, "mention": 5254, "burning": 5255, "wake": 5256, "combination": 5257, "occur": 5258, "mirror": 5259, "leads": 5260, "jimmy": 5261, "indeed": 5262, "impossible": 5263, "singapore": 5264, "paintings": 5265, "covering": 5266, "##nes": 5267, "soldier": 5268, "locations": 5269, "attendance": 5270, "sell": 5271, "historian": 5272, "wisconsin": 5273, "invasion": 5274, "argued": 5275, "painter": 5276, "diego": 5277, "changing": 5278, "egypt": 5279, "##don": 5280, "experienced": 5281, "inches": 5282, "##ku": 5283, "missouri": 5284, "vol": 5285, "grounds": 5286, "spoken": 5287, "switzerland": 5288, "##gan": 5289, "reform": 5290, "rolling": 5291, "ha": 5292, "forget": 5293, "massive": 5294, "resigned": 5295, "burned": 5296, "allen": 5297, "tennessee": 5298, "locked": 5299, "values": 5300, "improved": 5301, "##mo": 5302, "wounded": 5303, "universe": 5304, "sick": 5305, "dating": 5306, "facing": 5307, "pack": 5308, "purchase": 5309, "user": 5310, "##pur": 5311, "moments": 5312, "##ul": 5313, "merged": 5314, "anniversary": 5315, "1908": 5316, "coal": 5317, "brick": 5318, "understood": 5319, "causes": 5320, "dynasty": 5321, "queensland": 5322, "establish": 5323, "stores": 5324, "crisis": 5325, "promote": 5326, "hoping": 5327, "views": 5328, "cards": 5329, "referee": 5330, "extension": 5331, "##si": 5332, "raise": 5333, "arizona": 5334, "improve": 5335, "colonial": 5336, "formal": 5337, "charged": 5338, "##rt": 5339, "palm": 5340, "lucky": 5341, "hide": 5342, "rescue": 5343, "faces": 5344, "95": 5345, "feelings": 5346, "candidates": 5347, "juan": 5348, "##ell": 5349, "goods": 5350, "6th": 5351, "courses": 5352, "weekend": 5353, "59": 5354, "luke": 5355, "cash": 5356, "fallen": 5357, "##om": 5358, "delivered": 5359, "affected": 5360, "installed": 5361, "carefully": 5362, "tries": 5363, "swiss": 5364, "hollywood": 5365, "costs": 5366, "lincoln": 5367, "responsibility": 5368, "##he": 5369, "shore": 5370, "file": 5371, "proper": 5372, "normally": 5373, "maryland": 5374, "assistance": 5375, "jump": 5376, "constant": 5377, "offering": 5378, "friendly": 5379, "waters": 5380, "persons": 5381, "realize": 5382, "contain": 5383, "trophy": 5384, "800": 5385, "partnership": 5386, "factor": 5387, "58": 5388, "musicians": 5389, "cry": 5390, "bound": 5391, "oregon": 5392, "indicated": 5393, "hero": 5394, "houston": 5395, "medium": 5396, "##ure": 5397, "consisting": 5398, "somewhat": 5399, "##ara": 5400, "57": 5401, "cycle": 5402, "##che": 5403, "beer": 5404, "moore": 5405, "frederick": 5406, "gotten": 5407, "eleven": 5408, "worst": 5409, "weak": 5410, "approached": 5411, "arranged": 5412, "chin": 5413, "loan": 5414, "universal": 5415, "bond": 5416, "fifteen": 5417, "pattern": 5418, "disappeared": 5419, "##ney": 5420, "translated": 5421, "##zed": 5422, "lip": 5423, "arab": 5424, "capture": 5425, "interests": 5426, "insurance": 5427, "##chi": 5428, "shifted": 5429, "cave": 5430, "prix": 5431, "warning": 5432, "sections": 5433, "courts": 5434, "coat": 5435, "plot": 5436, "smell": 5437, "feed": 5438, "golf": 5439, "favorite": 5440, "maintain": 5441, "knife": 5442, "vs": 5443, "voted": 5444, "degrees": 5445, "finance": 5446, "quebec": 5447, "opinion": 5448, "translation": 5449, "manner": 5450, "ruled": 5451, "operate": 5452, "productions": 5453, "choose": 5454, "musician": 5455, "discovery": 5456, "confused": 5457, "tired": 5458, "separated": 5459, "stream": 5460, "techniques": 5461, "committed": 5462, "attend": 5463, "ranking": 5464, "kings": 5465, "throw": 5466, "passengers": 5467, "measure": 5468, "horror": 5469, "fan": 5470, "mining": 5471, "sand": 5472, "danger": 5473, "salt": 5474, "calm": 5475, "decade": 5476, "dam": 5477, "require": 5478, "runner": 5479, "##ik": 5480, "rush": 5481, "associate": 5482, "greece": 5483, "##ker": 5484, "rivers": 5485, "consecutive": 5486, "matthew": 5487, "##ski": 5488, "sighed": 5489, "sq": 5490, "documents": 5491, "steam": 5492, "edited": 5493, "closing": 5494, "tie": 5495, "accused": 5496, "1905": 5497, "##ini": 5498, "islamic": 5499, "distributed": 5500, "directors": 5501, "organisation": 5502, "bruce": 5503, "7th": 5504, "breathing": 5505, "mad": 5506, "lit": 5507, "arrival": 5508, "concrete": 5509, "taste": 5510, "08": 5511, "composition": 5512, "shaking": 5513, "faster": 5514, "amateur": 5515, "adjacent": 5516, "stating": 5517, "1906": 5518, "twin": 5519, "flew": 5520, "##ran": 5521, "tokyo": 5522, "publications": 5523, "##tone": 5524, "obviously": 5525, "ridge": 5526, "storage": 5527, "1907": 5528, "carl": 5529, "pages": 5530, "concluded": 5531, "desert": 5532, "driven": 5533, "universities": 5534, "ages": 5535, "terminal": 5536, "sequence": 5537, "borough": 5538, "250": 5539, "constituency": 5540, "creative": 5541, "cousin": 5542, "economics": 5543, "dreams": 5544, "margaret": 5545, "notably": 5546, "reduce": 5547, "montreal": 5548, "mode": 5549, "17th": 5550, "ears": 5551, "saved": 5552, "jan": 5553, "vocal": 5554, "##ica": 5555, "1909": 5556, "andy": 5557, "##jo": 5558, "riding": 5559, "roughly": 5560, "threatened": 5561, "##ise": 5562, "meters": 5563, "meanwhile": 5564, "landed": 5565, "compete": 5566, "repeated": 5567, "grass": 5568, "czech": 5569, "regularly": 5570, "charges": 5571, "tea": 5572, "sudden": 5573, "appeal": 5574, "##ung": 5575, "solution": 5576, "describes": 5577, "pierre": 5578, "classification": 5579, "glad": 5580, "parking": 5581, "##ning": 5582, "belt": 5583, "physics": 5584, "99": 5585, "rachel": 5586, "add": 5587, "hungarian": 5588, "participate": 5589, "expedition": 5590, "damaged": 5591, "gift": 5592, "childhood": 5593, "85": 5594, "fifty": 5595, "##red": 5596, "mathematics": 5597, "jumped": 5598, "letting": 5599, "defensive": 5600, "mph": 5601, "##ux": 5602, "##gh": 5603, "testing": 5604, "##hip": 5605, "hundreds": 5606, "shoot": 5607, "owners": 5608, "matters": 5609, "smoke": 5610, "israeli": 5611, "kentucky": 5612, "dancing": 5613, "mounted": 5614, "grandfather": 5615, "emma": 5616, "designs": 5617, "profit": 5618, "argentina": 5619, "##gs": 5620, "truly": 5621, "li": 5622, "lawrence": 5623, "cole": 5624, "begun": 5625, "detroit": 5626, "willing": 5627, "branches": 5628, "smiling": 5629, "decide": 5630, "miami": 5631, "enjoyed": 5632, "recordings": 5633, "##dale": 5634, "poverty": 5635, "ethnic": 5636, "gay": 5637, "##bi": 5638, "gary": 5639, "arabic": 5640, "09": 5641, "accompanied": 5642, "##one": 5643, "##ons": 5644, "fishing": 5645, "determine": 5646, "residential": 5647, "acid": 5648, "##ary": 5649, "alice": 5650, "returns": 5651, "starred": 5652, "mail": 5653, "##ang": 5654, "jonathan": 5655, "strategy": 5656, "##ue": 5657, "net": 5658, "forty": 5659, "cook": 5660, "businesses": 5661, "equivalent": 5662, "commonwealth": 5663, "distinct": 5664, "ill": 5665, "##cy": 5666, "seriously": 5667, "##ors": 5668, "##ped": 5669, "shift": 5670, "harris": 5671, "replace": 5672, "rio": 5673, "imagine": 5674, "formula": 5675, "ensure": 5676, "##ber": 5677, "additionally": 5678, "scheme": 5679, "conservation": 5680, "occasionally": 5681, "purposes": 5682, "feels": 5683, "favor": 5684, "##and": 5685, "##ore": 5686, "1930s": 5687, "contrast": 5688, "hanging": 5689, "hunt": 5690, "movies": 5691, "1904": 5692, "instruments": 5693, "victims": 5694, "danish": 5695, "christopher": 5696, "busy": 5697, "demon": 5698, "sugar": 5699, "earliest": 5700, "colony": 5701, "studying": 5702, "balance": 5703, "duties": 5704, "##ks": 5705, "belgium": 5706, "slipped": 5707, "carter": 5708, "05": 5709, "visible": 5710, "stages": 5711, "iraq": 5712, "fifa": 5713, "##im": 5714, "commune": 5715, "forming": 5716, "zero": 5717, "07": 5718, "continuing": 5719, "talked": 5720, "counties": 5721, "legend": 5722, "bathroom": 5723, "option": 5724, "tail": 5725, "clay": 5726, "daughters": 5727, "afterwards": 5728, "severe": 5729, "jaw": 5730, "visitors": 5731, "##ded": 5732, "devices": 5733, "aviation": 5734, "russell": 5735, "kate": 5736, "##vi": 5737, "entering": 5738, "subjects": 5739, "##ino": 5740, "temporary": 5741, "swimming": 5742, "forth": 5743, "smooth": 5744, "ghost": 5745, "audio": 5746, "bush": 5747, "operates": 5748, "rocks": 5749, "movements": 5750, "signs": 5751, "eddie": 5752, "##tz": 5753, "ann": 5754, "voices": 5755, "honorary": 5756, "06": 5757, "memories": 5758, "dallas": 5759, "pure": 5760, "measures": 5761, "racial": 5762, "promised": 5763, "66": 5764, "harvard": 5765, "ceo": 5766, "16th": 5767, "parliamentary": 5768, "indicate": 5769, "benefit": 5770, "flesh": 5771, "dublin": 5772, "louisiana": 5773, "1902": 5774, "1901": 5775, "patient": 5776, "sleeping": 5777, "1903": 5778, "membership": 5779, "coastal": 5780, "medieval": 5781, "wanting": 5782, "element": 5783, "scholars": 5784, "rice": 5785, "62": 5786, "limit": 5787, "survive": 5788, "makeup": 5789, "rating": 5790, "definitely": 5791, "collaboration": 5792, "obvious": 5793, "##tan": 5794, "boss": 5795, "ms": 5796, "baron": 5797, "birthday": 5798, "linked": 5799, "soil": 5800, "diocese": 5801, "##lan": 5802, "ncaa": 5803, "##mann": 5804, "offensive": 5805, "shell": 5806, "shouldn": 5807, "waist": 5808, "##tus": 5809, "plain": 5810, "ross": 5811, "organ": 5812, "resolution": 5813, "manufacturing": 5814, "adding": 5815, "relative": 5816, "kennedy": 5817, "98": 5818, "whilst": 5819, "moth": 5820, "marketing": 5821, "gardens": 5822, "crash": 5823, "72": 5824, "heading": 5825, "partners": 5826, "credited": 5827, "carlos": 5828, "moves": 5829, "cable": 5830, "##zi": 5831, "marshall": 5832, "##out": 5833, "depending": 5834, "bottle": 5835, "represents": 5836, "rejected": 5837, "responded": 5838, "existed": 5839, "04": 5840, "jobs": 5841, "denmark": 5842, "lock": 5843, "##ating": 5844, "treated": 5845, "graham": 5846, "routes": 5847, "talent": 5848, "commissioner": 5849, "drugs": 5850, "secure": 5851, "tests": 5852, "reign": 5853, "restored": 5854, "photography": 5855, "##gi": 5856, "contributions": 5857, "oklahoma": 5858, "designer": 5859, "disc": 5860, "grin": 5861, "seattle": 5862, "robin": 5863, "paused": 5864, "atlanta": 5865, "unusual": 5866, "##gate": 5867, "praised": 5868, "las": 5869, "laughing": 5870, "satellite": 5871, "hungary": 5872, "visiting": 5873, "##sky": 5874, "interesting": 5875, "factors": 5876, "deck": 5877, "poems": 5878, "norman": 5879, "##water": 5880, "stuck": 5881, "speaker": 5882, "rifle": 5883, "domain": 5884, "premiered": 5885, "##her": 5886, "dc": 5887, "comics": 5888, "actors": 5889, "01": 5890, "reputation": 5891, "eliminated": 5892, "8th": 5893, "ceiling": 5894, "prisoners": 5895, "script": 5896, "##nce": 5897, "leather": 5898, "austin": 5899, "mississippi": 5900, "rapidly": 5901, "admiral": 5902, "parallel": 5903, "charlotte": 5904, "guilty": 5905, "tools": 5906, "gender": 5907, "divisions": 5908, "fruit": 5909, "##bs": 5910, "laboratory": 5911, "nelson": 5912, "fantasy": 5913, "marry": 5914, "rapid": 5915, "aunt": 5916, "tribe": 5917, "requirements": 5918, "aspects": 5919, "suicide": 5920, "amongst": 5921, "adams": 5922, "bone": 5923, "ukraine": 5924, "abc": 5925, "kick": 5926, "sees": 5927, "edinburgh": 5928, "clothing": 5929, "column": 5930, "rough": 5931, "gods": 5932, "hunting": 5933, "broadway": 5934, "gathered": 5935, "concerns": 5936, "##ek": 5937, "spending": 5938, "ty": 5939, "12th": 5940, "snapped": 5941, "requires": 5942, "solar": 5943, "bones": 5944, "cavalry": 5945, "##tta": 5946, "iowa": 5947, "drinking": 5948, "waste": 5949, "index": 5950, "franklin": 5951, "charity": 5952, "thompson": 5953, "stewart": 5954, "tip": 5955, "flash": 5956, "landscape": 5957, "friday": 5958, "enjoy": 5959, "singh": 5960, "poem": 5961, "listening": 5962, "##back": 5963, "eighth": 5964, "fred": 5965, "differences": 5966, "adapted": 5967, "bomb": 5968, "ukrainian": 5969, "surgery": 5970, "corporate": 5971, "masters": 5972, "anywhere": 5973, "##more": 5974, "waves": 5975, "odd": 5976, "sean": 5977, "portugal": 5978, "orleans": 5979, "dick": 5980, "debate": 5981, "kent": 5982, "eating": 5983, "puerto": 5984, "cleared": 5985, "96": 5986, "expect": 5987, "cinema": 5988, "97": 5989, "guitarist": 5990, "blocks": 5991, "electrical": 5992, "agree": 5993, "involving": 5994, "depth": 5995, "dying": 5996, "panel": 5997, "struggle": 5998, "##ged": 5999, "peninsula": 6000, "adults": 6001, "novels": 6002, "emerged": 6003, "vienna": 6004, "metro": 6005, "debuted": 6006, "shoes": 6007, "tamil": 6008, "songwriter": 6009, "meets": 6010, "prove": 6011, "beating": 6012, "instance": 6013, "heaven": 6014, "scared": 6015, "sending": 6016, "marks": 6017, "artistic": 6018, "passage": 6019, "superior": 6020, "03": 6021, "significantly": 6022, "shopping": 6023, "##tive": 6024, "retained": 6025, "##izing": 6026, "malaysia": 6027, "technique": 6028, "cheeks": 6029, "##ola": 6030, "warren": 6031, "maintenance": 6032, "destroy": 6033, "extreme": 6034, "allied": 6035, "120": 6036, "appearing": 6037, "##yn": 6038, "fill": 6039, "advice": 6040, "alabama": 6041, "qualifying": 6042, "policies": 6043, "cleveland": 6044, "hat": 6045, "battery": 6046, "smart": 6047, "authors": 6048, "10th": 6049, "soundtrack": 6050, "acted": 6051, "dated": 6052, "lb": 6053, "glance": 6054, "equipped": 6055, "coalition": 6056, "funny": 6057, "outer": 6058, "ambassador": 6059, "roy": 6060, "possibility": 6061, "couples": 6062, "campbell": 6063, "dna": 6064, "loose": 6065, "ethan": 6066, "supplies": 6067, "1898": 6068, "gonna": 6069, "88": 6070, "monster": 6071, "##res": 6072, "shake": 6073, "agents": 6074, "frequency": 6075, "springs": 6076, "dogs": 6077, "practices": 6078, "61": 6079, "gang": 6080, "plastic": 6081, "easier": 6082, "suggests": 6083, "gulf": 6084, "blade": 6085, "exposed": 6086, "colors": 6087, "industries": 6088, "markets": 6089, "pan": 6090, "nervous": 6091, "electoral": 6092, "charts": 6093, "legislation": 6094, "ownership": 6095, "##idae": 6096, "mac": 6097, "appointment": 6098, "shield": 6099, "copy": 6100, "assault": 6101, "socialist": 6102, "abbey": 6103, "monument": 6104, "license": 6105, "throne": 6106, "employment": 6107, "jay": 6108, "93": 6109, "replacement": 6110, "charter": 6111, "cloud": 6112, "powered": 6113, "suffering": 6114, "accounts": 6115, "oak": 6116, "connecticut": 6117, "strongly": 6118, "wright": 6119, "colour": 6120, "crystal": 6121, "13th": 6122, "context": 6123, "welsh": 6124, "networks": 6125, "voiced": 6126, "gabriel": 6127, "jerry": 6128, "##cing": 6129, "forehead": 6130, "mp": 6131, "##ens": 6132, "manage": 6133, "schedule": 6134, "totally": 6135, "remix": 6136, "##ii": 6137, "forests": 6138, "occupation": 6139, "print": 6140, "nicholas": 6141, "brazilian": 6142, "strategic": 6143, "vampires": 6144, "engineers": 6145, "76": 6146, "roots": 6147, "seek": 6148, "correct": 6149, "instrumental": 6150, "und": 6151, "alfred": 6152, "backed": 6153, "hop": 6154, "##des": 6155, "stanley": 6156, "robinson": 6157, "traveled": 6158, "wayne": 6159, "welcome": 6160, "austrian": 6161, "achieve": 6162, "67": 6163, "exit": 6164, "rates": 6165, "1899": 6166, "strip": 6167, "whereas": 6168, "##cs": 6169, "sing": 6170, "deeply": 6171, "adventure": 6172, "bobby": 6173, "rick": 6174, "jamie": 6175, "careful": 6176, "components": 6177, "cap": 6178, "useful": 6179, "personality": 6180, "knee": 6181, "##shi": 6182, "pushing": 6183, "hosts": 6184, "02": 6185, "protest": 6186, "ca": 6187, "ottoman": 6188, "symphony": 6189, "##sis": 6190, "63": 6191, "boundary": 6192, "1890": 6193, "processes": 6194, "considering": 6195, "considerable": 6196, "tons": 6197, "##work": 6198, "##ft": 6199, "##nia": 6200, "cooper": 6201, "trading": 6202, "dear": 6203, "conduct": 6204, "91": 6205, "illegal": 6206, "apple": 6207, "revolutionary": 6208, "holiday": 6209, "definition": 6210, "harder": 6211, "##van": 6212, "jacob": 6213, "circumstances": 6214, "destruction": 6215, "##lle": 6216, "popularity": 6217, "grip": 6218, "classified": 6219, "liverpool": 6220, "donald": 6221, "baltimore": 6222, "flows": 6223, "seeking": 6224, "honour": 6225, "approval": 6226, "92": 6227, "mechanical": 6228, "till": 6229, "happening": 6230, "statue": 6231, "critic": 6232, "increasingly": 6233, "immediate": 6234, "describe": 6235, "commerce": 6236, "stare": 6237, "##ster": 6238, "indonesia": 6239, "meat": 6240, "rounds": 6241, "boats": 6242, "baker": 6243, "orthodox": 6244, "depression": 6245, "formally": 6246, "worn": 6247, "naked": 6248, "claire": 6249, "muttered": 6250, "sentence": 6251, "11th": 6252, "emily": 6253, "document": 6254, "77": 6255, "criticism": 6256, "wished": 6257, "vessel": 6258, "spiritual": 6259, "bent": 6260, "virgin": 6261, "parker": 6262, "minimum": 6263, "murray": 6264, "lunch": 6265, "danny": 6266, "printed": 6267, "compilation": 6268, "keyboards": 6269, "false": 6270, "blow": 6271, "belonged": 6272, "68": 6273, "raising": 6274, "78": 6275, "cutting": 6276, "##board": 6277, "pittsburgh": 6278, "##up": 6279, "9th": 6280, "shadows": 6281, "81": 6282, "hated": 6283, "indigenous": 6284, "jon": 6285, "15th": 6286, "barry": 6287, "scholar": 6288, "ah": 6289, "##zer": 6290, "oliver": 6291, "##gy": 6292, "stick": 6293, "susan": 6294, "meetings": 6295, "attracted": 6296, "spell": 6297, "romantic": 6298, "##ver": 6299, "ye": 6300, "1895": 6301, "photo": 6302, "demanded": 6303, "customers": 6304, "##ac": 6305, "1896": 6306, "logan": 6307, "revival": 6308, "keys": 6309, "modified": 6310, "commanded": 6311, "jeans": 6312, "##ious": 6313, "upset": 6314, "raw": 6315, "phil": 6316, "detective": 6317, "hiding": 6318, "resident": 6319, "vincent": 6320, "##bly": 6321, "experiences": 6322, "diamond": 6323, "defeating": 6324, "coverage": 6325, "lucas": 6326, "external": 6327, "parks": 6328, "franchise": 6329, "helen": 6330, "bible": 6331, "successor": 6332, "percussion": 6333, "celebrated": 6334, "il": 6335, "lift": 6336, "profile": 6337, "clan": 6338, "romania": 6339, "##ied": 6340, "mills": 6341, "##su": 6342, "nobody": 6343, "achievement": 6344, "shrugged": 6345, "fault": 6346, "1897": 6347, "rhythm": 6348, "initiative": 6349, "breakfast": 6350, "carbon": 6351, "700": 6352, "69": 6353, "lasted": 6354, "violent": 6355, "74": 6356, "wound": 6357, "ken": 6358, "killer": 6359, "gradually": 6360, "filmed": 6361, "°c": 6362, "dollars": 6363, "processing": 6364, "94": 6365, "remove": 6366, "criticized": 6367, "guests": 6368, "sang": 6369, "chemistry": 6370, "##vin": 6371, "legislature": 6372, "disney": 6373, "##bridge": 6374, "uniform": 6375, "escaped": 6376, "integrated": 6377, "proposal": 6378, "purple": 6379, "denied": 6380, "liquid": 6381, "karl": 6382, "influential": 6383, "morris": 6384, "nights": 6385, "stones": 6386, "intense": 6387, "experimental": 6388, "twisted": 6389, "71": 6390, "84": 6391, "##ld": 6392, "pace": 6393, "nazi": 6394, "mitchell": 6395, "ny": 6396, "blind": 6397, "reporter": 6398, "newspapers": 6399, "14th": 6400, "centers": 6401, "burn": 6402, "basin": 6403, "forgotten": 6404, "surviving": 6405, "filed": 6406, "collections": 6407, "monastery": 6408, "losses": 6409, "manual": 6410, "couch": 6411, "description": 6412, "appropriate": 6413, "merely": 6414, "tag": 6415, "missions": 6416, "sebastian": 6417, "restoration": 6418, "replacing": 6419, "triple": 6420, "73": 6421, "elder": 6422, "julia": 6423, "warriors": 6424, "benjamin": 6425, "julian": 6426, "convinced": 6427, "stronger": 6428, "amazing": 6429, "declined": 6430, "versus": 6431, "merchant": 6432, "happens": 6433, "output": 6434, "finland": 6435, "bare": 6436, "barbara": 6437, "absence": 6438, "ignored": 6439, "dawn": 6440, "injuries": 6441, "##port": 6442, "producers": 6443, "##ram": 6444, "82": 6445, "luis": 6446, "##ities": 6447, "kw": 6448, "admit": 6449, "expensive": 6450, "electricity": 6451, "nba": 6452, "exception": 6453, "symbol": 6454, "##ving": 6455, "ladies": 6456, "shower": 6457, "sheriff": 6458, "characteristics": 6459, "##je": 6460, "aimed": 6461, "button": 6462, "ratio": 6463, "effectively": 6464, "summit": 6465, "angle": 6466, "jury": 6467, "bears": 6468, "foster": 6469, "vessels": 6470, "pants": 6471, "executed": 6472, "evans": 6473, "dozen": 6474, "advertising": 6475, "kicked": 6476, "patrol": 6477, "1889": 6478, "competitions": 6479, "lifetime": 6480, "principles": 6481, "athletics": 6482, "##logy": 6483, "birmingham": 6484, "sponsored": 6485, "89": 6486, "rob": 6487, "nomination": 6488, "1893": 6489, "acoustic": 6490, "##sm": 6491, "creature": 6492, "longest": 6493, "##tra": 6494, "credits": 6495, "harbor": 6496, "dust": 6497, "josh": 6498, "##so": 6499, "territories": 6500, "milk": 6501, "infrastructure": 6502, "completion": 6503, "thailand": 6504, "indians": 6505, "leon": 6506, "archbishop": 6507, "##sy": 6508, "assist": 6509, "pitch": 6510, "blake": 6511, "arrangement": 6512, "girlfriend": 6513, "serbian": 6514, "operational": 6515, "hence": 6516, "sad": 6517, "scent": 6518, "fur": 6519, "dj": 6520, "sessions": 6521, "hp": 6522, "refer": 6523, "rarely": 6524, "##ora": 6525, "exists": 6526, "1892": 6527, "##ten": 6528, "scientists": 6529, "dirty": 6530, "penalty": 6531, "burst": 6532, "portrait": 6533, "seed": 6534, "79": 6535, "pole": 6536, "limits": 6537, "rival": 6538, "1894": 6539, "stable": 6540, "alpha": 6541, "grave": 6542, "constitutional": 6543, "alcohol": 6544, "arrest": 6545, "flower": 6546, "mystery": 6547, "devil": 6548, "architectural": 6549, "relationships": 6550, "greatly": 6551, "habitat": 6552, "##istic": 6553, "larry": 6554, "progressive": 6555, "remote": 6556, "cotton": 6557, "##ics": 6558, "##ok": 6559, "preserved": 6560, "reaches": 6561, "##ming": 6562, "cited": 6563, "86": 6564, "vast": 6565, "scholarship": 6566, "decisions": 6567, "cbs": 6568, "joy": 6569, "teach": 6570, "1885": 6571, "editions": 6572, "knocked": 6573, "eve": 6574, "searching": 6575, "partly": 6576, "participation": 6577, "gap": 6578, "animated": 6579, "fate": 6580, "excellent": 6581, "##ett": 6582, "na": 6583, "87": 6584, "alternate": 6585, "saints": 6586, "youngest": 6587, "##ily": 6588, "climbed": 6589, "##ita": 6590, "##tors": 6591, "suggest": 6592, "##ct": 6593, "discussion": 6594, "staying": 6595, "choir": 6596, "lakes": 6597, "jacket": 6598, "revenue": 6599, "nevertheless": 6600, "peaked": 6601, "instrument": 6602, "wondering": 6603, "annually": 6604, "managing": 6605, "neil": 6606, "1891": 6607, "signing": 6608, "terry": 6609, "##ice": 6610, "apply": 6611, "clinical": 6612, "brooklyn": 6613, "aim": 6614, "catherine": 6615, "fuck": 6616, "farmers": 6617, "figured": 6618, "ninth": 6619, "pride": 6620, "hugh": 6621, "evolution": 6622, "ordinary": 6623, "involvement": 6624, "comfortable": 6625, "shouted": 6626, "tech": 6627, "encouraged": 6628, "taiwan": 6629, "representation": 6630, "sharing": 6631, "##lia": 6632, "##em": 6633, "panic": 6634, "exact": 6635, "cargo": 6636, "competing": 6637, "fat": 6638, "cried": 6639, "83": 6640, "1920s": 6641, "occasions": 6642, "pa": 6643, "cabin": 6644, "borders": 6645, "utah": 6646, "marcus": 6647, "##isation": 6648, "badly": 6649, "muscles": 6650, "##ance": 6651, "victorian": 6652, "transition": 6653, "warner": 6654, "bet": 6655, "permission": 6656, "##rin": 6657, "slave": 6658, "terrible": 6659, "similarly": 6660, "shares": 6661, "seth": 6662, "uefa": 6663, "possession": 6664, "medals": 6665, "benefits": 6666, "colleges": 6667, "lowered": 6668, "perfectly": 6669, "mall": 6670, "transit": 6671, "##ye": 6672, "##kar": 6673, "publisher": 6674, "##ened": 6675, "harrison": 6676, "deaths": 6677, "elevation": 6678, "##ae": 6679, "asleep": 6680, "machines": 6681, "sigh": 6682, "ash": 6683, "hardly": 6684, "argument": 6685, "occasion": 6686, "parent": 6687, "leo": 6688, "decline": 6689, "1888": 6690, "contribution": 6691, "##ua": 6692, "concentration": 6693, "1000": 6694, "opportunities": 6695, "hispanic": 6696, "guardian": 6697, "extent": 6698, "emotions": 6699, "hips": 6700, "mason": 6701, "volumes": 6702, "bloody": 6703, "controversy": 6704, "diameter": 6705, "steady": 6706, "mistake": 6707, "phoenix": 6708, "identify": 6709, "violin": 6710, "##sk": 6711, "departure": 6712, "richmond": 6713, "spin": 6714, "funeral": 6715, "enemies": 6716, "1864": 6717, "gear": 6718, "literally": 6719, "connor": 6720, "random": 6721, "sergeant": 6722, "grab": 6723, "confusion": 6724, "1865": 6725, "transmission": 6726, "informed": 6727, "op": 6728, "leaning": 6729, "sacred": 6730, "suspended": 6731, "thinks": 6732, "gates": 6733, "portland": 6734, "luck": 6735, "agencies": 6736, "yours": 6737, "hull": 6738, "expert": 6739, "muscle": 6740, "layer": 6741, "practical": 6742, "sculpture": 6743, "jerusalem": 6744, "latest": 6745, "lloyd": 6746, "statistics": 6747, "deeper": 6748, "recommended": 6749, "warrior": 6750, "arkansas": 6751, "mess": 6752, "supports": 6753, "greg": 6754, "eagle": 6755, "1880": 6756, "recovered": 6757, "rated": 6758, "concerts": 6759, "rushed": 6760, "##ano": 6761, "stops": 6762, "eggs": 6763, "files": 6764, "premiere": 6765, "keith": 6766, "##vo": 6767, "delhi": 6768, "turner": 6769, "pit": 6770, "affair": 6771, "belief": 6772, "paint": 6773, "##zing": 6774, "mate": 6775, "##ach": 6776, "##ev": 6777, "victim": 6778, "##ology": 6779, "withdrew": 6780, "bonus": 6781, "styles": 6782, "fled": 6783, "##ud": 6784, "glasgow": 6785, "technologies": 6786, "funded": 6787, "nbc": 6788, "adaptation": 6789, "##ata": 6790, "portrayed": 6791, "cooperation": 6792, "supporters": 6793, "judges": 6794, "bernard": 6795, "justin": 6796, "hallway": 6797, "ralph": 6798, "##ick": 6799, "graduating": 6800, "controversial": 6801, "distant": 6802, "continental": 6803, "spider": 6804, "bite": 6805, "##ho": 6806, "recognize": 6807, "intention": 6808, "mixing": 6809, "##ese": 6810, "egyptian": 6811, "bow": 6812, "tourism": 6813, "suppose": 6814, "claiming": 6815, "tiger": 6816, "dominated": 6817, "participants": 6818, "vi": 6819, "##ru": 6820, "nurse": 6821, "partially": 6822, "tape": 6823, "##rum": 6824, "psychology": 6825, "##rn": 6826, "essential": 6827, "touring": 6828, "duo": 6829, "voting": 6830, "civilian": 6831, "emotional": 6832, "channels": 6833, "##king": 6834, "apparent": 6835, "hebrew": 6836, "1887": 6837, "tommy": 6838, "carrier": 6839, "intersection": 6840, "beast": 6841, "hudson": 6842, "##gar": 6843, "##zo": 6844, "lab": 6845, "nova": 6846, "bench": 6847, "discuss": 6848, "costa": 6849, "##ered": 6850, "detailed": 6851, "behalf": 6852, "drivers": 6853, "unfortunately": 6854, "obtain": 6855, "##lis": 6856, "rocky": 6857, "##dae": 6858, "siege": 6859, "friendship": 6860, "honey": 6861, "##rian": 6862, "1861": 6863, "amy": 6864, "hang": 6865, "posted": 6866, "governments": 6867, "collins": 6868, "respond": 6869, "wildlife": 6870, "preferred": 6871, "operator": 6872, "##po": 6873, "laura": 6874, "pregnant": 6875, "videos": 6876, "dennis": 6877, "suspected": 6878, "boots": 6879, "instantly": 6880, "weird": 6881, "automatic": 6882, "businessman": 6883, "alleged": 6884, "placing": 6885, "throwing": 6886, "ph": 6887, "mood": 6888, "1862": 6889, "perry": 6890, "venue": 6891, "jet": 6892, "remainder": 6893, "##lli": 6894, "##ci": 6895, "passion": 6896, "biological": 6897, "boyfriend": 6898, "1863": 6899, "dirt": 6900, "buffalo": 6901, "ron": 6902, "segment": 6903, "fa": 6904, "abuse": 6905, "##era": 6906, "genre": 6907, "thrown": 6908, "stroke": 6909, "colored": 6910, "stress": 6911, "exercise": 6912, "displayed": 6913, "##gen": 6914, "struggled": 6915, "##tti": 6916, "abroad": 6917, "dramatic": 6918, "wonderful": 6919, "thereafter": 6920, "madrid": 6921, "component": 6922, "widespread": 6923, "##sed": 6924, "tale": 6925, "citizen": 6926, "todd": 6927, "monday": 6928, "1886": 6929, "vancouver": 6930, "overseas": 6931, "forcing": 6932, "crying": 6933, "descent": 6934, "##ris": 6935, "discussed": 6936, "substantial": 6937, "ranks": 6938, "regime": 6939, "1870": 6940, "provinces": 6941, "switch": 6942, "drum": 6943, "zane": 6944, "ted": 6945, "tribes": 6946, "proof": 6947, "lp": 6948, "cream": 6949, "researchers": 6950, "volunteer": 6951, "manor": 6952, "silk": 6953, "milan": 6954, "donated": 6955, "allies": 6956, "venture": 6957, "principle": 6958, "delivery": 6959, "enterprise": 6960, "##ves": 6961, "##ans": 6962, "bars": 6963, "traditionally": 6964, "witch": 6965, "reminded": 6966, "copper": 6967, "##uk": 6968, "pete": 6969, "inter": 6970, "links": 6971, "colin": 6972, "grinned": 6973, "elsewhere": 6974, "competitive": 6975, "frequent": 6976, "##oy": 6977, "scream": 6978, "##hu": 6979, "tension": 6980, "texts": 6981, "submarine": 6982, "finnish": 6983, "defending": 6984, "defend": 6985, "pat": 6986, "detail": 6987, "1884": 6988, "affiliated": 6989, "stuart": 6990, "themes": 6991, "villa": 6992, "periods": 6993, "tool": 6994, "belgian": 6995, "ruling": 6996, "crimes": 6997, "answers": 6998, "folded": 6999, "licensed": 7000, "resort": 7001, "demolished": 7002, "hans": 7003, "lucy": 7004, "1881": 7005, "lion": 7006, "traded": 7007, "photographs": 7008, "writes": 7009, "craig": 7010, "##fa": 7011, "trials": 7012, "generated": 7013, "beth": 7014, "noble": 7015, "debt": 7016, "percentage": 7017, "yorkshire": 7018, "erected": 7019, "ss": 7020, "viewed": 7021, "grades": 7022, "confidence": 7023, "ceased": 7024, "islam": 7025, "telephone": 7026, "retail": 7027, "##ible": 7028, "chile": 7029, "m²": 7030, "roberts": 7031, "sixteen": 7032, "##ich": 7033, "commented": 7034, "hampshire": 7035, "innocent": 7036, "dual": 7037, "pounds": 7038, "checked": 7039, "regulations": 7040, "afghanistan": 7041, "sung": 7042, "rico": 7043, "liberty": 7044, "assets": 7045, "bigger": 7046, "options": 7047, "angels": 7048, "relegated": 7049, "tribute": 7050, "wells": 7051, "attending": 7052, "leaf": 7053, "##yan": 7054, "butler": 7055, "romanian": 7056, "forum": 7057, "monthly": 7058, "lisa": 7059, "patterns": 7060, "gmina": 7061, "##tory": 7062, "madison": 7063, "hurricane": 7064, "rev": 7065, "##ians": 7066, "bristol": 7067, "##ula": 7068, "elite": 7069, "valuable": 7070, "disaster": 7071, "democracy": 7072, "awareness": 7073, "germans": 7074, "freyja": 7075, "##ins": 7076, "loop": 7077, "absolutely": 7078, "paying": 7079, "populations": 7080, "maine": 7081, "sole": 7082, "prayer": 7083, "spencer": 7084, "releases": 7085, "doorway": 7086, "bull": 7087, "##ani": 7088, "lover": 7089, "midnight": 7090, "conclusion": 7091, "##sson": 7092, "thirteen": 7093, "lily": 7094, "mediterranean": 7095, "##lt": 7096, "nhl": 7097, "proud": 7098, "sample": 7099, "##hill": 7100, "drummer": 7101, "guinea": 7102, "##ova": 7103, "murphy": 7104, "climb": 7105, "##ston": 7106, "instant": 7107, "attributed": 7108, "horn": 7109, "ain": 7110, "railways": 7111, "steven": 7112, "##ao": 7113, "autumn": 7114, "ferry": 7115, "opponent": 7116, "root": 7117, "traveling": 7118, "secured": 7119, "corridor": 7120, "stretched": 7121, "tales": 7122, "sheet": 7123, "trinity": 7124, "cattle": 7125, "helps": 7126, "indicates": 7127, "manhattan": 7128, "murdered": 7129, "fitted": 7130, "1882": 7131, "gentle": 7132, "grandmother": 7133, "mines": 7134, "shocked": 7135, "vegas": 7136, "produces": 7137, "##light": 7138, "caribbean": 7139, "##ou": 7140, "belong": 7141, "continuous": 7142, "desperate": 7143, "drunk": 7144, "historically": 7145, "trio": 7146, "waved": 7147, "raf": 7148, "dealing": 7149, "nathan": 7150, "bat": 7151, "murmured": 7152, "interrupted": 7153, "residing": 7154, "scientist": 7155, "pioneer": 7156, "harold": 7157, "aaron": 7158, "##net": 7159, "delta": 7160, "attempting": 7161, "minority": 7162, "mini": 7163, "believes": 7164, "chorus": 7165, "tend": 7166, "lots": 7167, "eyed": 7168, "indoor": 7169, "load": 7170, "shots": 7171, "updated": 7172, "jail": 7173, "##llo": 7174, "concerning": 7175, "connecting": 7176, "wealth": 7177, "##ved": 7178, "slaves": 7179, "arrive": 7180, "rangers": 7181, "sufficient": 7182, "rebuilt": 7183, "##wick": 7184, "cardinal": 7185, "flood": 7186, "muhammad": 7187, "whenever": 7188, "relation": 7189, "runners": 7190, "moral": 7191, "repair": 7192, "viewers": 7193, "arriving": 7194, "revenge": 7195, "punk": 7196, "assisted": 7197, "bath": 7198, "fairly": 7199, "breathe": 7200, "lists": 7201, "innings": 7202, "illustrated": 7203, "whisper": 7204, "nearest": 7205, "voters": 7206, "clinton": 7207, "ties": 7208, "ultimate": 7209, "screamed": 7210, "beijing": 7211, "lions": 7212, "andre": 7213, "fictional": 7214, "gathering": 7215, "comfort": 7216, "radar": 7217, "suitable": 7218, "dismissed": 7219, "hms": 7220, "ban": 7221, "pine": 7222, "wrist": 7223, "atmosphere": 7224, "voivodeship": 7225, "bid": 7226, "timber": 7227, "##ned": 7228, "##nan": 7229, "giants": 7230, "##ane": 7231, "cameron": 7232, "recovery": 7233, "uss": 7234, "identical": 7235, "categories": 7236, "switched": 7237, "serbia": 7238, "laughter": 7239, "noah": 7240, "ensemble": 7241, "therapy": 7242, "peoples": 7243, "touching": 7244, "##off": 7245, "locally": 7246, "pearl": 7247, "platforms": 7248, "everywhere": 7249, "ballet": 7250, "tables": 7251, "lanka": 7252, "herbert": 7253, "outdoor": 7254, "toured": 7255, "derek": 7256, "1883": 7257, "spaces": 7258, "contested": 7259, "swept": 7260, "1878": 7261, "exclusive": 7262, "slight": 7263, "connections": 7264, "##dra": 7265, "winds": 7266, "prisoner": 7267, "collective": 7268, "bangladesh": 7269, "tube": 7270, "publicly": 7271, "wealthy": 7272, "thai": 7273, "##ys": 7274, "isolated": 7275, "select": 7276, "##ric": 7277, "insisted": 7278, "pen": 7279, "fortune": 7280, "ticket": 7281, "spotted": 7282, "reportedly": 7283, "animation": 7284, "enforcement": 7285, "tanks": 7286, "110": 7287, "decides": 7288, "wider": 7289, "lowest": 7290, "owen": 7291, "##time": 7292, "nod": 7293, "hitting": 7294, "##hn": 7295, "gregory": 7296, "furthermore": 7297, "magazines": 7298, "fighters": 7299, "solutions": 7300, "##ery": 7301, "pointing": 7302, "requested": 7303, "peru": 7304, "reed": 7305, "chancellor": 7306, "knights": 7307, "mask": 7308, "worker": 7309, "eldest": 7310, "flames": 7311, "reduction": 7312, "1860": 7313, "volunteers": 7314, "##tis": 7315, "reporting": 7316, "##hl": 7317, "wire": 7318, "advisory": 7319, "endemic": 7320, "origins": 7321, "settlers": 7322, "pursue": 7323, "knock": 7324, "consumer": 7325, "1876": 7326, "eu": 7327, "compound": 7328, "creatures": 7329, "mansion": 7330, "sentenced": 7331, "ivan": 7332, "deployed": 7333, "guitars": 7334, "frowned": 7335, "involves": 7336, "mechanism": 7337, "kilometers": 7338, "perspective": 7339, "shops": 7340, "maps": 7341, "terminus": 7342, "duncan": 7343, "alien": 7344, "fist": 7345, "bridges": 7346, "##pers": 7347, "heroes": 7348, "fed": 7349, "derby": 7350, "swallowed": 7351, "##ros": 7352, "patent": 7353, "sara": 7354, "illness": 7355, "characterized": 7356, "adventures": 7357, "slide": 7358, "hawaii": 7359, "jurisdiction": 7360, "##op": 7361, "organised": 7362, "##side": 7363, "adelaide": 7364, "walks": 7365, "biology": 7366, "se": 7367, "##ties": 7368, "rogers": 7369, "swing": 7370, "tightly": 7371, "boundaries": 7372, "##rie": 7373, "prepare": 7374, "implementation": 7375, "stolen": 7376, "##sha": 7377, "certified": 7378, "colombia": 7379, "edwards": 7380, "garage": 7381, "##mm": 7382, "recalled": 7383, "##ball": 7384, "rage": 7385, "harm": 7386, "nigeria": 7387, "breast": 7388, "##ren": 7389, "furniture": 7390, "pupils": 7391, "settle": 7392, "##lus": 7393, "cuba": 7394, "balls": 7395, "client": 7396, "alaska": 7397, "21st": 7398, "linear": 7399, "thrust": 7400, "celebration": 7401, "latino": 7402, "genetic": 7403, "terror": 7404, "##cia": 7405, "##ening": 7406, "lightning": 7407, "fee": 7408, "witness": 7409, "lodge": 7410, "establishing": 7411, "skull": 7412, "##ique": 7413, "earning": 7414, "hood": 7415, "##ei": 7416, "rebellion": 7417, "wang": 7418, "sporting": 7419, "warned": 7420, "missile": 7421, "devoted": 7422, "activist": 7423, "porch": 7424, "worship": 7425, "fourteen": 7426, "package": 7427, "1871": 7428, "decorated": 7429, "##shire": 7430, "housed": 7431, "##ock": 7432, "chess": 7433, "sailed": 7434, "doctors": 7435, "oscar": 7436, "joan": 7437, "treat": 7438, "garcia": 7439, "harbour": 7440, "jeremy": 7441, "##ire": 7442, "traditions": 7443, "dominant": 7444, "jacques": 7445, "##gon": 7446, "##wan": 7447, "relocated": 7448, "1879": 7449, "amendment": 7450, "sized": 7451, "companion": 7452, "simultaneously": 7453, "volleyball": 7454, "spun": 7455, "acre": 7456, "increases": 7457, "stopping": 7458, "loves": 7459, "belongs": 7460, "affect": 7461, "drafted": 7462, "tossed": 7463, "scout": 7464, "battles": 7465, "1875": 7466, "filming": 7467, "shoved": 7468, "munich": 7469, "tenure": 7470, "vertical": 7471, "romance": 7472, "pc": 7473, "##cher": 7474, "argue": 7475, "##ical": 7476, "craft": 7477, "ranging": 7478, "www": 7479, "opens": 7480, "honest": 7481, "tyler": 7482, "yesterday": 7483, "virtual": 7484, "##let": 7485, "muslims": 7486, "reveal": 7487, "snake": 7488, "immigrants": 7489, "radical": 7490, "screaming": 7491, "speakers": 7492, "firing": 7493, "saving": 7494, "belonging": 7495, "ease": 7496, "lighting": 7497, "prefecture": 7498, "blame": 7499, "farmer": 7500, "hungry": 7501, "grows": 7502, "rubbed": 7503, "beam": 7504, "sur": 7505, "subsidiary": 7506, "##cha": 7507, "armenian": 7508, "sao": 7509, "dropping": 7510, "conventional": 7511, "##fer": 7512, "microsoft": 7513, "reply": 7514, "qualify": 7515, "spots": 7516, "1867": 7517, "sweat": 7518, "festivals": 7519, "##ken": 7520, "immigration": 7521, "physician": 7522, "discover": 7523, "exposure": 7524, "sandy": 7525, "explanation": 7526, "isaac": 7527, "implemented": 7528, "##fish": 7529, "hart": 7530, "initiated": 7531, "connect": 7532, "stakes": 7533, "presents": 7534, "heights": 7535, "householder": 7536, "pleased": 7537, "tourist": 7538, "regardless": 7539, "slip": 7540, "closest": 7541, "##ction": 7542, "surely": 7543, "sultan": 7544, "brings": 7545, "riley": 7546, "preparation": 7547, "aboard": 7548, "slammed": 7549, "baptist": 7550, "experiment": 7551, "ongoing": 7552, "interstate": 7553, "organic": 7554, "playoffs": 7555, "##ika": 7556, "1877": 7557, "130": 7558, "##tar": 7559, "hindu": 7560, "error": 7561, "tours": 7562, "tier": 7563, "plenty": 7564, "arrangements": 7565, "talks": 7566, "trapped": 7567, "excited": 7568, "sank": 7569, "ho": 7570, "athens": 7571, "1872": 7572, "denver": 7573, "welfare": 7574, "suburb": 7575, "athletes": 7576, "trick": 7577, "diverse": 7578, "belly": 7579, "exclusively": 7580, "yelled": 7581, "1868": 7582, "##med": 7583, "conversion": 7584, "##ette": 7585, "1874": 7586, "internationally": 7587, "computers": 7588, "conductor": 7589, "abilities": 7590, "sensitive": 7591, "hello": 7592, "dispute": 7593, "measured": 7594, "globe": 7595, "rocket": 7596, "prices": 7597, "amsterdam": 7598, "flights": 7599, "tigers": 7600, "inn": 7601, "municipalities": 7602, "emotion": 7603, "references": 7604, "3d": 7605, "##mus": 7606, "explains": 7607, "airlines": 7608, "manufactured": 7609, "pm": 7610, "archaeological": 7611, "1873": 7612, "interpretation": 7613, "devon": 7614, "comment": 7615, "##ites": 7616, "settlements": 7617, "kissing": 7618, "absolute": 7619, "improvement": 7620, "suite": 7621, "impressed": 7622, "barcelona": 7623, "sullivan": 7624, "jefferson": 7625, "towers": 7626, "jesse": 7627, "julie": 7628, "##tin": 7629, "##lu": 7630, "grandson": 7631, "hi": 7632, "gauge": 7633, "regard": 7634, "rings": 7635, "interviews": 7636, "trace": 7637, "raymond": 7638, "thumb": 7639, "departments": 7640, "burns": 7641, "serial": 7642, "bulgarian": 7643, "scores": 7644, "demonstrated": 7645, "##ix": 7646, "1866": 7647, "kyle": 7648, "alberta": 7649, "underneath": 7650, "romanized": 7651, "##ward": 7652, "relieved": 7653, "acquisition": 7654, "phrase": 7655, "cliff": 7656, "reveals": 7657, "han": 7658, "cuts": 7659, "merger": 7660, "custom": 7661, "##dar": 7662, "nee": 7663, "gilbert": 7664, "graduation": 7665, "##nts": 7666, "assessment": 7667, "cafe": 7668, "difficulty": 7669, "demands": 7670, "swung": 7671, "democrat": 7672, "jennifer": 7673, "commons": 7674, "1940s": 7675, "grove": 7676, "##yo": 7677, "completing": 7678, "focuses": 7679, "sum": 7680, "substitute": 7681, "bearing": 7682, "stretch": 7683, "reception": 7684, "##py": 7685, "reflected": 7686, "essentially": 7687, "destination": 7688, "pairs": 7689, "##ched": 7690, "survival": 7691, "resource": 7692, "##bach": 7693, "promoting": 7694, "doubles": 7695, "messages": 7696, "tear": 7697, "##down": 7698, "##fully": 7699, "parade": 7700, "florence": 7701, "harvey": 7702, "incumbent": 7703, "partial": 7704, "framework": 7705, "900": 7706, "pedro": 7707, "frozen": 7708, "procedure": 7709, "olivia": 7710, "controls": 7711, "##mic": 7712, "shelter": 7713, "personally": 7714, "temperatures": 7715, "##od": 7716, "brisbane": 7717, "tested": 7718, "sits": 7719, "marble": 7720, "comprehensive": 7721, "oxygen": 7722, "leonard": 7723, "##kov": 7724, "inaugural": 7725, "iranian": 7726, "referring": 7727, "quarters": 7728, "attitude": 7729, "##ivity": 7730, "mainstream": 7731, "lined": 7732, "mars": 7733, "dakota": 7734, "norfolk": 7735, "unsuccessful": 7736, "##°": 7737, "explosion": 7738, "helicopter": 7739, "congressional": 7740, "##sing": 7741, "inspector": 7742, "bitch": 7743, "seal": 7744, "departed": 7745, "divine": 7746, "##ters": 7747, "coaching": 7748, "examination": 7749, "punishment": 7750, "manufacturer": 7751, "sink": 7752, "columns": 7753, "unincorporated": 7754, "signals": 7755, "nevada": 7756, "squeezed": 7757, "dylan": 7758, "dining": 7759, "photos": 7760, "martial": 7761, "manuel": 7762, "eighteen": 7763, "elevator": 7764, "brushed": 7765, "plates": 7766, "ministers": 7767, "ivy": 7768, "congregation": 7769, "##len": 7770, "slept": 7771, "specialized": 7772, "taxes": 7773, "curve": 7774, "restricted": 7775, "negotiations": 7776, "likes": 7777, "statistical": 7778, "arnold": 7779, "inspiration": 7780, "execution": 7781, "bold": 7782, "intermediate": 7783, "significance": 7784, "margin": 7785, "ruler": 7786, "wheels": 7787, "gothic": 7788, "intellectual": 7789, "dependent": 7790, "listened": 7791, "eligible": 7792, "buses": 7793, "widow": 7794, "syria": 7795, "earn": 7796, "cincinnati": 7797, "collapsed": 7798, "recipient": 7799, "secrets": 7800, "accessible": 7801, "philippine": 7802, "maritime": 7803, "goddess": 7804, "clerk": 7805, "surrender": 7806, "breaks": 7807, "playoff": 7808, "database": 7809, "##ified": 7810, "##lon": 7811, "ideal": 7812, "beetle": 7813, "aspect": 7814, "soap": 7815, "regulation": 7816, "strings": 7817, "expand": 7818, "anglo": 7819, "shorter": 7820, "crosses": 7821, "retreat": 7822, "tough": 7823, "coins": 7824, "wallace": 7825, "directions": 7826, "pressing": 7827, "##oon": 7828, "shipping": 7829, "locomotives": 7830, "comparison": 7831, "topics": 7832, "nephew": 7833, "##mes": 7834, "distinction": 7835, "honors": 7836, "travelled": 7837, "sierra": 7838, "ibn": 7839, "##over": 7840, "fortress": 7841, "sa": 7842, "recognised": 7843, "carved": 7844, "1869": 7845, "clients": 7846, "##dan": 7847, "intent": 7848, "##mar": 7849, "coaches": 7850, "describing": 7851, "bread": 7852, "##ington": 7853, "beaten": 7854, "northwestern": 7855, "##ona": 7856, "merit": 7857, "youtube": 7858, "collapse": 7859, "challenges": 7860, "em": 7861, "historians": 7862, "objective": 7863, "submitted": 7864, "virus": 7865, "attacking": 7866, "drake": 7867, "assume": 7868, "##ere": 7869, "diseases": 7870, "marc": 7871, "stem": 7872, "leeds": 7873, "##cus": 7874, "##ab": 7875, "farming": 7876, "glasses": 7877, "##lock": 7878, "visits": 7879, "nowhere": 7880, "fellowship": 7881, "relevant": 7882, "carries": 7883, "restaurants": 7884, "experiments": 7885, "101": 7886, "constantly": 7887, "bases": 7888, "targets": 7889, "shah": 7890, "tenth": 7891, "opponents": 7892, "verse": 7893, "territorial": 7894, "##ira": 7895, "writings": 7896, "corruption": 7897, "##hs": 7898, "instruction": 7899, "inherited": 7900, "reverse": 7901, "emphasis": 7902, "##vic": 7903, "employee": 7904, "arch": 7905, "keeps": 7906, "rabbi": 7907, "watson": 7908, "payment": 7909, "uh": 7910, "##ala": 7911, "nancy": 7912, "##tre": 7913, "venice": 7914, "fastest": 7915, "sexy": 7916, "banned": 7917, "adrian": 7918, "properly": 7919, "ruth": 7920, "touchdown": 7921, "dollar": 7922, "boards": 7923, "metre": 7924, "circles": 7925, "edges": 7926, "favour": 7927, "comments": 7928, "ok": 7929, "travels": 7930, "liberation": 7931, "scattered": 7932, "firmly": 7933, "##ular": 7934, "holland": 7935, "permitted": 7936, "diesel": 7937, "kenya": 7938, "den": 7939, "originated": 7940, "##ral": 7941, "demons": 7942, "resumed": 7943, "dragged": 7944, "rider": 7945, "##rus": 7946, "servant": 7947, "blinked": 7948, "extend": 7949, "torn": 7950, "##ias": 7951, "##sey": 7952, "input": 7953, "meal": 7954, "everybody": 7955, "cylinder": 7956, "kinds": 7957, "camps": 7958, "##fe": 7959, "bullet": 7960, "logic": 7961, "##wn": 7962, "croatian": 7963, "evolved": 7964, "healthy": 7965, "fool": 7966, "chocolate": 7967, "wise": 7968, "preserve": 7969, "pradesh": 7970, "##ess": 7971, "respective": 7972, "1850": 7973, "##ew": 7974, "chicken": 7975, "artificial": 7976, "gross": 7977, "corresponding": 7978, "convicted": 7979, "cage": 7980, "caroline": 7981, "dialogue": 7982, "##dor": 7983, "narrative": 7984, "stranger": 7985, "mario": 7986, "br": 7987, "christianity": 7988, "failing": 7989, "trent": 7990, "commanding": 7991, "buddhist": 7992, "1848": 7993, "maurice": 7994, "focusing": 7995, "yale": 7996, "bike": 7997, "altitude": 7998, "##ering": 7999, "mouse": 8000, "revised": 8001, "##sley": 8002, "veteran": 8003, "##ig": 8004, "pulls": 8005, "theology": 8006, "crashed": 8007, "campaigns": 8008, "legion": 8009, "##ability": 8010, "drag": 8011, "excellence": 8012, "customer": 8013, "cancelled": 8014, "intensity": 8015, "excuse": 8016, "##lar": 8017, "liga": 8018, "participating": 8019, "contributing": 8020, "printing": 8021, "##burn": 8022, "variable": 8023, "##rk": 8024, "curious": 8025, "bin": 8026, "legacy": 8027, "renaissance": 8028, "##my": 8029, "symptoms": 8030, "binding": 8031, "vocalist": 8032, "dancer": 8033, "##nie": 8034, "grammar": 8035, "gospel": 8036, "democrats": 8037, "ya": 8038, "enters": 8039, "sc": 8040, "diplomatic": 8041, "hitler": 8042, "##ser": 8043, "clouds": 8044, "mathematical": 8045, "quit": 8046, "defended": 8047, "oriented": 8048, "##heim": 8049, "fundamental": 8050, "hardware": 8051, "impressive": 8052, "equally": 8053, "convince": 8054, "confederate": 8055, "guilt": 8056, "chuck": 8057, "sliding": 8058, "##ware": 8059, "magnetic": 8060, "narrowed": 8061, "petersburg": 8062, "bulgaria": 8063, "otto": 8064, "phd": 8065, "skill": 8066, "##ama": 8067, "reader": 8068, "hopes": 8069, "pitcher": 8070, "reservoir": 8071, "hearts": 8072, "automatically": 8073, "expecting": 8074, "mysterious": 8075, "bennett": 8076, "extensively": 8077, "imagined": 8078, "seeds": 8079, "monitor": 8080, "fix": 8081, "##ative": 8082, "journalism": 8083, "struggling": 8084, "signature": 8085, "ranch": 8086, "encounter": 8087, "photographer": 8088, "observation": 8089, "protests": 8090, "##pin": 8091, "influences": 8092, "##hr": 8093, "calendar": 8094, "##all": 8095, "cruz": 8096, "croatia": 8097, "locomotive": 8098, "hughes": 8099, "naturally": 8100, "shakespeare": 8101, "basement": 8102, "hook": 8103, "uncredited": 8104, "faded": 8105, "theories": 8106, "approaches": 8107, "dare": 8108, "phillips": 8109, "filling": 8110, "fury": 8111, "obama": 8112, "##ain": 8113, "efficient": 8114, "arc": 8115, "deliver": 8116, "min": 8117, "raid": 8118, "breeding": 8119, "inducted": 8120, "leagues": 8121, "efficiency": 8122, "axis": 8123, "montana": 8124, "eagles": 8125, "##ked": 8126, "supplied": 8127, "instructions": 8128, "karen": 8129, "picking": 8130, "indicating": 8131, "trap": 8132, "anchor": 8133, "practically": 8134, "christians": 8135, "tomb": 8136, "vary": 8137, "occasional": 8138, "electronics": 8139, "lords": 8140, "readers": 8141, "newcastle": 8142, "faint": 8143, "innovation": 8144, "collect": 8145, "situations": 8146, "engagement": 8147, "160": 8148, "claude": 8149, "mixture": 8150, "##feld": 8151, "peer": 8152, "tissue": 8153, "logo": 8154, "lean": 8155, "##ration": 8156, "°f": 8157, "floors": 8158, "##ven": 8159, "architects": 8160, "reducing": 8161, "##our": 8162, "##ments": 8163, "rope": 8164, "1859": 8165, "ottawa": 8166, "##har": 8167, "samples": 8168, "banking": 8169, "declaration": 8170, "proteins": 8171, "resignation": 8172, "francois": 8173, "saudi": 8174, "advocate": 8175, "exhibited": 8176, "armor": 8177, "twins": 8178, "divorce": 8179, "##ras": 8180, "abraham": 8181, "reviewed": 8182, "jo": 8183, "temporarily": 8184, "matrix": 8185, "physically": 8186, "pulse": 8187, "curled": 8188, "##ena": 8189, "difficulties": 8190, "bengal": 8191, "usage": 8192, "##ban": 8193, "annie": 8194, "riders": 8195, "certificate": 8196, "##pi": 8197, "holes": 8198, "warsaw": 8199, "distinctive": 8200, "jessica": 8201, "##mon": 8202, "mutual": 8203, "1857": 8204, "customs": 8205, "circular": 8206, "eugene": 8207, "removal": 8208, "loaded": 8209, "mere": 8210, "vulnerable": 8211, "depicted": 8212, "generations": 8213, "dame": 8214, "heir": 8215, "enormous": 8216, "lightly": 8217, "climbing": 8218, "pitched": 8219, "lessons": 8220, "pilots": 8221, "nepal": 8222, "ram": 8223, "google": 8224, "preparing": 8225, "brad": 8226, "louise": 8227, "renowned": 8228, "##₂": 8229, "liam": 8230, "##ably": 8231, "plaza": 8232, "shaw": 8233, "sophie": 8234, "brilliant": 8235, "bills": 8236, "##bar": 8237, "##nik": 8238, "fucking": 8239, "mainland": 8240, "server": 8241, "pleasant": 8242, "seized": 8243, "veterans": 8244, "jerked": 8245, "fail": 8246, "beta": 8247, "brush": 8248, "radiation": 8249, "stored": 8250, "warmth": 8251, "southeastern": 8252, "nate": 8253, "sin": 8254, "raced": 8255, "berkeley": 8256, "joke": 8257, "athlete": 8258, "designation": 8259, "trunk": 8260, "##low": 8261, "roland": 8262, "qualification": 8263, "archives": 8264, "heels": 8265, "artwork": 8266, "receives": 8267, "judicial": 8268, "reserves": 8269, "##bed": 8270, "woke": 8271, "installation": 8272, "abu": 8273, "floating": 8274, "fake": 8275, "lesser": 8276, "excitement": 8277, "interface": 8278, "concentrated": 8279, "addressed": 8280, "characteristic": 8281, "amanda": 8282, "saxophone": 8283, "monk": 8284, "auto": 8285, "##bus": 8286, "releasing": 8287, "egg": 8288, "dies": 8289, "interaction": 8290, "defender": 8291, "ce": 8292, "outbreak": 8293, "glory": 8294, "loving": 8295, "##bert": 8296, "sequel": 8297, "consciousness": 8298, "http": 8299, "awake": 8300, "ski": 8301, "enrolled": 8302, "##ress": 8303, "handling": 8304, "rookie": 8305, "brow": 8306, "somebody": 8307, "biography": 8308, "warfare": 8309, "amounts": 8310, "contracts": 8311, "presentation": 8312, "fabric": 8313, "dissolved": 8314, "challenged": 8315, "meter": 8316, "psychological": 8317, "lt": 8318, "elevated": 8319, "rally": 8320, "accurate": 8321, "##tha": 8322, "hospitals": 8323, "undergraduate": 8324, "specialist": 8325, "venezuela": 8326, "exhibit": 8327, "shed": 8328, "nursing": 8329, "protestant": 8330, "fluid": 8331, "structural": 8332, "footage": 8333, "jared": 8334, "consistent": 8335, "prey": 8336, "##ska": 8337, "succession": 8338, "reflect": 8339, "exile": 8340, "lebanon": 8341, "wiped": 8342, "suspect": 8343, "shanghai": 8344, "resting": 8345, "integration": 8346, "preservation": 8347, "marvel": 8348, "variant": 8349, "pirates": 8350, "sheep": 8351, "rounded": 8352, "capita": 8353, "sailing": 8354, "colonies": 8355, "manuscript": 8356, "deemed": 8357, "variations": 8358, "clarke": 8359, "functional": 8360, "emerging": 8361, "boxing": 8362, "relaxed": 8363, "curse": 8364, "azerbaijan": 8365, "heavyweight": 8366, "nickname": 8367, "editorial": 8368, "rang": 8369, "grid": 8370, "tightened": 8371, "earthquake": 8372, "flashed": 8373, "miguel": 8374, "rushing": 8375, "##ches": 8376, "improvements": 8377, "boxes": 8378, "brooks": 8379, "180": 8380, "consumption": 8381, "molecular": 8382, "felix": 8383, "societies": 8384, "repeatedly": 8385, "variation": 8386, "aids": 8387, "civic": 8388, "graphics": 8389, "professionals": 8390, "realm": 8391, "autonomous": 8392, "receiver": 8393, "delayed": 8394, "workshop": 8395, "militia": 8396, "chairs": 8397, "trump": 8398, "canyon": 8399, "##point": 8400, "harsh": 8401, "extending": 8402, "lovely": 8403, "happiness": 8404, "##jan": 8405, "stake": 8406, "eyebrows": 8407, "embassy": 8408, "wellington": 8409, "hannah": 8410, "##ella": 8411, "sony": 8412, "corners": 8413, "bishops": 8414, "swear": 8415, "cloth": 8416, "contents": 8417, "xi": 8418, "namely": 8419, "commenced": 8420, "1854": 8421, "stanford": 8422, "nashville": 8423, "courage": 8424, "graphic": 8425, "commitment": 8426, "garrison": 8427, "##bin": 8428, "hamlet": 8429, "clearing": 8430, "rebels": 8431, "attraction": 8432, "literacy": 8433, "cooking": 8434, "ruins": 8435, "temples": 8436, "jenny": 8437, "humanity": 8438, "celebrate": 8439, "hasn": 8440, "freight": 8441, "sixty": 8442, "rebel": 8443, "bastard": 8444, "##art": 8445, "newton": 8446, "##ada": 8447, "deer": 8448, "##ges": 8449, "##ching": 8450, "smiles": 8451, "delaware": 8452, "singers": 8453, "##ets": 8454, "approaching": 8455, "assists": 8456, "flame": 8457, "##ph": 8458, "boulevard": 8459, "barrel": 8460, "planted": 8461, "##ome": 8462, "pursuit": 8463, "##sia": 8464, "consequences": 8465, "posts": 8466, "shallow": 8467, "invitation": 8468, "rode": 8469, "depot": 8470, "ernest": 8471, "kane": 8472, "rod": 8473, "concepts": 8474, "preston": 8475, "topic": 8476, "chambers": 8477, "striking": 8478, "blast": 8479, "arrives": 8480, "descendants": 8481, "montgomery": 8482, "ranges": 8483, "worlds": 8484, "##lay": 8485, "##ari": 8486, "span": 8487, "chaos": 8488, "praise": 8489, "##ag": 8490, "fewer": 8491, "1855": 8492, "sanctuary": 8493, "mud": 8494, "fbi": 8495, "##ions": 8496, "programmes": 8497, "maintaining": 8498, "unity": 8499, "harper": 8500, "bore": 8501, "handsome": 8502, "closure": 8503, "tournaments": 8504, "thunder": 8505, "nebraska": 8506, "linda": 8507, "facade": 8508, "puts": 8509, "satisfied": 8510, "argentine": 8511, "dale": 8512, "cork": 8513, "dome": 8514, "panama": 8515, "##yl": 8516, "1858": 8517, "tasks": 8518, "experts": 8519, "##ates": 8520, "feeding": 8521, "equation": 8522, "##las": 8523, "##ida": 8524, "##tu": 8525, "engage": 8526, "bryan": 8527, "##ax": 8528, "um": 8529, "quartet": 8530, "melody": 8531, "disbanded": 8532, "sheffield": 8533, "blocked": 8534, "gasped": 8535, "delay": 8536, "kisses": 8537, "maggie": 8538, "connects": 8539, "##non": 8540, "sts": 8541, "poured": 8542, "creator": 8543, "publishers": 8544, "##we": 8545, "guided": 8546, "ellis": 8547, "extinct": 8548, "hug": 8549, "gaining": 8550, "##ord": 8551, "complicated": 8552, "##bility": 8553, "poll": 8554, "clenched": 8555, "investigate": 8556, "##use": 8557, "thereby": 8558, "quantum": 8559, "spine": 8560, "cdp": 8561, "humor": 8562, "kills": 8563, "administered": 8564, "semifinals": 8565, "##du": 8566, "encountered": 8567, "ignore": 8568, "##bu": 8569, "commentary": 8570, "##maker": 8571, "bother": 8572, "roosevelt": 8573, "140": 8574, "plains": 8575, "halfway": 8576, "flowing": 8577, "cultures": 8578, "crack": 8579, "imprisoned": 8580, "neighboring": 8581, "airline": 8582, "##ses": 8583, "##view": 8584, "##mate": 8585, "##ec": 8586, "gather": 8587, "wolves": 8588, "marathon": 8589, "transformed": 8590, "##ill": 8591, "cruise": 8592, "organisations": 8593, "carol": 8594, "punch": 8595, "exhibitions": 8596, "numbered": 8597, "alarm": 8598, "ratings": 8599, "daddy": 8600, "silently": 8601, "##stein": 8602, "queens": 8603, "colours": 8604, "impression": 8605, "guidance": 8606, "liu": 8607, "tactical": 8608, "##rat": 8609, "marshal": 8610, "della": 8611, "arrow": 8612, "##ings": 8613, "rested": 8614, "feared": 8615, "tender": 8616, "owns": 8617, "bitter": 8618, "advisor": 8619, "escort": 8620, "##ides": 8621, "spare": 8622, "farms": 8623, "grants": 8624, "##ene": 8625, "dragons": 8626, "encourage": 8627, "colleagues": 8628, "cameras": 8629, "##und": 8630, "sucked": 8631, "pile": 8632, "spirits": 8633, "prague": 8634, "statements": 8635, "suspension": 8636, "landmark": 8637, "fence": 8638, "torture": 8639, "recreation": 8640, "bags": 8641, "permanently": 8642, "survivors": 8643, "pond": 8644, "spy": 8645, "predecessor": 8646, "bombing": 8647, "coup": 8648, "##og": 8649, "protecting": 8650, "transformation": 8651, "glow": 8652, "##lands": 8653, "##book": 8654, "dug": 8655, "priests": 8656, "andrea": 8657, "feat": 8658, "barn": 8659, "jumping": 8660, "##chen": 8661, "##ologist": 8662, "##con": 8663, "casualties": 8664, "stern": 8665, "auckland": 8666, "pipe": 8667, "serie": 8668, "revealing": 8669, "ba": 8670, "##bel": 8671, "trevor": 8672, "mercy": 8673, "spectrum": 8674, "yang": 8675, "consist": 8676, "governing": 8677, "collaborated": 8678, "possessed": 8679, "epic": 8680, "comprises": 8681, "blew": 8682, "shane": 8683, "##ack": 8684, "lopez": 8685, "honored": 8686, "magical": 8687, "sacrifice": 8688, "judgment": 8689, "perceived": 8690, "hammer": 8691, "mtv": 8692, "baronet": 8693, "tune": 8694, "das": 8695, "missionary": 8696, "sheets": 8697, "350": 8698, "neutral": 8699, "oral": 8700, "threatening": 8701, "attractive": 8702, "shade": 8703, "aims": 8704, "seminary": 8705, "##master": 8706, "estates": 8707, "1856": 8708, "michel": 8709, "wounds": 8710, "refugees": 8711, "manufacturers": 8712, "##nic": 8713, "mercury": 8714, "syndrome": 8715, "porter": 8716, "##iya": 8717, "##din": 8718, "hamburg": 8719, "identification": 8720, "upstairs": 8721, "purse": 8722, "widened": 8723, "pause": 8724, "cared": 8725, "breathed": 8726, "affiliate": 8727, "santiago": 8728, "prevented": 8729, "celtic": 8730, "fisher": 8731, "125": 8732, "recruited": 8733, "byzantine": 8734, "reconstruction": 8735, "farther": 8736, "##mp": 8737, "diet": 8738, "sake": 8739, "au": 8740, "spite": 8741, "sensation": 8742, "##ert": 8743, "blank": 8744, "separation": 8745, "105": 8746, "##hon": 8747, "vladimir": 8748, "armies": 8749, "anime": 8750, "##lie": 8751, "accommodate": 8752, "orbit": 8753, "cult": 8754, "sofia": 8755, "archive": 8756, "##ify": 8757, "##box": 8758, "founders": 8759, "sustained": 8760, "disorder": 8761, "honours": 8762, "northeastern": 8763, "mia": 8764, "crops": 8765, "violet": 8766, "threats": 8767, "blanket": 8768, "fires": 8769, "canton": 8770, "followers": 8771, "southwestern": 8772, "prototype": 8773, "voyage": 8774, "assignment": 8775, "altered": 8776, "moderate": 8777, "protocol": 8778, "pistol": 8779, "##eo": 8780, "questioned": 8781, "brass": 8782, "lifting": 8783, "1852": 8784, "math": 8785, "authored": 8786, "##ual": 8787, "doug": 8788, "dimensional": 8789, "dynamic": 8790, "##san": 8791, "1851": 8792, "pronounced": 8793, "grateful": 8794, "quest": 8795, "uncomfortable": 8796, "boom": 8797, "presidency": 8798, "stevens": 8799, "relating": 8800, "politicians": 8801, "chen": 8802, "barrier": 8803, "quinn": 8804, "diana": 8805, "mosque": 8806, "tribal": 8807, "cheese": 8808, "palmer": 8809, "portions": 8810, "sometime": 8811, "chester": 8812, "treasure": 8813, "wu": 8814, "bend": 8815, "download": 8816, "millions": 8817, "reforms": 8818, "registration": 8819, "##osa": 8820, "consequently": 8821, "monitoring": 8822, "ate": 8823, "preliminary": 8824, "brandon": 8825, "invented": 8826, "ps": 8827, "eaten": 8828, "exterior": 8829, "intervention": 8830, "ports": 8831, "documented": 8832, "log": 8833, "displays": 8834, "lecture": 8835, "sally": 8836, "favourite": 8837, "##itz": 8838, "vermont": 8839, "lo": 8840, "invisible": 8841, "isle": 8842, "breed": 8843, "##ator": 8844, "journalists": 8845, "relay": 8846, "speaks": 8847, "backward": 8848, "explore": 8849, "midfielder": 8850, "actively": 8851, "stefan": 8852, "procedures": 8853, "cannon": 8854, "blond": 8855, "kenneth": 8856, "centered": 8857, "servants": 8858, "chains": 8859, "libraries": 8860, "malcolm": 8861, "essex": 8862, "henri": 8863, "slavery": 8864, "##hal": 8865, "facts": 8866, "fairy": 8867, "coached": 8868, "cassie": 8869, "cats": 8870, "washed": 8871, "cop": 8872, "##fi": 8873, "announcement": 8874, "item": 8875, "2000s": 8876, "vinyl": 8877, "activated": 8878, "marco": 8879, "frontier": 8880, "growled": 8881, "curriculum": 8882, "##das": 8883, "loyal": 8884, "accomplished": 8885, "leslie": 8886, "ritual": 8887, "kenny": 8888, "##00": 8889, "vii": 8890, "napoleon": 8891, "hollow": 8892, "hybrid": 8893, "jungle": 8894, "stationed": 8895, "friedrich": 8896, "counted": 8897, "##ulated": 8898, "platinum": 8899, "theatrical": 8900, "seated": 8901, "col": 8902, "rubber": 8903, "glen": 8904, "1840": 8905, "diversity": 8906, "healing": 8907, "extends": 8908, "id": 8909, "provisions": 8910, "administrator": 8911, "columbus": 8912, "##oe": 8913, "tributary": 8914, "te": 8915, "assured": 8916, "org": 8917, "##uous": 8918, "prestigious": 8919, "examined": 8920, "lectures": 8921, "grammy": 8922, "ronald": 8923, "associations": 8924, "bailey": 8925, "allan": 8926, "essays": 8927, "flute": 8928, "believing": 8929, "consultant": 8930, "proceedings": 8931, "travelling": 8932, "1853": 8933, "kit": 8934, "kerala": 8935, "yugoslavia": 8936, "buddy": 8937, "methodist": 8938, "##ith": 8939, "burial": 8940, "centres": 8941, "batman": 8942, "##nda": 8943, "discontinued": 8944, "bo": 8945, "dock": 8946, "stockholm": 8947, "lungs": 8948, "severely": 8949, "##nk": 8950, "citing": 8951, "manga": 8952, "##ugh": 8953, "steal": 8954, "mumbai": 8955, "iraqi": 8956, "robot": 8957, "celebrity": 8958, "bride": 8959, "broadcasts": 8960, "abolished": 8961, "pot": 8962, "joel": 8963, "overhead": 8964, "franz": 8965, "packed": 8966, "reconnaissance": 8967, "johann": 8968, "acknowledged": 8969, "introduce": 8970, "handled": 8971, "doctorate": 8972, "developments": 8973, "drinks": 8974, "alley": 8975, "palestine": 8976, "##nis": 8977, "##aki": 8978, "proceeded": 8979, "recover": 8980, "bradley": 8981, "grain": 8982, "patch": 8983, "afford": 8984, "infection": 8985, "nationalist": 8986, "legendary": 8987, "##ath": 8988, "interchange": 8989, "virtually": 8990, "gen": 8991, "gravity": 8992, "exploration": 8993, "amber": 8994, "vital": 8995, "wishes": 8996, "powell": 8997, "doctrine": 8998, "elbow": 8999, "screenplay": 9000, "##bird": 9001, "contribute": 9002, "indonesian": 9003, "pet": 9004, "creates": 9005, "##com": 9006, "enzyme": 9007, "kylie": 9008, "discipline": 9009, "drops": 9010, "manila": 9011, "hunger": 9012, "##ien": 9013, "layers": 9014, "suffer": 9015, "fever": 9016, "bits": 9017, "monica": 9018, "keyboard": 9019, "manages": 9020, "##hood": 9021, "searched": 9022, "appeals": 9023, "##bad": 9024, "testament": 9025, "grande": 9026, "reid": 9027, "##war": 9028, "beliefs": 9029, "congo": 9030, "##ification": 9031, "##dia": 9032, "si": 9033, "requiring": 9034, "##via": 9035, "casey": 9036, "1849": 9037, "regret": 9038, "streak": 9039, "rape": 9040, "depends": 9041, "syrian": 9042, "sprint": 9043, "pound": 9044, "tourists": 9045, "upcoming": 9046, "pub": 9047, "##xi": 9048, "tense": 9049, "##els": 9050, "practiced": 9051, "echo": 9052, "nationwide": 9053, "guild": 9054, "motorcycle": 9055, "liz": 9056, "##zar": 9057, "chiefs": 9058, "desired": 9059, "elena": 9060, "bye": 9061, "precious": 9062, "absorbed": 9063, "relatives": 9064, "booth": 9065, "pianist": 9066, "##mal": 9067, "citizenship": 9068, "exhausted": 9069, "wilhelm": 9070, "##ceae": 9071, "##hed": 9072, "noting": 9073, "quarterback": 9074, "urge": 9075, "hectares": 9076, "##gue": 9077, "ace": 9078, "holly": 9079, "##tal": 9080, "blonde": 9081, "davies": 9082, "parked": 9083, "sustainable": 9084, "stepping": 9085, "twentieth": 9086, "airfield": 9087, "galaxy": 9088, "nest": 9089, "chip": 9090, "##nell": 9091, "tan": 9092, "shaft": 9093, "paulo": 9094, "requirement": 9095, "##zy": 9096, "paradise": 9097, "tobacco": 9098, "trans": 9099, "renewed": 9100, "vietnamese": 9101, "##cker": 9102, "##ju": 9103, "suggesting": 9104, "catching": 9105, "holmes": 9106, "enjoying": 9107, "md": 9108, "trips": 9109, "colt": 9110, "holder": 9111, "butterfly": 9112, "nerve": 9113, "reformed": 9114, "cherry": 9115, "bowling": 9116, "trailer": 9117, "carriage": 9118, "goodbye": 9119, "appreciate": 9120, "toy": 9121, "joshua": 9122, "interactive": 9123, "enabled": 9124, "involve": 9125, "##kan": 9126, "collar": 9127, "determination": 9128, "bunch": 9129, "facebook": 9130, "recall": 9131, "shorts": 9132, "superintendent": 9133, "episcopal": 9134, "frustration": 9135, "giovanni": 9136, "nineteenth": 9137, "laser": 9138, "privately": 9139, "array": 9140, "circulation": 9141, "##ovic": 9142, "armstrong": 9143, "deals": 9144, "painful": 9145, "permit": 9146, "discrimination": 9147, "##wi": 9148, "aires": 9149, "retiring": 9150, "cottage": 9151, "ni": 9152, "##sta": 9153, "horizon": 9154, "ellen": 9155, "jamaica": 9156, "ripped": 9157, "fernando": 9158, "chapters": 9159, "playstation": 9160, "patron": 9161, "lecturer": 9162, "navigation": 9163, "behaviour": 9164, "genes": 9165, "georgian": 9166, "export": 9167, "solomon": 9168, "rivals": 9169, "swift": 9170, "seventeen": 9171, "rodriguez": 9172, "princeton": 9173, "independently": 9174, "sox": 9175, "1847": 9176, "arguing": 9177, "entity": 9178, "casting": 9179, "hank": 9180, "criteria": 9181, "oakland": 9182, "geographic": 9183, "milwaukee": 9184, "reflection": 9185, "expanding": 9186, "conquest": 9187, "dubbed": 9188, "##tv": 9189, "halt": 9190, "brave": 9191, "brunswick": 9192, "doi": 9193, "arched": 9194, "curtis": 9195, "divorced": 9196, "predominantly": 9197, "somerset": 9198, "streams": 9199, "ugly": 9200, "zoo": 9201, "horrible": 9202, "curved": 9203, "buenos": 9204, "fierce": 9205, "dictionary": 9206, "vector": 9207, "theological": 9208, "unions": 9209, "handful": 9210, "stability": 9211, "chan": 9212, "punjab": 9213, "segments": 9214, "##lly": 9215, "altar": 9216, "ignoring": 9217, "gesture": 9218, "monsters": 9219, "pastor": 9220, "##stone": 9221, "thighs": 9222, "unexpected": 9223, "operators": 9224, "abruptly": 9225, "coin": 9226, "compiled": 9227, "associates": 9228, "improving": 9229, "migration": 9230, "pin": 9231, "##ose": 9232, "compact": 9233, "collegiate": 9234, "reserved": 9235, "##urs": 9236, "quarterfinals": 9237, "roster": 9238, "restore": 9239, "assembled": 9240, "hurry": 9241, "oval": 9242, "##cies": 9243, "1846": 9244, "flags": 9245, "martha": 9246, "##del": 9247, "victories": 9248, "sharply": 9249, "##rated": 9250, "argues": 9251, "deadly": 9252, "neo": 9253, "drawings": 9254, "symbols": 9255, "performer": 9256, "##iel": 9257, "griffin": 9258, "restrictions": 9259, "editing": 9260, "andrews": 9261, "java": 9262, "journals": 9263, "arabia": 9264, "compositions": 9265, "dee": 9266, "pierce": 9267, "removing": 9268, "hindi": 9269, "casino": 9270, "runway": 9271, "civilians": 9272, "minds": 9273, "nasa": 9274, "hotels": 9275, "##zation": 9276, "refuge": 9277, "rent": 9278, "retain": 9279, "potentially": 9280, "conferences": 9281, "suburban": 9282, "conducting": 9283, "##tto": 9284, "##tions": 9285, "##tle": 9286, "descended": 9287, "massacre": 9288, "##cal": 9289, "ammunition": 9290, "terrain": 9291, "fork": 9292, "souls": 9293, "counts": 9294, "chelsea": 9295, "durham": 9296, "drives": 9297, "cab": 9298, "##bank": 9299, "perth": 9300, "realizing": 9301, "palestinian": 9302, "finn": 9303, "simpson": 9304, "##dal": 9305, "betty": 9306, "##ule": 9307, "moreover": 9308, "particles": 9309, "cardinals": 9310, "tent": 9311, "evaluation": 9312, "extraordinary": 9313, "##oid": 9314, "inscription": 9315, "##works": 9316, "wednesday": 9317, "chloe": 9318, "maintains": 9319, "panels": 9320, "ashley": 9321, "trucks": 9322, "##nation": 9323, "cluster": 9324, "sunlight": 9325, "strikes": 9326, "zhang": 9327, "##wing": 9328, "dialect": 9329, "canon": 9330, "##ap": 9331, "tucked": 9332, "##ws": 9333, "collecting": 9334, "##mas": 9335, "##can": 9336, "##sville": 9337, "maker": 9338, "quoted": 9339, "evan": 9340, "franco": 9341, "aria": 9342, "buying": 9343, "cleaning": 9344, "eva": 9345, "closet": 9346, "provision": 9347, "apollo": 9348, "clinic": 9349, "rat": 9350, "##ez": 9351, "necessarily": 9352, "ac": 9353, "##gle": 9354, "##ising": 9355, "venues": 9356, "flipped": 9357, "cent": 9358, "spreading": 9359, "trustees": 9360, "checking": 9361, "authorized": 9362, "##sco": 9363, "disappointed": 9364, "##ado": 9365, "notion": 9366, "duration": 9367, "trumpet": 9368, "hesitated": 9369, "topped": 9370, "brussels": 9371, "rolls": 9372, "theoretical": 9373, "hint": 9374, "define": 9375, "aggressive": 9376, "repeat": 9377, "wash": 9378, "peaceful": 9379, "optical": 9380, "width": 9381, "allegedly": 9382, "mcdonald": 9383, "strict": 9384, "copyright": 9385, "##illa": 9386, "investors": 9387, "mar": 9388, "jam": 9389, "witnesses": 9390, "sounding": 9391, "miranda": 9392, "michelle": 9393, "privacy": 9394, "hugo": 9395, "harmony": 9396, "##pp": 9397, "valid": 9398, "lynn": 9399, "glared": 9400, "nina": 9401, "102": 9402, "headquartered": 9403, "diving": 9404, "boarding": 9405, "gibson": 9406, "##ncy": 9407, "albanian": 9408, "marsh": 9409, "routine": 9410, "dealt": 9411, "enhanced": 9412, "er": 9413, "intelligent": 9414, "substance": 9415, "targeted": 9416, "enlisted": 9417, "discovers": 9418, "spinning": 9419, "observations": 9420, "pissed": 9421, "smoking": 9422, "rebecca": 9423, "capitol": 9424, "visa": 9425, "varied": 9426, "costume": 9427, "seemingly": 9428, "indies": 9429, "compensation": 9430, "surgeon": 9431, "thursday": 9432, "arsenal": 9433, "westminster": 9434, "suburbs": 9435, "rid": 9436, "anglican": 9437, "##ridge": 9438, "knots": 9439, "foods": 9440, "alumni": 9441, "lighter": 9442, "fraser": 9443, "whoever": 9444, "portal": 9445, "scandal": 9446, "##ray": 9447, "gavin": 9448, "advised": 9449, "instructor": 9450, "flooding": 9451, "terrorist": 9452, "##ale": 9453, "teenage": 9454, "interim": 9455, "senses": 9456, "duck": 9457, "teen": 9458, "thesis": 9459, "abby": 9460, "eager": 9461, "overcome": 9462, "##ile": 9463, "newport": 9464, "glenn": 9465, "rises": 9466, "shame": 9467, "##cc": 9468, "prompted": 9469, "priority": 9470, "forgot": 9471, "bomber": 9472, "nicolas": 9473, "protective": 9474, "360": 9475, "cartoon": 9476, "katherine": 9477, "breeze": 9478, "lonely": 9479, "trusted": 9480, "henderson": 9481, "richardson": 9482, "relax": 9483, "banner": 9484, "candy": 9485, "palms": 9486, "remarkable": 9487, "##rio": 9488, "legends": 9489, "cricketer": 9490, "essay": 9491, "ordained": 9492, "edmund": 9493, "rifles": 9494, "trigger": 9495, "##uri": 9496, "##away": 9497, "sail": 9498, "alert": 9499, "1830": 9500, "audiences": 9501, "penn": 9502, "sussex": 9503, "siblings": 9504, "pursued": 9505, "indianapolis": 9506, "resist": 9507, "rosa": 9508, "consequence": 9509, "succeed": 9510, "avoided": 9511, "1845": 9512, "##ulation": 9513, "inland": 9514, "##tie": 9515, "##nna": 9516, "counsel": 9517, "profession": 9518, "chronicle": 9519, "hurried": 9520, "##una": 9521, "eyebrow": 9522, "eventual": 9523, "bleeding": 9524, "innovative": 9525, "cure": 9526, "##dom": 9527, "committees": 9528, "accounting": 9529, "con": 9530, "scope": 9531, "hardy": 9532, "heather": 9533, "tenor": 9534, "gut": 9535, "herald": 9536, "codes": 9537, "tore": 9538, "scales": 9539, "wagon": 9540, "##oo": 9541, "luxury": 9542, "tin": 9543, "prefer": 9544, "fountain": 9545, "triangle": 9546, "bonds": 9547, "darling": 9548, "convoy": 9549, "dried": 9550, "traced": 9551, "beings": 9552, "troy": 9553, "accidentally": 9554, "slam": 9555, "findings": 9556, "smelled": 9557, "joey": 9558, "lawyers": 9559, "outcome": 9560, "steep": 9561, "bosnia": 9562, "configuration": 9563, "shifting": 9564, "toll": 9565, "brook": 9566, "performers": 9567, "lobby": 9568, "philosophical": 9569, "construct": 9570, "shrine": 9571, "aggregate": 9572, "boot": 9573, "cox": 9574, "phenomenon": 9575, "savage": 9576, "insane": 9577, "solely": 9578, "reynolds": 9579, "lifestyle": 9580, "##ima": 9581, "nationally": 9582, "holdings": 9583, "consideration": 9584, "enable": 9585, "edgar": 9586, "mo": 9587, "mama": 9588, "##tein": 9589, "fights": 9590, "relegation": 9591, "chances": 9592, "atomic": 9593, "hub": 9594, "conjunction": 9595, "awkward": 9596, "reactions": 9597, "currency": 9598, "finale": 9599, "kumar": 9600, "underwent": 9601, "steering": 9602, "elaborate": 9603, "gifts": 9604, "comprising": 9605, "melissa": 9606, "veins": 9607, "reasonable": 9608, "sunshine": 9609, "chi": 9610, "solve": 9611, "trails": 9612, "inhabited": 9613, "elimination": 9614, "ethics": 9615, "huh": 9616, "ana": 9617, "molly": 9618, "consent": 9619, "apartments": 9620, "layout": 9621, "marines": 9622, "##ces": 9623, "hunters": 9624, "bulk": 9625, "##oma": 9626, "hometown": 9627, "##wall": 9628, "##mont": 9629, "cracked": 9630, "reads": 9631, "neighbouring": 9632, "withdrawn": 9633, "admission": 9634, "wingspan": 9635, "damned": 9636, "anthology": 9637, "lancashire": 9638, "brands": 9639, "batting": 9640, "forgive": 9641, "cuban": 9642, "awful": 9643, "##lyn": 9644, "104": 9645, "dimensions": 9646, "imagination": 9647, "##ade": 9648, "dante": 9649, "##ship": 9650, "tracking": 9651, "desperately": 9652, "goalkeeper": 9653, "##yne": 9654, "groaned": 9655, "workshops": 9656, "confident": 9657, "burton": 9658, "gerald": 9659, "milton": 9660, "circus": 9661, "uncertain": 9662, "slope": 9663, "copenhagen": 9664, "sophia": 9665, "fog": 9666, "philosopher": 9667, "portraits": 9668, "accent": 9669, "cycling": 9670, "varying": 9671, "gripped": 9672, "larvae": 9673, "garrett": 9674, "specified": 9675, "scotia": 9676, "mature": 9677, "luther": 9678, "kurt": 9679, "rap": 9680, "##kes": 9681, "aerial": 9682, "750": 9683, "ferdinand": 9684, "heated": 9685, "es": 9686, "transported": 9687, "##shan": 9688, "safely": 9689, "nonetheless": 9690, "##orn": 9691, "##gal": 9692, "motors": 9693, "demanding": 9694, "##sburg": 9695, "startled": 9696, "##brook": 9697, "ally": 9698, "generate": 9699, "caps": 9700, "ghana": 9701, "stained": 9702, "demo": 9703, "mentions": 9704, "beds": 9705, "ap": 9706, "afterward": 9707, "diary": 9708, "##bling": 9709, "utility": 9710, "##iro": 9711, "richards": 9712, "1837": 9713, "conspiracy": 9714, "conscious": 9715, "shining": 9716, "footsteps": 9717, "observer": 9718, "cyprus": 9719, "urged": 9720, "loyalty": 9721, "developer": 9722, "probability": 9723, "olive": 9724, "upgraded": 9725, "gym": 9726, "miracle": 9727, "insects": 9728, "graves": 9729, "1844": 9730, "ourselves": 9731, "hydrogen": 9732, "amazon": 9733, "katie": 9734, "tickets": 9735, "poets": 9736, "##pm": 9737, "planes": 9738, "##pan": 9739, "prevention": 9740, "witnessed": 9741, "dense": 9742, "jin": 9743, "randy": 9744, "tang": 9745, "warehouse": 9746, "monroe": 9747, "bang": 9748, "archived": 9749, "elderly": 9750, "investigations": 9751, "alec": 9752, "granite": 9753, "mineral": 9754, "conflicts": 9755, "controlling": 9756, "aboriginal": 9757, "carlo": 9758, "##zu": 9759, "mechanics": 9760, "stan": 9761, "stark": 9762, "rhode": 9763, "skirt": 9764, "est": 9765, "##berry": 9766, "bombs": 9767, "respected": 9768, "##horn": 9769, "imposed": 9770, "limestone": 9771, "deny": 9772, "nominee": 9773, "memphis": 9774, "grabbing": 9775, "disabled": 9776, "##als": 9777, "amusement": 9778, "aa": 9779, "frankfurt": 9780, "corn": 9781, "referendum": 9782, "varies": 9783, "slowed": 9784, "disk": 9785, "firms": 9786, "unconscious": 9787, "incredible": 9788, "clue": 9789, "sue": 9790, "##zhou": 9791, "twist": 9792, "##cio": 9793, "joins": 9794, "idaho": 9795, "chad": 9796, "developers": 9797, "computing": 9798, "destroyer": 9799, "103": 9800, "mortal": 9801, "tucker": 9802, "kingston": 9803, "choices": 9804, "yu": 9805, "carson": 9806, "1800": 9807, "os": 9808, "whitney": 9809, "geneva": 9810, "pretend": 9811, "dimension": 9812, "staged": 9813, "plateau": 9814, "maya": 9815, "##une": 9816, "freestyle": 9817, "##bc": 9818, "rovers": 9819, "hiv": 9820, "##ids": 9821, "tristan": 9822, "classroom": 9823, "prospect": 9824, "##hus": 9825, "honestly": 9826, "diploma": 9827, "lied": 9828, "thermal": 9829, "auxiliary": 9830, "feast": 9831, "unlikely": 9832, "iata": 9833, "##tel": 9834, "morocco": 9835, "pounding": 9836, "treasury": 9837, "lithuania": 9838, "considerably": 9839, "1841": 9840, "dish": 9841, "1812": 9842, "geological": 9843, "matching": 9844, "stumbled": 9845, "destroying": 9846, "marched": 9847, "brien": 9848, "advances": 9849, "cake": 9850, "nicole": 9851, "belle": 9852, "settling": 9853, "measuring": 9854, "directing": 9855, "##mie": 9856, "tuesday": 9857, "bassist": 9858, "capabilities": 9859, "stunned": 9860, "fraud": 9861, "torpedo": 9862, "##list": 9863, "##phone": 9864, "anton": 9865, "wisdom": 9866, "surveillance": 9867, "ruined": 9868, "##ulate": 9869, "lawsuit": 9870, "healthcare": 9871, "theorem": 9872, "halls": 9873, "trend": 9874, "aka": 9875, "horizontal": 9876, "dozens": 9877, "acquire": 9878, "lasting": 9879, "swim": 9880, "hawk": 9881, "gorgeous": 9882, "fees": 9883, "vicinity": 9884, "decrease": 9885, "adoption": 9886, "tactics": 9887, "##ography": 9888, "pakistani": 9889, "##ole": 9890, "draws": 9891, "##hall": 9892, "willie": 9893, "burke": 9894, "heath": 9895, "algorithm": 9896, "integral": 9897, "powder": 9898, "elliott": 9899, "brigadier": 9900, "jackie": 9901, "tate": 9902, "varieties": 9903, "darker": 9904, "##cho": 9905, "lately": 9906, "cigarette": 9907, "specimens": 9908, "adds": 9909, "##ree": 9910, "##ensis": 9911, "##inger": 9912, "exploded": 9913, "finalist": 9914, "cia": 9915, "murders": 9916, "wilderness": 9917, "arguments": 9918, "nicknamed": 9919, "acceptance": 9920, "onwards": 9921, "manufacture": 9922, "robertson": 9923, "jets": 9924, "tampa": 9925, "enterprises": 9926, "blog": 9927, "loudly": 9928, "composers": 9929, "nominations": 9930, "1838": 9931, "ai": 9932, "malta": 9933, "inquiry": 9934, "automobile": 9935, "hosting": 9936, "viii": 9937, "rays": 9938, "tilted": 9939, "grief": 9940, "museums": 9941, "strategies": 9942, "furious": 9943, "euro": 9944, "equality": 9945, "cohen": 9946, "poison": 9947, "surrey": 9948, "wireless": 9949, "governed": 9950, "ridiculous": 9951, "moses": 9952, "##esh": 9953, "##room": 9954, "vanished": 9955, "##ito": 9956, "barnes": 9957, "attract": 9958, "morrison": 9959, "istanbul": 9960, "##iness": 9961, "absent": 9962, "rotation": 9963, "petition": 9964, "janet": 9965, "##logical": 9966, "satisfaction": 9967, "custody": 9968, "deliberately": 9969, "observatory": 9970, "comedian": 9971, "surfaces": 9972, "pinyin": 9973, "novelist": 9974, "strictly": 9975, "canterbury": 9976, "oslo": 9977, "monks": 9978, "embrace": 9979, "ibm": 9980, "jealous": 9981, "photograph": 9982, "continent": 9983, "dorothy": 9984, "marina": 9985, "doc": 9986, "excess": 9987, "holden": 9988, "allegations": 9989, "explaining": 9990, "stack": 9991, "avoiding": 9992, "lance": 9993, "storyline": 9994, "majesty": 9995, "poorly": 9996, "spike": 9997, "dos": 9998, "bradford": 9999, "raven": 10000, "travis": 10001, "classics": 10002, "proven": 10003, "voltage": 10004, "pillow": 10005, "fists": 10006, "butt": 10007, "1842": 10008, "interpreted": 10009, "##car": 10010, "1839": 10011, "gage": 10012, "telegraph": 10013, "lens": 10014, "promising": 10015, "expelled": 10016, "casual": 10017, "collector": 10018, "zones": 10019, "##min": 10020, "silly": 10021, "nintendo": 10022, "##kh": 10023, "##bra": 10024, "downstairs": 10025, "chef": 10026, "suspicious": 10027, "afl": 10028, "flies": 10029, "vacant": 10030, "uganda": 10031, "pregnancy": 10032, "condemned": 10033, "lutheran": 10034, "estimates": 10035, "cheap": 10036, "decree": 10037, "saxon": 10038, "proximity": 10039, "stripped": 10040, "idiot": 10041, "deposits": 10042, "contrary": 10043, "presenter": 10044, "magnus": 10045, "glacier": 10046, "im": 10047, "offense": 10048, "edwin": 10049, "##ori": 10050, "upright": 10051, "##long": 10052, "bolt": 10053, "##ois": 10054, "toss": 10055, "geographical": 10056, "##izes": 10057, "environments": 10058, "delicate": 10059, "marking": 10060, "abstract": 10061, "xavier": 10062, "nails": 10063, "windsor": 10064, "plantation": 10065, "occurring": 10066, "equity": 10067, "saskatchewan": 10068, "fears": 10069, "drifted": 10070, "sequences": 10071, "vegetation": 10072, "revolt": 10073, "##stic": 10074, "1843": 10075, "sooner": 10076, "fusion": 10077, "opposing": 10078, "nato": 10079, "skating": 10080, "1836": 10081, "secretly": 10082, "ruin": 10083, "lease": 10084, "##oc": 10085, "edit": 10086, "##nne": 10087, "flora": 10088, "anxiety": 10089, "ruby": 10090, "##ological": 10091, "##mia": 10092, "tel": 10093, "bout": 10094, "taxi": 10095, "emmy": 10096, "frost": 10097, "rainbow": 10098, "compounds": 10099, "foundations": 10100, "rainfall": 10101, "assassination": 10102, "nightmare": 10103, "dominican": 10104, "##win": 10105, "achievements": 10106, "deserve": 10107, "orlando": 10108, "intact": 10109, "armenia": 10110, "##nte": 10111, "calgary": 10112, "valentine": 10113, "106": 10114, "marion": 10115, "proclaimed": 10116, "theodore": 10117, "bells": 10118, "courtyard": 10119, "thigh": 10120, "gonzalez": 10121, "console": 10122, "troop": 10123, "minimal": 10124, "monte": 10125, "everyday": 10126, "##ence": 10127, "##if": 10128, "supporter": 10129, "terrorism": 10130, "buck": 10131, "openly": 10132, "presbyterian": 10133, "activists": 10134, "carpet": 10135, "##iers": 10136, "rubbing": 10137, "uprising": 10138, "##yi": 10139, "cute": 10140, "conceived": 10141, "legally": 10142, "##cht": 10143, "millennium": 10144, "cello": 10145, "velocity": 10146, "ji": 10147, "rescued": 10148, "cardiff": 10149, "1835": 10150, "rex": 10151, "concentrate": 10152, "senators": 10153, "beard": 10154, "rendered": 10155, "glowing": 10156, "battalions": 10157, "scouts": 10158, "competitors": 10159, "sculptor": 10160, "catalogue": 10161, "arctic": 10162, "ion": 10163, "raja": 10164, "bicycle": 10165, "wow": 10166, "glancing": 10167, "lawn": 10168, "##woman": 10169, "gentleman": 10170, "lighthouse": 10171, "publish": 10172, "predicted": 10173, "calculated": 10174, "##val": 10175, "variants": 10176, "##gne": 10177, "strain": 10178, "##ui": 10179, "winston": 10180, "deceased": 10181, "##nus": 10182, "touchdowns": 10183, "brady": 10184, "caleb": 10185, "sinking": 10186, "echoed": 10187, "crush": 10188, "hon": 10189, "blessed": 10190, "protagonist": 10191, "hayes": 10192, "endangered": 10193, "magnitude": 10194, "editors": 10195, "##tine": 10196, "estimate": 10197, "responsibilities": 10198, "##mel": 10199, "backup": 10200, "laying": 10201, "consumed": 10202, "sealed": 10203, "zurich": 10204, "lovers": 10205, "frustrated": 10206, "##eau": 10207, "ahmed": 10208, "kicking": 10209, "mit": 10210, "treasurer": 10211, "1832": 10212, "biblical": 10213, "refuse": 10214, "terrified": 10215, "pump": 10216, "agrees": 10217, "genuine": 10218, "imprisonment": 10219, "refuses": 10220, "plymouth": 10221, "##hen": 10222, "lou": 10223, "##nen": 10224, "tara": 10225, "trembling": 10226, "antarctic": 10227, "ton": 10228, "learns": 10229, "##tas": 10230, "crap": 10231, "crucial": 10232, "faction": 10233, "atop": 10234, "##borough": 10235, "wrap": 10236, "lancaster": 10237, "odds": 10238, "hopkins": 10239, "erik": 10240, "lyon": 10241, "##eon": 10242, "bros": 10243, "##ode": 10244, "snap": 10245, "locality": 10246, "tips": 10247, "empress": 10248, "crowned": 10249, "cal": 10250, "acclaimed": 10251, "chuckled": 10252, "##ory": 10253, "clara": 10254, "sends": 10255, "mild": 10256, "towel": 10257, "##fl": 10258, "##day": 10259, "##а": 10260, "wishing": 10261, "assuming": 10262, "interviewed": 10263, "##bal": 10264, "##die": 10265, "interactions": 10266, "eden": 10267, "cups": 10268, "helena": 10269, "##lf": 10270, "indie": 10271, "beck": 10272, "##fire": 10273, "batteries": 10274, "filipino": 10275, "wizard": 10276, "parted": 10277, "##lam": 10278, "traces": 10279, "##born": 10280, "rows": 10281, "idol": 10282, "albany": 10283, "delegates": 10284, "##ees": 10285, "##sar": 10286, "discussions": 10287, "##ex": 10288, "notre": 10289, "instructed": 10290, "belgrade": 10291, "highways": 10292, "suggestion": 10293, "lauren": 10294, "possess": 10295, "orientation": 10296, "alexandria": 10297, "abdul": 10298, "beats": 10299, "salary": 10300, "reunion": 10301, "ludwig": 10302, "alright": 10303, "wagner": 10304, "intimate": 10305, "pockets": 10306, "slovenia": 10307, "hugged": 10308, "brighton": 10309, "merchants": 10310, "cruel": 10311, "stole": 10312, "trek": 10313, "slopes": 10314, "repairs": 10315, "enrollment": 10316, "politically": 10317, "underlying": 10318, "promotional": 10319, "counting": 10320, "boeing": 10321, "##bb": 10322, "isabella": 10323, "naming": 10324, "##и": 10325, "keen": 10326, "bacteria": 10327, "listing": 10328, "separately": 10329, "belfast": 10330, "ussr": 10331, "450": 10332, "lithuanian": 10333, "anybody": 10334, "ribs": 10335, "sphere": 10336, "martinez": 10337, "cock": 10338, "embarrassed": 10339, "proposals": 10340, "fragments": 10341, "nationals": 10342, "##fs": 10343, "##wski": 10344, "premises": 10345, "fin": 10346, "1500": 10347, "alpine": 10348, "matched": 10349, "freely": 10350, "bounded": 10351, "jace": 10352, "sleeve": 10353, "##af": 10354, "gaming": 10355, "pier": 10356, "populated": 10357, "evident": 10358, "##like": 10359, "frances": 10360, "flooded": 10361, "##dle": 10362, "frightened": 10363, "pour": 10364, "trainer": 10365, "framed": 10366, "visitor": 10367, "challenging": 10368, "pig": 10369, "wickets": 10370, "##fold": 10371, "infected": 10372, "email": 10373, "##pes": 10374, "arose": 10375, "##aw": 10376, "reward": 10377, "ecuador": 10378, "oblast": 10379, "vale": 10380, "ch": 10381, "shuttle": 10382, "##usa": 10383, "bach": 10384, "rankings": 10385, "forbidden": 10386, "cornwall": 10387, "accordance": 10388, "salem": 10389, "consumers": 10390, "bruno": 10391, "fantastic": 10392, "toes": 10393, "machinery": 10394, "resolved": 10395, "julius": 10396, "remembering": 10397, "propaganda": 10398, "iceland": 10399, "bombardment": 10400, "tide": 10401, "contacts": 10402, "wives": 10403, "##rah": 10404, "concerto": 10405, "macdonald": 10406, "albania": 10407, "implement": 10408, "daisy": 10409, "tapped": 10410, "sudan": 10411, "helmet": 10412, "angela": 10413, "mistress": 10414, "##lic": 10415, "crop": 10416, "sunk": 10417, "finest": 10418, "##craft": 10419, "hostile": 10420, "##ute": 10421, "##tsu": 10422, "boxer": 10423, "fr": 10424, "paths": 10425, "adjusted": 10426, "habit": 10427, "ballot": 10428, "supervision": 10429, "soprano": 10430, "##zen": 10431, "bullets": 10432, "wicked": 10433, "sunset": 10434, "regiments": 10435, "disappear": 10436, "lamp": 10437, "performs": 10438, "app": 10439, "##gia": 10440, "##oa": 10441, "rabbit": 10442, "digging": 10443, "incidents": 10444, "entries": 10445, "##cion": 10446, "dishes": 10447, "##oi": 10448, "introducing": 10449, "##ati": 10450, "##fied": 10451, "freshman": 10452, "slot": 10453, "jill": 10454, "tackles": 10455, "baroque": 10456, "backs": 10457, "##iest": 10458, "lone": 10459, "sponsor": 10460, "destiny": 10461, "altogether": 10462, "convert": 10463, "##aro": 10464, "consensus": 10465, "shapes": 10466, "demonstration": 10467, "basically": 10468, "feminist": 10469, "auction": 10470, "artifacts": 10471, "##bing": 10472, "strongest": 10473, "twitter": 10474, "halifax": 10475, "2019": 10476, "allmusic": 10477, "mighty": 10478, "smallest": 10479, "precise": 10480, "alexandra": 10481, "viola": 10482, "##los": 10483, "##ille": 10484, "manuscripts": 10485, "##illo": 10486, "dancers": 10487, "ari": 10488, "managers": 10489, "monuments": 10490, "blades": 10491, "barracks": 10492, "springfield": 10493, "maiden": 10494, "consolidated": 10495, "electron": 10496, "##end": 10497, "berry": 10498, "airing": 10499, "wheat": 10500, "nobel": 10501, "inclusion": 10502, "blair": 10503, "payments": 10504, "geography": 10505, "bee": 10506, "cc": 10507, "eleanor": 10508, "react": 10509, "##hurst": 10510, "afc": 10511, "manitoba": 10512, "##yu": 10513, "su": 10514, "lineup": 10515, "fitness": 10516, "recreational": 10517, "investments": 10518, "airborne": 10519, "disappointment": 10520, "##dis": 10521, "edmonton": 10522, "viewing": 10523, "##row": 10524, "renovation": 10525, "##cast": 10526, "infant": 10527, "bankruptcy": 10528, "roses": 10529, "aftermath": 10530, "pavilion": 10531, "##yer": 10532, "carpenter": 10533, "withdrawal": 10534, "ladder": 10535, "##hy": 10536, "discussing": 10537, "popped": 10538, "reliable": 10539, "agreements": 10540, "rochester": 10541, "##abad": 10542, "curves": 10543, "bombers": 10544, "220": 10545, "rao": 10546, "reverend": 10547, "decreased": 10548, "choosing": 10549, "107": 10550, "stiff": 10551, "consulting": 10552, "naples": 10553, "crawford": 10554, "tracy": 10555, "ka": 10556, "ribbon": 10557, "cops": 10558, "##lee": 10559, "crushed": 10560, "deciding": 10561, "unified": 10562, "teenager": 10563, "accepting": 10564, "flagship": 10565, "explorer": 10566, "poles": 10567, "sanchez": 10568, "inspection": 10569, "revived": 10570, "skilled": 10571, "induced": 10572, "exchanged": 10573, "flee": 10574, "locals": 10575, "tragedy": 10576, "swallow": 10577, "loading": 10578, "hanna": 10579, "demonstrate": 10580, "##ela": 10581, "salvador": 10582, "flown": 10583, "contestants": 10584, "civilization": 10585, "##ines": 10586, "wanna": 10587, "rhodes": 10588, "fletcher": 10589, "hector": 10590, "knocking": 10591, "considers": 10592, "##ough": 10593, "nash": 10594, "mechanisms": 10595, "sensed": 10596, "mentally": 10597, "walt": 10598, "unclear": 10599, "##eus": 10600, "renovated": 10601, "madame": 10602, "##cks": 10603, "crews": 10604, "governmental": 10605, "##hin": 10606, "undertaken": 10607, "monkey": 10608, "##ben": 10609, "##ato": 10610, "fatal": 10611, "armored": 10612, "copa": 10613, "caves": 10614, "governance": 10615, "grasp": 10616, "perception": 10617, "certification": 10618, "froze": 10619, "damp": 10620, "tugged": 10621, "wyoming": 10622, "##rg": 10623, "##ero": 10624, "newman": 10625, "##lor": 10626, "nerves": 10627, "curiosity": 10628, "graph": 10629, "115": 10630, "##ami": 10631, "withdraw": 10632, "tunnels": 10633, "dull": 10634, "meredith": 10635, "moss": 10636, "exhibits": 10637, "neighbors": 10638, "communicate": 10639, "accuracy": 10640, "explored": 10641, "raiders": 10642, "republicans": 10643, "secular": 10644, "kat": 10645, "superman": 10646, "penny": 10647, "criticised": 10648, "##tch": 10649, "freed": 10650, "update": 10651, "conviction": 10652, "wade": 10653, "ham": 10654, "likewise": 10655, "delegation": 10656, "gotta": 10657, "doll": 10658, "promises": 10659, "technological": 10660, "myth": 10661, "nationality": 10662, "resolve": 10663, "convent": 10664, "##mark": 10665, "sharon": 10666, "dig": 10667, "sip": 10668, "coordinator": 10669, "entrepreneur": 10670, "fold": 10671, "##dine": 10672, "capability": 10673, "councillor": 10674, "synonym": 10675, "blown": 10676, "swan": 10677, "cursed": 10678, "1815": 10679, "jonas": 10680, "haired": 10681, "sofa": 10682, "canvas": 10683, "keeper": 10684, "rivalry": 10685, "##hart": 10686, "rapper": 10687, "speedway": 10688, "swords": 10689, "postal": 10690, "maxwell": 10691, "estonia": 10692, "potter": 10693, "recurring": 10694, "##nn": 10695, "##ave": 10696, "errors": 10697, "##oni": 10698, "cognitive": 10699, "1834": 10700, "##²": 10701, "claws": 10702, "nadu": 10703, "roberto": 10704, "bce": 10705, "wrestler": 10706, "ellie": 10707, "##ations": 10708, "infinite": 10709, "ink": 10710, "##tia": 10711, "presumably": 10712, "finite": 10713, "staircase": 10714, "108": 10715, "noel": 10716, "patricia": 10717, "nacional": 10718, "##cation": 10719, "chill": 10720, "eternal": 10721, "tu": 10722, "preventing": 10723, "prussia": 10724, "fossil": 10725, "limbs": 10726, "##logist": 10727, "ernst": 10728, "frog": 10729, "perez": 10730, "rene": 10731, "##ace": 10732, "pizza": 10733, "prussian": 10734, "##ios": 10735, "##vy": 10736, "molecules": 10737, "regulatory": 10738, "answering": 10739, "opinions": 10740, "sworn": 10741, "lengths": 10742, "supposedly": 10743, "hypothesis": 10744, "upward": 10745, "habitats": 10746, "seating": 10747, "ancestors": 10748, "drank": 10749, "yield": 10750, "hd": 10751, "synthesis": 10752, "researcher": 10753, "modest": 10754, "##var": 10755, "mothers": 10756, "peered": 10757, "voluntary": 10758, "homeland": 10759, "##the": 10760, "acclaim": 10761, "##igan": 10762, "static": 10763, "valve": 10764, "luxembourg": 10765, "alto": 10766, "carroll": 10767, "fe": 10768, "receptor": 10769, "norton": 10770, "ambulance": 10771, "##tian": 10772, "johnston": 10773, "catholics": 10774, "depicting": 10775, "jointly": 10776, "elephant": 10777, "gloria": 10778, "mentor": 10779, "badge": 10780, "ahmad": 10781, "distinguish": 10782, "remarked": 10783, "councils": 10784, "precisely": 10785, "allison": 10786, "advancing": 10787, "detection": 10788, "crowded": 10789, "##10": 10790, "cooperative": 10791, "ankle": 10792, "mercedes": 10793, "dagger": 10794, "surrendered": 10795, "pollution": 10796, "commit": 10797, "subway": 10798, "jeffrey": 10799, "lesson": 10800, "sculptures": 10801, "provider": 10802, "##fication": 10803, "membrane": 10804, "timothy": 10805, "rectangular": 10806, "fiscal": 10807, "heating": 10808, "teammate": 10809, "basket": 10810, "particle": 10811, "anonymous": 10812, "deployment": 10813, "##ple": 10814, "missiles": 10815, "courthouse": 10816, "proportion": 10817, "shoe": 10818, "sec": 10819, "##ller": 10820, "complaints": 10821, "forbes": 10822, "blacks": 10823, "abandon": 10824, "remind": 10825, "sizes": 10826, "overwhelming": 10827, "autobiography": 10828, "natalie": 10829, "##awa": 10830, "risks": 10831, "contestant": 10832, "countryside": 10833, "babies": 10834, "scorer": 10835, "invaded": 10836, "enclosed": 10837, "proceed": 10838, "hurling": 10839, "disorders": 10840, "##cu": 10841, "reflecting": 10842, "continuously": 10843, "cruiser": 10844, "graduates": 10845, "freeway": 10846, "investigated": 10847, "ore": 10848, "deserved": 10849, "maid": 10850, "blocking": 10851, "phillip": 10852, "jorge": 10853, "shakes": 10854, "dove": 10855, "mann": 10856, "variables": 10857, "lacked": 10858, "burden": 10859, "accompanying": 10860, "que": 10861, "consistently": 10862, "organizing": 10863, "provisional": 10864, "complained": 10865, "endless": 10866, "##rm": 10867, "tubes": 10868, "juice": 10869, "georges": 10870, "krishna": 10871, "mick": 10872, "labels": 10873, "thriller": 10874, "##uch": 10875, "laps": 10876, "arcade": 10877, "sage": 10878, "snail": 10879, "##table": 10880, "shannon": 10881, "fi": 10882, "laurence": 10883, "seoul": 10884, "vacation": 10885, "presenting": 10886, "hire": 10887, "churchill": 10888, "surprisingly": 10889, "prohibited": 10890, "savannah": 10891, "technically": 10892, "##oli": 10893, "170": 10894, "##lessly": 10895, "testimony": 10896, "suited": 10897, "speeds": 10898, "toys": 10899, "romans": 10900, "mlb": 10901, "flowering": 10902, "measurement": 10903, "talented": 10904, "kay": 10905, "settings": 10906, "charleston": 10907, "expectations": 10908, "shattered": 10909, "achieving": 10910, "triumph": 10911, "ceremonies": 10912, "portsmouth": 10913, "lanes": 10914, "mandatory": 10915, "loser": 10916, "stretching": 10917, "cologne": 10918, "realizes": 10919, "seventy": 10920, "cornell": 10921, "careers": 10922, "webb": 10923, "##ulating": 10924, "americas": 10925, "budapest": 10926, "ava": 10927, "suspicion": 10928, "##ison": 10929, "yo": 10930, "conrad": 10931, "##hai": 10932, "sterling": 10933, "jessie": 10934, "rector": 10935, "##az": 10936, "1831": 10937, "transform": 10938, "organize": 10939, "loans": 10940, "christine": 10941, "volcanic": 10942, "warrant": 10943, "slender": 10944, "summers": 10945, "subfamily": 10946, "newer": 10947, "danced": 10948, "dynamics": 10949, "rhine": 10950, "proceeds": 10951, "heinrich": 10952, "gastropod": 10953, "commands": 10954, "sings": 10955, "facilitate": 10956, "easter": 10957, "ra": 10958, "positioned": 10959, "responses": 10960, "expense": 10961, "fruits": 10962, "yanked": 10963, "imported": 10964, "25th": 10965, "velvet": 10966, "vic": 10967, "primitive": 10968, "tribune": 10969, "baldwin": 10970, "neighbourhood": 10971, "donna": 10972, "rip": 10973, "hay": 10974, "pr": 10975, "##uro": 10976, "1814": 10977, "espn": 10978, "welcomed": 10979, "##aria": 10980, "qualifier": 10981, "glare": 10982, "highland": 10983, "timing": 10984, "##cted": 10985, "shells": 10986, "eased": 10987, "geometry": 10988, "louder": 10989, "exciting": 10990, "slovakia": 10991, "##sion": 10992, "##iz": 10993, "##lot": 10994, "savings": 10995, "prairie": 10996, "##ques": 10997, "marching": 10998, "rafael": 10999, "tonnes": 11000, "##lled": 11001, "curtain": 11002, "preceding": 11003, "shy": 11004, "heal": 11005, "greene": 11006, "worthy": 11007, "##pot": 11008, "detachment": 11009, "bury": 11010, "sherman": 11011, "##eck": 11012, "reinforced": 11013, "seeks": 11014, "bottles": 11015, "contracted": 11016, "duchess": 11017, "outfit": 11018, "walsh": 11019, "##sc": 11020, "mickey": 11021, "##ase": 11022, "geoffrey": 11023, "archer": 11024, "squeeze": 11025, "dawson": 11026, "eliminate": 11027, "invention": 11028, "##enberg": 11029, "neal": 11030, "##eth": 11031, "stance": 11032, "dealer": 11033, "coral": 11034, "maple": 11035, "retire": 11036, "polo": 11037, "simplified": 11038, "##ht": 11039, "1833": 11040, "hid": 11041, "watts": 11042, "backwards": 11043, "jules": 11044, "##oke": 11045, "genesis": 11046, "mt": 11047, "frames": 11048, "rebounds": 11049, "burma": 11050, "woodland": 11051, "moist": 11052, "santos": 11053, "whispers": 11054, "drained": 11055, "subspecies": 11056, "##aa": 11057, "streaming": 11058, "ulster": 11059, "burnt": 11060, "correspondence": 11061, "maternal": 11062, "gerard": 11063, "denis": 11064, "stealing": 11065, "##load": 11066, "genius": 11067, "duchy": 11068, "##oria": 11069, "inaugurated": 11070, "momentum": 11071, "suits": 11072, "placement": 11073, "sovereign": 11074, "clause": 11075, "thames": 11076, "##hara": 11077, "confederation": 11078, "reservation": 11079, "sketch": 11080, "yankees": 11081, "lets": 11082, "rotten": 11083, "charm": 11084, "hal": 11085, "verses": 11086, "ultra": 11087, "commercially": 11088, "dot": 11089, "salon": 11090, "citation": 11091, "adopt": 11092, "winnipeg": 11093, "mist": 11094, "allocated": 11095, "cairo": 11096, "##boy": 11097, "jenkins": 11098, "interference": 11099, "objectives": 11100, "##wind": 11101, "1820": 11102, "portfolio": 11103, "armoured": 11104, "sectors": 11105, "##eh": 11106, "initiatives": 11107, "##world": 11108, "integrity": 11109, "exercises": 11110, "robe": 11111, "tap": 11112, "ab": 11113, "gazed": 11114, "##tones": 11115, "distracted": 11116, "rulers": 11117, "111": 11118, "favorable": 11119, "jerome": 11120, "tended": 11121, "cart": 11122, "factories": 11123, "##eri": 11124, "diplomat": 11125, "valued": 11126, "gravel": 11127, "charitable": 11128, "##try": 11129, "calvin": 11130, "exploring": 11131, "chang": 11132, "shepherd": 11133, "terrace": 11134, "pdf": 11135, "pupil": 11136, "##ural": 11137, "reflects": 11138, "ups": 11139, "##rch": 11140, "governors": 11141, "shelf": 11142, "depths": 11143, "##nberg": 11144, "trailed": 11145, "crest": 11146, "tackle": 11147, "##nian": 11148, "##ats": 11149, "hatred": 11150, "##kai": 11151, "clare": 11152, "makers": 11153, "ethiopia": 11154, "longtime": 11155, "detected": 11156, "embedded": 11157, "lacking": 11158, "slapped": 11159, "rely": 11160, "thomson": 11161, "anticipation": 11162, "iso": 11163, "morton": 11164, "successive": 11165, "agnes": 11166, "screenwriter": 11167, "straightened": 11168, "philippe": 11169, "playwright": 11170, "haunted": 11171, "licence": 11172, "iris": 11173, "intentions": 11174, "sutton": 11175, "112": 11176, "logical": 11177, "correctly": 11178, "##weight": 11179, "branded": 11180, "licked": 11181, "tipped": 11182, "silva": 11183, "ricky": 11184, "narrator": 11185, "requests": 11186, "##ents": 11187, "greeted": 11188, "supernatural": 11189, "cow": 11190, "##wald": 11191, "lung": 11192, "refusing": 11193, "employer": 11194, "strait": 11195, "gaelic": 11196, "liner": 11197, "##piece": 11198, "zoe": 11199, "sabha": 11200, "##mba": 11201, "driveway": 11202, "harvest": 11203, "prints": 11204, "bates": 11205, "reluctantly": 11206, "threshold": 11207, "algebra": 11208, "ira": 11209, "wherever": 11210, "coupled": 11211, "240": 11212, "assumption": 11213, "picks": 11214, "##air": 11215, "designers": 11216, "raids": 11217, "gentlemen": 11218, "##ean": 11219, "roller": 11220, "blowing": 11221, "leipzig": 11222, "locks": 11223, "screw": 11224, "dressing": 11225, "strand": 11226, "##lings": 11227, "scar": 11228, "dwarf": 11229, "depicts": 11230, "##nu": 11231, "nods": 11232, "##mine": 11233, "differ": 11234, "boris": 11235, "##eur": 11236, "yuan": 11237, "flip": 11238, "##gie": 11239, "mob": 11240, "invested": 11241, "questioning": 11242, "applying": 11243, "##ture": 11244, "shout": 11245, "##sel": 11246, "gameplay": 11247, "blamed": 11248, "illustrations": 11249, "bothered": 11250, "weakness": 11251, "rehabilitation": 11252, "##of": 11253, "##zes": 11254, "envelope": 11255, "rumors": 11256, "miners": 11257, "leicester": 11258, "subtle": 11259, "kerry": 11260, "##ico": 11261, "ferguson": 11262, "##fu": 11263, "premiership": 11264, "ne": 11265, "##cat": 11266, "bengali": 11267, "prof": 11268, "catches": 11269, "remnants": 11270, "dana": 11271, "##rily": 11272, "shouting": 11273, "presidents": 11274, "baltic": 11275, "ought": 11276, "ghosts": 11277, "dances": 11278, "sailors": 11279, "shirley": 11280, "fancy": 11281, "dominic": 11282, "##bie": 11283, "madonna": 11284, "##rick": 11285, "bark": 11286, "buttons": 11287, "gymnasium": 11288, "ashes": 11289, "liver": 11290, "toby": 11291, "oath": 11292, "providence": 11293, "doyle": 11294, "evangelical": 11295, "nixon": 11296, "cement": 11297, "carnegie": 11298, "embarked": 11299, "hatch": 11300, "surroundings": 11301, "guarantee": 11302, "needing": 11303, "pirate": 11304, "essence": 11305, "##bee": 11306, "filter": 11307, "crane": 11308, "hammond": 11309, "projected": 11310, "immune": 11311, "percy": 11312, "twelfth": 11313, "##ult": 11314, "regent": 11315, "doctoral": 11316, "damon": 11317, "mikhail": 11318, "##ichi": 11319, "lu": 11320, "critically": 11321, "elect": 11322, "realised": 11323, "abortion": 11324, "acute": 11325, "screening": 11326, "mythology": 11327, "steadily": 11328, "##fc": 11329, "frown": 11330, "nottingham": 11331, "kirk": 11332, "wa": 11333, "minneapolis": 11334, "##rra": 11335, "module": 11336, "algeria": 11337, "mc": 11338, "nautical": 11339, "encounters": 11340, "surprising": 11341, "statues": 11342, "availability": 11343, "shirts": 11344, "pie": 11345, "alma": 11346, "brows": 11347, "munster": 11348, "mack": 11349, "soup": 11350, "crater": 11351, "tornado": 11352, "sanskrit": 11353, "cedar": 11354, "explosive": 11355, "bordered": 11356, "dixon": 11357, "planets": 11358, "stamp": 11359, "exam": 11360, "happily": 11361, "##bble": 11362, "carriers": 11363, "kidnapped": 11364, "##vis": 11365, "accommodation": 11366, "emigrated": 11367, "##met": 11368, "knockout": 11369, "correspondent": 11370, "violation": 11371, "profits": 11372, "peaks": 11373, "lang": 11374, "specimen": 11375, "agenda": 11376, "ancestry": 11377, "pottery": 11378, "spelling": 11379, "equations": 11380, "obtaining": 11381, "ki": 11382, "linking": 11383, "1825": 11384, "debris": 11385, "asylum": 11386, "##20": 11387, "buddhism": 11388, "teddy": 11389, "##ants": 11390, "gazette": 11391, "##nger": 11392, "##sse": 11393, "dental": 11394, "eligibility": 11395, "utc": 11396, "fathers": 11397, "averaged": 11398, "zimbabwe": 11399, "francesco": 11400, "coloured": 11401, "hissed": 11402, "translator": 11403, "lynch": 11404, "mandate": 11405, "humanities": 11406, "mackenzie": 11407, "uniforms": 11408, "lin": 11409, "##iana": 11410, "##gio": 11411, "asset": 11412, "mhz": 11413, "fitting": 11414, "samantha": 11415, "genera": 11416, "wei": 11417, "rim": 11418, "beloved": 11419, "shark": 11420, "riot": 11421, "entities": 11422, "expressions": 11423, "indo": 11424, "carmen": 11425, "slipping": 11426, "owing": 11427, "abbot": 11428, "neighbor": 11429, "sidney": 11430, "##av": 11431, "rats": 11432, "recommendations": 11433, "encouraging": 11434, "squadrons": 11435, "anticipated": 11436, "commanders": 11437, "conquered": 11438, "##oto": 11439, "donations": 11440, "diagnosed": 11441, "##mond": 11442, "divide": 11443, "##iva": 11444, "guessed": 11445, "decoration": 11446, "vernon": 11447, "auditorium": 11448, "revelation": 11449, "conversations": 11450, "##kers": 11451, "##power": 11452, "herzegovina": 11453, "dash": 11454, "alike": 11455, "protested": 11456, "lateral": 11457, "herman": 11458, "accredited": 11459, "mg": 11460, "##gent": 11461, "freeman": 11462, "mel": 11463, "fiji": 11464, "crow": 11465, "crimson": 11466, "##rine": 11467, "livestock": 11468, "##pped": 11469, "humanitarian": 11470, "bored": 11471, "oz": 11472, "whip": 11473, "##lene": 11474, "##ali": 11475, "legitimate": 11476, "alter": 11477, "grinning": 11478, "spelled": 11479, "anxious": 11480, "oriental": 11481, "wesley": 11482, "##nin": 11483, "##hole": 11484, "carnival": 11485, "controller": 11486, "detect": 11487, "##ssa": 11488, "bowed": 11489, "educator": 11490, "kosovo": 11491, "macedonia": 11492, "##sin": 11493, "occupy": 11494, "mastering": 11495, "stephanie": 11496, "janeiro": 11497, "para": 11498, "unaware": 11499, "nurses": 11500, "noon": 11501, "135": 11502, "cam": 11503, "hopefully": 11504, "ranger": 11505, "combine": 11506, "sociology": 11507, "polar": 11508, "rica": 11509, "##eer": 11510, "neill": 11511, "##sman": 11512, "holocaust": 11513, "##ip": 11514, "doubled": 11515, "lust": 11516, "1828": 11517, "109": 11518, "decent": 11519, "cooling": 11520, "unveiled": 11521, "##card": 11522, "1829": 11523, "nsw": 11524, "homer": 11525, "chapman": 11526, "meyer": 11527, "##gin": 11528, "dive": 11529, "mae": 11530, "reagan": 11531, "expertise": 11532, "##gled": 11533, "darwin": 11534, "brooke": 11535, "sided": 11536, "prosecution": 11537, "investigating": 11538, "comprised": 11539, "petroleum": 11540, "genres": 11541, "reluctant": 11542, "differently": 11543, "trilogy": 11544, "johns": 11545, "vegetables": 11546, "corpse": 11547, "highlighted": 11548, "lounge": 11549, "pension": 11550, "unsuccessfully": 11551, "elegant": 11552, "aided": 11553, "ivory": 11554, "beatles": 11555, "amelia": 11556, "cain": 11557, "dubai": 11558, "sunny": 11559, "immigrant": 11560, "babe": 11561, "click": 11562, "##nder": 11563, "underwater": 11564, "pepper": 11565, "combining": 11566, "mumbled": 11567, "atlas": 11568, "horns": 11569, "accessed": 11570, "ballad": 11571, "physicians": 11572, "homeless": 11573, "gestured": 11574, "rpm": 11575, "freak": 11576, "louisville": 11577, "corporations": 11578, "patriots": 11579, "prizes": 11580, "rational": 11581, "warn": 11582, "modes": 11583, "decorative": 11584, "overnight": 11585, "din": 11586, "troubled": 11587, "phantom": 11588, "##ort": 11589, "monarch": 11590, "sheer": 11591, "##dorf": 11592, "generals": 11593, "guidelines": 11594, "organs": 11595, "addresses": 11596, "##zon": 11597, "enhance": 11598, "curling": 11599, "parishes": 11600, "cord": 11601, "##kie": 11602, "linux": 11603, "caesar": 11604, "deutsche": 11605, "bavaria": 11606, "##bia": 11607, "coleman": 11608, "cyclone": 11609, "##eria": 11610, "bacon": 11611, "petty": 11612, "##yama": 11613, "##old": 11614, "hampton": 11615, "diagnosis": 11616, "1824": 11617, "throws": 11618, "complexity": 11619, "rita": 11620, "disputed": 11621, "##₃": 11622, "pablo": 11623, "##sch": 11624, "marketed": 11625, "trafficking": 11626, "##ulus": 11627, "examine": 11628, "plague": 11629, "formats": 11630, "##oh": 11631, "vault": 11632, "faithful": 11633, "##bourne": 11634, "webster": 11635, "##ox": 11636, "highlights": 11637, "##ient": 11638, "##ann": 11639, "phones": 11640, "vacuum": 11641, "sandwich": 11642, "modeling": 11643, "##gated": 11644, "bolivia": 11645, "clergy": 11646, "qualities": 11647, "isabel": 11648, "##nas": 11649, "##ars": 11650, "wears": 11651, "screams": 11652, "reunited": 11653, "annoyed": 11654, "bra": 11655, "##ancy": 11656, "##rate": 11657, "differential": 11658, "transmitter": 11659, "tattoo": 11660, "container": 11661, "poker": 11662, "##och": 11663, "excessive": 11664, "resides": 11665, "cowboys": 11666, "##tum": 11667, "augustus": 11668, "trash": 11669, "providers": 11670, "statute": 11671, "retreated": 11672, "balcony": 11673, "reversed": 11674, "void": 11675, "storey": 11676, "preceded": 11677, "masses": 11678, "leap": 11679, "laughs": 11680, "neighborhoods": 11681, "wards": 11682, "schemes": 11683, "falcon": 11684, "santo": 11685, "battlefield": 11686, "pad": 11687, "ronnie": 11688, "thread": 11689, "lesbian": 11690, "venus": 11691, "##dian": 11692, "beg": 11693, "sandstone": 11694, "daylight": 11695, "punched": 11696, "gwen": 11697, "analog": 11698, "stroked": 11699, "wwe": 11700, "acceptable": 11701, "measurements": 11702, "dec": 11703, "toxic": 11704, "##kel": 11705, "adequate": 11706, "surgical": 11707, "economist": 11708, "parameters": 11709, "varsity": 11710, "##sberg": 11711, "quantity": 11712, "ella": 11713, "##chy": 11714, "##rton": 11715, "countess": 11716, "generating": 11717, "precision": 11718, "diamonds": 11719, "expressway": 11720, "ga": 11721, "##ı": 11722, "1821": 11723, "uruguay": 11724, "talents": 11725, "galleries": 11726, "expenses": 11727, "scanned": 11728, "colleague": 11729, "outlets": 11730, "ryder": 11731, "lucien": 11732, "##ila": 11733, "paramount": 11734, "##bon": 11735, "syracuse": 11736, "dim": 11737, "fangs": 11738, "gown": 11739, "sweep": 11740, "##sie": 11741, "toyota": 11742, "missionaries": 11743, "websites": 11744, "##nsis": 11745, "sentences": 11746, "adviser": 11747, "val": 11748, "trademark": 11749, "spells": 11750, "##plane": 11751, "patience": 11752, "starter": 11753, "slim": 11754, "##borg": 11755, "toe": 11756, "incredibly": 11757, "shoots": 11758, "elliot": 11759, "nobility": 11760, "##wyn": 11761, "cowboy": 11762, "endorsed": 11763, "gardner": 11764, "tendency": 11765, "persuaded": 11766, "organisms": 11767, "emissions": 11768, "kazakhstan": 11769, "amused": 11770, "boring": 11771, "chips": 11772, "themed": 11773, "##hand": 11774, "llc": 11775, "constantinople": 11776, "chasing": 11777, "systematic": 11778, "guatemala": 11779, "borrowed": 11780, "erin": 11781, "carey": 11782, "##hard": 11783, "highlands": 11784, "struggles": 11785, "1810": 11786, "##ifying": 11787, "##ced": 11788, "wong": 11789, "exceptions": 11790, "develops": 11791, "enlarged": 11792, "kindergarten": 11793, "castro": 11794, "##ern": 11795, "##rina": 11796, "leigh": 11797, "zombie": 11798, "juvenile": 11799, "##most": 11800, "consul": 11801, "##nar": 11802, "sailor": 11803, "hyde": 11804, "clarence": 11805, "intensive": 11806, "pinned": 11807, "nasty": 11808, "useless": 11809, "jung": 11810, "clayton": 11811, "stuffed": 11812, "exceptional": 11813, "ix": 11814, "apostolic": 11815, "230": 11816, "transactions": 11817, "##dge": 11818, "exempt": 11819, "swinging": 11820, "cove": 11821, "religions": 11822, "##ash": 11823, "shields": 11824, "dairy": 11825, "bypass": 11826, "190": 11827, "pursuing": 11828, "bug": 11829, "joyce": 11830, "bombay": 11831, "chassis": 11832, "southampton": 11833, "chat": 11834, "interact": 11835, "redesignated": 11836, "##pen": 11837, "nascar": 11838, "pray": 11839, "salmon": 11840, "rigid": 11841, "regained": 11842, "malaysian": 11843, "grim": 11844, "publicity": 11845, "constituted": 11846, "capturing": 11847, "toilet": 11848, "delegate": 11849, "purely": 11850, "tray": 11851, "drift": 11852, "loosely": 11853, "striker": 11854, "weakened": 11855, "trinidad": 11856, "mitch": 11857, "itv": 11858, "defines": 11859, "transmitted": 11860, "ming": 11861, "scarlet": 11862, "nodding": 11863, "fitzgerald": 11864, "fu": 11865, "narrowly": 11866, "sp": 11867, "tooth": 11868, "standings": 11869, "virtue": 11870, "##₁": 11871, "##wara": 11872, "##cting": 11873, "chateau": 11874, "gloves": 11875, "lid": 11876, "##nel": 11877, "hurting": 11878, "conservatory": 11879, "##pel": 11880, "sinclair": 11881, "reopened": 11882, "sympathy": 11883, "nigerian": 11884, "strode": 11885, "advocated": 11886, "optional": 11887, "chronic": 11888, "discharge": 11889, "##rc": 11890, "suck": 11891, "compatible": 11892, "laurel": 11893, "stella": 11894, "shi": 11895, "fails": 11896, "wage": 11897, "dodge": 11898, "128": 11899, "informal": 11900, "sorts": 11901, "levi": 11902, "buddha": 11903, "villagers": 11904, "##aka": 11905, "chronicles": 11906, "heavier": 11907, "summoned": 11908, "gateway": 11909, "3000": 11910, "eleventh": 11911, "jewelry": 11912, "translations": 11913, "accordingly": 11914, "seas": 11915, "##ency": 11916, "fiber": 11917, "pyramid": 11918, "cubic": 11919, "dragging": 11920, "##ista": 11921, "caring": 11922, "##ops": 11923, "android": 11924, "contacted": 11925, "lunar": 11926, "##dt": 11927, "kai": 11928, "lisbon": 11929, "patted": 11930, "1826": 11931, "sacramento": 11932, "theft": 11933, "madagascar": 11934, "subtropical": 11935, "disputes": 11936, "ta": 11937, "holidays": 11938, "piper": 11939, "willow": 11940, "mare": 11941, "cane": 11942, "itunes": 11943, "newfoundland": 11944, "benny": 11945, "companions": 11946, "dong": 11947, "raj": 11948, "observe": 11949, "roar": 11950, "charming": 11951, "plaque": 11952, "tibetan": 11953, "fossils": 11954, "enacted": 11955, "manning": 11956, "bubble": 11957, "tina": 11958, "tanzania": 11959, "##eda": 11960, "##hir": 11961, "funk": 11962, "swamp": 11963, "deputies": 11964, "cloak": 11965, "ufc": 11966, "scenario": 11967, "par": 11968, "scratch": 11969, "metals": 11970, "anthem": 11971, "guru": 11972, "engaging": 11973, "specially": 11974, "##boat": 11975, "dialects": 11976, "nineteen": 11977, "cecil": 11978, "duet": 11979, "disability": 11980, "messenger": 11981, "unofficial": 11982, "##lies": 11983, "defunct": 11984, "eds": 11985, "moonlight": 11986, "drainage": 11987, "surname": 11988, "puzzle": 11989, "honda": 11990, "switching": 11991, "conservatives": 11992, "mammals": 11993, "knox": 11994, "broadcaster": 11995, "sidewalk": 11996, "cope": 11997, "##ried": 11998, "benson": 11999, "princes": 12000, "peterson": 12001, "##sal": 12002, "bedford": 12003, "sharks": 12004, "eli": 12005, "wreck": 12006, "alberto": 12007, "gasp": 12008, "archaeology": 12009, "lgbt": 12010, "teaches": 12011, "securities": 12012, "madness": 12013, "compromise": 12014, "waving": 12015, "coordination": 12016, "davidson": 12017, "visions": 12018, "leased": 12019, "possibilities": 12020, "eighty": 12021, "jun": 12022, "fernandez": 12023, "enthusiasm": 12024, "assassin": 12025, "sponsorship": 12026, "reviewer": 12027, "kingdoms": 12028, "estonian": 12029, "laboratories": 12030, "##fy": 12031, "##nal": 12032, "applies": 12033, "verb": 12034, "celebrations": 12035, "##zzo": 12036, "rowing": 12037, "lightweight": 12038, "sadness": 12039, "submit": 12040, "mvp": 12041, "balanced": 12042, "dude": 12043, "##vas": 12044, "explicitly": 12045, "metric": 12046, "magnificent": 12047, "mound": 12048, "brett": 12049, "mohammad": 12050, "mistakes": 12051, "irregular": 12052, "##hing": 12053, "##ass": 12054, "sanders": 12055, "betrayed": 12056, "shipped": 12057, "surge": 12058, "##enburg": 12059, "reporters": 12060, "termed": 12061, "georg": 12062, "pity": 12063, "verbal": 12064, "bulls": 12065, "abbreviated": 12066, "enabling": 12067, "appealed": 12068, "##are": 12069, "##atic": 12070, "sicily": 12071, "sting": 12072, "heel": 12073, "sweetheart": 12074, "bart": 12075, "spacecraft": 12076, "brutal": 12077, "monarchy": 12078, "##tter": 12079, "aberdeen": 12080, "cameo": 12081, "diane": 12082, "##ub": 12083, "survivor": 12084, "clyde": 12085, "##aries": 12086, "complaint": 12087, "##makers": 12088, "clarinet": 12089, "delicious": 12090, "chilean": 12091, "karnataka": 12092, "coordinates": 12093, "1818": 12094, "panties": 12095, "##rst": 12096, "pretending": 12097, "ar": 12098, "dramatically": 12099, "kiev": 12100, "bella": 12101, "tends": 12102, "distances": 12103, "113": 12104, "catalog": 12105, "launching": 12106, "instances": 12107, "telecommunications": 12108, "portable": 12109, "lindsay": 12110, "vatican": 12111, "##eim": 12112, "angles": 12113, "aliens": 12114, "marker": 12115, "stint": 12116, "screens": 12117, "bolton": 12118, "##rne": 12119, "judy": 12120, "wool": 12121, "benedict": 12122, "plasma": 12123, "europa": 12124, "spark": 12125, "imaging": 12126, "filmmaker": 12127, "swiftly": 12128, "##een": 12129, "contributor": 12130, "##nor": 12131, "opted": 12132, "stamps": 12133, "apologize": 12134, "financing": 12135, "butter": 12136, "gideon": 12137, "sophisticated": 12138, "alignment": 12139, "avery": 12140, "chemicals": 12141, "yearly": 12142, "speculation": 12143, "prominence": 12144, "professionally": 12145, "##ils": 12146, "immortal": 12147, "institutional": 12148, "inception": 12149, "wrists": 12150, "identifying": 12151, "tribunal": 12152, "derives": 12153, "gains": 12154, "##wo": 12155, "papal": 12156, "preference": 12157, "linguistic": 12158, "vince": 12159, "operative": 12160, "brewery": 12161, "##ont": 12162, "unemployment": 12163, "boyd": 12164, "##ured": 12165, "##outs": 12166, "albeit": 12167, "prophet": 12168, "1813": 12169, "bi": 12170, "##rr": 12171, "##face": 12172, "##rad": 12173, "quarterly": 12174, "asteroid": 12175, "cleaned": 12176, "radius": 12177, "temper": 12178, "##llen": 12179, "telugu": 12180, "jerk": 12181, "viscount": 12182, "menu": 12183, "##ote": 12184, "glimpse": 12185, "##aya": 12186, "yacht": 12187, "hawaiian": 12188, "baden": 12189, "##rl": 12190, "laptop": 12191, "readily": 12192, "##gu": 12193, "monetary": 12194, "offshore": 12195, "scots": 12196, "watches": 12197, "##yang": 12198, "##arian": 12199, "upgrade": 12200, "needle": 12201, "xbox": 12202, "lea": 12203, "encyclopedia": 12204, "flank": 12205, "fingertips": 12206, "##pus": 12207, "delight": 12208, "teachings": 12209, "confirm": 12210, "roth": 12211, "beaches": 12212, "midway": 12213, "winters": 12214, "##iah": 12215, "teasing": 12216, "daytime": 12217, "beverly": 12218, "gambling": 12219, "bonnie": 12220, "##backs": 12221, "regulated": 12222, "clement": 12223, "hermann": 12224, "tricks": 12225, "knot": 12226, "##shing": 12227, "##uring": 12228, "##vre": 12229, "detached": 12230, "ecological": 12231, "owed": 12232, "specialty": 12233, "byron": 12234, "inventor": 12235, "bats": 12236, "stays": 12237, "screened": 12238, "unesco": 12239, "midland": 12240, "trim": 12241, "affection": 12242, "##ander": 12243, "##rry": 12244, "jess": 12245, "thoroughly": 12246, "feedback": 12247, "##uma": 12248, "chennai": 12249, "strained": 12250, "heartbeat": 12251, "wrapping": 12252, "overtime": 12253, "pleaded": 12254, "##sworth": 12255, "mon": 12256, "leisure": 12257, "oclc": 12258, "##tate": 12259, "##ele": 12260, "feathers": 12261, "angelo": 12262, "thirds": 12263, "nuts": 12264, "surveys": 12265, "clever": 12266, "gill": 12267, "commentator": 12268, "##dos": 12269, "darren": 12270, "rides": 12271, "gibraltar": 12272, "##nc": 12273, "##mu": 12274, "dissolution": 12275, "dedication": 12276, "shin": 12277, "meals": 12278, "saddle": 12279, "elvis": 12280, "reds": 12281, "chaired": 12282, "taller": 12283, "appreciation": 12284, "functioning": 12285, "niece": 12286, "favored": 12287, "advocacy": 12288, "robbie": 12289, "criminals": 12290, "suffolk": 12291, "yugoslav": 12292, "passport": 12293, "constable": 12294, "congressman": 12295, "hastings": 12296, "vera": 12297, "##rov": 12298, "consecrated": 12299, "sparks": 12300, "ecclesiastical": 12301, "confined": 12302, "##ovich": 12303, "muller": 12304, "floyd": 12305, "nora": 12306, "1822": 12307, "paved": 12308, "1827": 12309, "cumberland": 12310, "ned": 12311, "saga": 12312, "spiral": 12313, "##flow": 12314, "appreciated": 12315, "yi": 12316, "collaborative": 12317, "treating": 12318, "similarities": 12319, "feminine": 12320, "finishes": 12321, "##ib": 12322, "jade": 12323, "import": 12324, "##nse": 12325, "##hot": 12326, "champagne": 12327, "mice": 12328, "securing": 12329, "celebrities": 12330, "helsinki": 12331, "attributes": 12332, "##gos": 12333, "cousins": 12334, "phases": 12335, "ache": 12336, "lucia": 12337, "gandhi": 12338, "submission": 12339, "vicar": 12340, "spear": 12341, "shine": 12342, "tasmania": 12343, "biting": 12344, "detention": 12345, "constitute": 12346, "tighter": 12347, "seasonal": 12348, "##gus": 12349, "terrestrial": 12350, "matthews": 12351, "##oka": 12352, "effectiveness": 12353, "parody": 12354, "philharmonic": 12355, "##onic": 12356, "1816": 12357, "strangers": 12358, "encoded": 12359, "consortium": 12360, "guaranteed": 12361, "regards": 12362, "shifts": 12363, "tortured": 12364, "collision": 12365, "supervisor": 12366, "inform": 12367, "broader": 12368, "insight": 12369, "theaters": 12370, "armour": 12371, "emeritus": 12372, "blink": 12373, "incorporates": 12374, "mapping": 12375, "##50": 12376, "##ein": 12377, "handball": 12378, "flexible": 12379, "##nta": 12380, "substantially": 12381, "generous": 12382, "thief": 12383, "##own": 12384, "carr": 12385, "loses": 12386, "1793": 12387, "prose": 12388, "ucla": 12389, "romeo": 12390, "generic": 12391, "metallic": 12392, "realization": 12393, "damages": 12394, "mk": 12395, "commissioners": 12396, "zach": 12397, "default": 12398, "##ther": 12399, "helicopters": 12400, "lengthy": 12401, "stems": 12402, "spa": 12403, "partnered": 12404, "spectators": 12405, "rogue": 12406, "indication": 12407, "penalties": 12408, "teresa": 12409, "1801": 12410, "sen": 12411, "##tric": 12412, "dalton": 12413, "##wich": 12414, "irving": 12415, "photographic": 12416, "##vey": 12417, "dell": 12418, "deaf": 12419, "peters": 12420, "excluded": 12421, "unsure": 12422, "##vable": 12423, "patterson": 12424, "crawled": 12425, "##zio": 12426, "resided": 12427, "whipped": 12428, "latvia": 12429, "slower": 12430, "ecole": 12431, "pipes": 12432, "employers": 12433, "maharashtra": 12434, "comparable": 12435, "va": 12436, "textile": 12437, "pageant": 12438, "##gel": 12439, "alphabet": 12440, "binary": 12441, "irrigation": 12442, "chartered": 12443, "choked": 12444, "antoine": 12445, "offs": 12446, "waking": 12447, "supplement": 12448, "##wen": 12449, "quantities": 12450, "demolition": 12451, "regain": 12452, "locate": 12453, "urdu": 12454, "folks": 12455, "alt": 12456, "114": 12457, "##mc": 12458, "scary": 12459, "andreas": 12460, "whites": 12461, "##ava": 12462, "classrooms": 12463, "mw": 12464, "aesthetic": 12465, "publishes": 12466, "valleys": 12467, "guides": 12468, "cubs": 12469, "johannes": 12470, "bryant": 12471, "conventions": 12472, "affecting": 12473, "##itt": 12474, "drain": 12475, "awesome": 12476, "isolation": 12477, "prosecutor": 12478, "ambitious": 12479, "apology": 12480, "captive": 12481, "downs": 12482, "atmospheric": 12483, "lorenzo": 12484, "aisle": 12485, "beef": 12486, "foul": 12487, "##onia": 12488, "kidding": 12489, "composite": 12490, "disturbed": 12491, "illusion": 12492, "natives": 12493, "##ffer": 12494, "emi": 12495, "rockets": 12496, "riverside": 12497, "wartime": 12498, "painters": 12499, "adolf": 12500, "melted": 12501, "##ail": 12502, "uncertainty": 12503, "simulation": 12504, "hawks": 12505, "progressed": 12506, "meantime": 12507, "builder": 12508, "spray": 12509, "breach": 12510, "unhappy": 12511, "regina": 12512, "russians": 12513, "##urg": 12514, "determining": 12515, "##tation": 12516, "tram": 12517, "1806": 12518, "##quin": 12519, "aging": 12520, "##12": 12521, "1823": 12522, "garion": 12523, "rented": 12524, "mister": 12525, "diaz": 12526, "terminated": 12527, "clip": 12528, "1817": 12529, "depend": 12530, "nervously": 12531, "disco": 12532, "owe": 12533, "defenders": 12534, "shiva": 12535, "notorious": 12536, "disbelief": 12537, "shiny": 12538, "worcester": 12539, "##gation": 12540, "##yr": 12541, "trailing": 12542, "undertook": 12543, "islander": 12544, "belarus": 12545, "limitations": 12546, "watershed": 12547, "fuller": 12548, "overlooking": 12549, "utilized": 12550, "raphael": 12551, "1819": 12552, "synthetic": 12553, "breakdown": 12554, "klein": 12555, "##nate": 12556, "moaned": 12557, "memoir": 12558, "lamb": 12559, "practicing": 12560, "##erly": 12561, "cellular": 12562, "arrows": 12563, "exotic": 12564, "##graphy": 12565, "witches": 12566, "117": 12567, "charted": 12568, "rey": 12569, "hut": 12570, "hierarchy": 12571, "subdivision": 12572, "freshwater": 12573, "giuseppe": 12574, "aloud": 12575, "reyes": 12576, "qatar": 12577, "marty": 12578, "sideways": 12579, "utterly": 12580, "sexually": 12581, "jude": 12582, "prayers": 12583, "mccarthy": 12584, "softball": 12585, "blend": 12586, "damien": 12587, "##gging": 12588, "##metric": 12589, "wholly": 12590, "erupted": 12591, "lebanese": 12592, "negro": 12593, "revenues": 12594, "tasted": 12595, "comparative": 12596, "teamed": 12597, "transaction": 12598, "labeled": 12599, "maori": 12600, "sovereignty": 12601, "parkway": 12602, "trauma": 12603, "gran": 12604, "malay": 12605, "121": 12606, "advancement": 12607, "descendant": 12608, "2020": 12609, "buzz": 12610, "salvation": 12611, "inventory": 12612, "symbolic": 12613, "##making": 12614, "antarctica": 12615, "mps": 12616, "##gas": 12617, "##bro": 12618, "mohammed": 12619, "myanmar": 12620, "holt": 12621, "submarines": 12622, "tones": 12623, "##lman": 12624, "locker": 12625, "patriarch": 12626, "bangkok": 12627, "emerson": 12628, "remarks": 12629, "predators": 12630, "kin": 12631, "afghan": 12632, "confession": 12633, "norwich": 12634, "rental": 12635, "emerge": 12636, "advantages": 12637, "##zel": 12638, "rca": 12639, "##hold": 12640, "shortened": 12641, "storms": 12642, "aidan": 12643, "##matic": 12644, "autonomy": 12645, "compliance": 12646, "##quet": 12647, "dudley": 12648, "atp": 12649, "##osis": 12650, "1803": 12651, "motto": 12652, "documentation": 12653, "summary": 12654, "professors": 12655, "spectacular": 12656, "christina": 12657, "archdiocese": 12658, "flashing": 12659, "innocence": 12660, "remake": 12661, "##dell": 12662, "psychic": 12663, "reef": 12664, "scare": 12665, "employ": 12666, "rs": 12667, "sticks": 12668, "meg": 12669, "gus": 12670, "leans": 12671, "##ude": 12672, "accompany": 12673, "bergen": 12674, "tomas": 12675, "##iko": 12676, "doom": 12677, "wages": 12678, "pools": 12679, "##nch": 12680, "##bes": 12681, "breasts": 12682, "scholarly": 12683, "alison": 12684, "outline": 12685, "brittany": 12686, "breakthrough": 12687, "willis": 12688, "realistic": 12689, "##cut": 12690, "##boro": 12691, "competitor": 12692, "##stan": 12693, "pike": 12694, "picnic": 12695, "icon": 12696, "designing": 12697, "commercials": 12698, "washing": 12699, "villain": 12700, "skiing": 12701, "micro": 12702, "costumes": 12703, "auburn": 12704, "halted": 12705, "executives": 12706, "##hat": 12707, "logistics": 12708, "cycles": 12709, "vowel": 12710, "applicable": 12711, "barrett": 12712, "exclaimed": 12713, "eurovision": 12714, "eternity": 12715, "ramon": 12716, "##umi": 12717, "##lls": 12718, "modifications": 12719, "sweeping": 12720, "disgust": 12721, "##uck": 12722, "torch": 12723, "aviv": 12724, "ensuring": 12725, "rude": 12726, "dusty": 12727, "sonic": 12728, "donovan": 12729, "outskirts": 12730, "cu": 12731, "pathway": 12732, "##band": 12733, "##gun": 12734, "##lines": 12735, "disciplines": 12736, "acids": 12737, "cadet": 12738, "paired": 12739, "##40": 12740, "sketches": 12741, "##sive": 12742, "marriages": 12743, "##⁺": 12744, "folding": 12745, "peers": 12746, "slovak": 12747, "implies": 12748, "admired": 12749, "##beck": 12750, "1880s": 12751, "leopold": 12752, "instinct": 12753, "attained": 12754, "weston": 12755, "megan": 12756, "horace": 12757, "##ination": 12758, "dorsal": 12759, "ingredients": 12760, "evolutionary": 12761, "##its": 12762, "complications": 12763, "deity": 12764, "lethal": 12765, "brushing": 12766, "levy": 12767, "deserted": 12768, "institutes": 12769, "posthumously": 12770, "delivering": 12771, "telescope": 12772, "coronation": 12773, "motivated": 12774, "rapids": 12775, "luc": 12776, "flicked": 12777, "pays": 12778, "volcano": 12779, "tanner": 12780, "weighed": 12781, "##nica": 12782, "crowds": 12783, "frankie": 12784, "gifted": 12785, "addressing": 12786, "granddaughter": 12787, "winding": 12788, "##rna": 12789, "constantine": 12790, "gomez": 12791, "##front": 12792, "landscapes": 12793, "rudolf": 12794, "anthropology": 12795, "slate": 12796, "werewolf": 12797, "##lio": 12798, "astronomy": 12799, "circa": 12800, "rouge": 12801, "dreaming": 12802, "sack": 12803, "knelt": 12804, "drowned": 12805, "naomi": 12806, "prolific": 12807, "tracked": 12808, "freezing": 12809, "herb": 12810, "##dium": 12811, "agony": 12812, "randall": 12813, "twisting": 12814, "wendy": 12815, "deposit": 12816, "touches": 12817, "vein": 12818, "wheeler": 12819, "##bbled": 12820, "##bor": 12821, "batted": 12822, "retaining": 12823, "tire": 12824, "presently": 12825, "compare": 12826, "specification": 12827, "daemon": 12828, "nigel": 12829, "##grave": 12830, "merry": 12831, "recommendation": 12832, "czechoslovakia": 12833, "sandra": 12834, "ng": 12835, "roma": 12836, "##sts": 12837, "lambert": 12838, "inheritance": 12839, "sheikh": 12840, "winchester": 12841, "cries": 12842, "examining": 12843, "##yle": 12844, "comeback": 12845, "cuisine": 12846, "nave": 12847, "##iv": 12848, "ko": 12849, "retrieve": 12850, "tomatoes": 12851, "barker": 12852, "polished": 12853, "defining": 12854, "irene": 12855, "lantern": 12856, "personalities": 12857, "begging": 12858, "tract": 12859, "swore": 12860, "1809": 12861, "175": 12862, "##gic": 12863, "omaha": 12864, "brotherhood": 12865, "##rley": 12866, "haiti": 12867, "##ots": 12868, "exeter": 12869, "##ete": 12870, "##zia": 12871, "steele": 12872, "dumb": 12873, "pearson": 12874, "210": 12875, "surveyed": 12876, "elisabeth": 12877, "trends": 12878, "##ef": 12879, "fritz": 12880, "##rf": 12881, "premium": 12882, "bugs": 12883, "fraction": 12884, "calmly": 12885, "viking": 12886, "##birds": 12887, "tug": 12888, "inserted": 12889, "unusually": 12890, "##ield": 12891, "confronted": 12892, "distress": 12893, "crashing": 12894, "brent": 12895, "turks": 12896, "resign": 12897, "##olo": 12898, "cambodia": 12899, "gabe": 12900, "sauce": 12901, "##kal": 12902, "evelyn": 12903, "116": 12904, "extant": 12905, "clusters": 12906, "quarry": 12907, "teenagers": 12908, "luna": 12909, "##lers": 12910, "##ister": 12911, "affiliation": 12912, "drill": 12913, "##ashi": 12914, "panthers": 12915, "scenic": 12916, "libya": 12917, "anita": 12918, "strengthen": 12919, "inscriptions": 12920, "##cated": 12921, "lace": 12922, "sued": 12923, "judith": 12924, "riots": 12925, "##uted": 12926, "mint": 12927, "##eta": 12928, "preparations": 12929, "midst": 12930, "dub": 12931, "challenger": 12932, "##vich": 12933, "mock": 12934, "cf": 12935, "displaced": 12936, "wicket": 12937, "breaths": 12938, "enables": 12939, "schmidt": 12940, "analyst": 12941, "##lum": 12942, "ag": 12943, "highlight": 12944, "automotive": 12945, "axe": 12946, "josef": 12947, "newark": 12948, "sufficiently": 12949, "resembles": 12950, "50th": 12951, "##pal": 12952, "flushed": 12953, "mum": 12954, "traits": 12955, "##ante": 12956, "commodore": 12957, "incomplete": 12958, "warming": 12959, "titular": 12960, "ceremonial": 12961, "ethical": 12962, "118": 12963, "celebrating": 12964, "eighteenth": 12965, "cao": 12966, "lima": 12967, "medalist": 12968, "mobility": 12969, "strips": 12970, "snakes": 12971, "##city": 12972, "miniature": 12973, "zagreb": 12974, "barton": 12975, "escapes": 12976, "umbrella": 12977, "automated": 12978, "doubted": 12979, "differs": 12980, "cooled": 12981, "georgetown": 12982, "dresden": 12983, "cooked": 12984, "fade": 12985, "wyatt": 12986, "rna": 12987, "jacobs": 12988, "carlton": 12989, "abundant": 12990, "stereo": 12991, "boost": 12992, "madras": 12993, "inning": 12994, "##hia": 12995, "spur": 12996, "ip": 12997, "malayalam": 12998, "begged": 12999, "osaka": 13000, "groan": 13001, "escaping": 13002, "charging": 13003, "dose": 13004, "vista": 13005, "##aj": 13006, "bud": 13007, "papa": 13008, "communists": 13009, "advocates": 13010, "edged": 13011, "tri": 13012, "##cent": 13013, "resemble": 13014, "peaking": 13015, "necklace": 13016, "fried": 13017, "montenegro": 13018, "saxony": 13019, "goose": 13020, "glances": 13021, "stuttgart": 13022, "curator": 13023, "recruit": 13024, "grocery": 13025, "sympathetic": 13026, "##tting": 13027, "##fort": 13028, "127": 13029, "lotus": 13030, "randolph": 13031, "ancestor": 13032, "##rand": 13033, "succeeding": 13034, "jupiter": 13035, "1798": 13036, "macedonian": 13037, "##heads": 13038, "hiking": 13039, "1808": 13040, "handing": 13041, "fischer": 13042, "##itive": 13043, "garbage": 13044, "node": 13045, "##pies": 13046, "prone": 13047, "singular": 13048, "papua": 13049, "inclined": 13050, "attractions": 13051, "italia": 13052, "pouring": 13053, "motioned": 13054, "grandma": 13055, "garnered": 13056, "jacksonville": 13057, "corp": 13058, "ego": 13059, "ringing": 13060, "aluminum": 13061, "##hausen": 13062, "ordering": 13063, "##foot": 13064, "drawer": 13065, "traders": 13066, "synagogue": 13067, "##play": 13068, "##kawa": 13069, "resistant": 13070, "wandering": 13071, "fragile": 13072, "fiona": 13073, "teased": 13074, "var": 13075, "hardcore": 13076, "soaked": 13077, "jubilee": 13078, "decisive": 13079, "exposition": 13080, "mercer": 13081, "poster": 13082, "valencia": 13083, "hale": 13084, "kuwait": 13085, "1811": 13086, "##ises": 13087, "##wr": 13088, "##eed": 13089, "tavern": 13090, "gamma": 13091, "122": 13092, "johan": 13093, "##uer": 13094, "airways": 13095, "amino": 13096, "gil": 13097, "##ury": 13098, "vocational": 13099, "domains": 13100, "torres": 13101, "##sp": 13102, "generator": 13103, "folklore": 13104, "outcomes": 13105, "##keeper": 13106, "canberra": 13107, "shooter": 13108, "fl": 13109, "beams": 13110, "confrontation": 13111, "##lling": 13112, "##gram": 13113, "feb": 13114, "aligned": 13115, "forestry": 13116, "pipeline": 13117, "jax": 13118, "motorway": 13119, "conception": 13120, "decay": 13121, "##tos": 13122, "coffin": 13123, "##cott": 13124, "stalin": 13125, "1805": 13126, "escorted": 13127, "minded": 13128, "##nam": 13129, "sitcom": 13130, "purchasing": 13131, "twilight": 13132, "veronica": 13133, "additions": 13134, "passive": 13135, "tensions": 13136, "straw": 13137, "123": 13138, "frequencies": 13139, "1804": 13140, "refugee": 13141, "cultivation": 13142, "##iate": 13143, "christie": 13144, "clary": 13145, "bulletin": 13146, "crept": 13147, "disposal": 13148, "##rich": 13149, "##zong": 13150, "processor": 13151, "crescent": 13152, "##rol": 13153, "bmw": 13154, "emphasized": 13155, "whale": 13156, "nazis": 13157, "aurora": 13158, "##eng": 13159, "dwelling": 13160, "hauled": 13161, "sponsors": 13162, "toledo": 13163, "mega": 13164, "ideology": 13165, "theatres": 13166, "tessa": 13167, "cerambycidae": 13168, "saves": 13169, "turtle": 13170, "cone": 13171, "suspects": 13172, "kara": 13173, "rusty": 13174, "yelling": 13175, "greeks": 13176, "mozart": 13177, "shades": 13178, "cocked": 13179, "participant": 13180, "##tro": 13181, "shire": 13182, "spit": 13183, "freeze": 13184, "necessity": 13185, "##cos": 13186, "inmates": 13187, "nielsen": 13188, "councillors": 13189, "loaned": 13190, "uncommon": 13191, "omar": 13192, "peasants": 13193, "botanical": 13194, "offspring": 13195, "daniels": 13196, "formations": 13197, "jokes": 13198, "1794": 13199, "pioneers": 13200, "sigma": 13201, "licensing": 13202, "##sus": 13203, "wheelchair": 13204, "polite": 13205, "1807": 13206, "liquor": 13207, "pratt": 13208, "trustee": 13209, "##uta": 13210, "forewings": 13211, "balloon": 13212, "##zz": 13213, "kilometre": 13214, "camping": 13215, "explicit": 13216, "casually": 13217, "shawn": 13218, "foolish": 13219, "teammates": 13220, "nm": 13221, "hassan": 13222, "carrie": 13223, "judged": 13224, "satisfy": 13225, "vanessa": 13226, "knives": 13227, "selective": 13228, "cnn": 13229, "flowed": 13230, "##lice": 13231, "eclipse": 13232, "stressed": 13233, "eliza": 13234, "mathematician": 13235, "cease": 13236, "cultivated": 13237, "##roy": 13238, "commissions": 13239, "browns": 13240, "##ania": 13241, "destroyers": 13242, "sheridan": 13243, "meadow": 13244, "##rius": 13245, "minerals": 13246, "##cial": 13247, "downstream": 13248, "clash": 13249, "gram": 13250, "memoirs": 13251, "ventures": 13252, "baha": 13253, "seymour": 13254, "archie": 13255, "midlands": 13256, "edith": 13257, "fare": 13258, "flynn": 13259, "invite": 13260, "canceled": 13261, "tiles": 13262, "stabbed": 13263, "boulder": 13264, "incorporate": 13265, "amended": 13266, "camden": 13267, "facial": 13268, "mollusk": 13269, "unreleased": 13270, "descriptions": 13271, "yoga": 13272, "grabs": 13273, "550": 13274, "raises": 13275, "ramp": 13276, "shiver": 13277, "##rose": 13278, "coined": 13279, "pioneering": 13280, "tunes": 13281, "qing": 13282, "warwick": 13283, "tops": 13284, "119": 13285, "melanie": 13286, "giles": 13287, "##rous": 13288, "wandered": 13289, "##inal": 13290, "annexed": 13291, "nov": 13292, "30th": 13293, "unnamed": 13294, "##ished": 13295, "organizational": 13296, "airplane": 13297, "normandy": 13298, "stoke": 13299, "whistle": 13300, "blessing": 13301, "violations": 13302, "chased": 13303, "holders": 13304, "shotgun": 13305, "##ctic": 13306, "outlet": 13307, "reactor": 13308, "##vik": 13309, "tires": 13310, "tearing": 13311, "shores": 13312, "fortified": 13313, "mascot": 13314, "constituencies": 13315, "nc": 13316, "columnist": 13317, "productive": 13318, "tibet": 13319, "##rta": 13320, "lineage": 13321, "hooked": 13322, "oct": 13323, "tapes": 13324, "judging": 13325, "cody": 13326, "##gger": 13327, "hansen": 13328, "kashmir": 13329, "triggered": 13330, "##eva": 13331, "solved": 13332, "cliffs": 13333, "##tree": 13334, "resisted": 13335, "anatomy": 13336, "protesters": 13337, "transparent": 13338, "implied": 13339, "##iga": 13340, "injection": 13341, "mattress": 13342, "excluding": 13343, "##mbo": 13344, "defenses": 13345, "helpless": 13346, "devotion": 13347, "##elli": 13348, "growl": 13349, "liberals": 13350, "weber": 13351, "phenomena": 13352, "atoms": 13353, "plug": 13354, "##iff": 13355, "mortality": 13356, "apprentice": 13357, "howe": 13358, "convincing": 13359, "aaa": 13360, "swimmer": 13361, "barber": 13362, "leone": 13363, "promptly": 13364, "sodium": 13365, "def": 13366, "nowadays": 13367, "arise": 13368, "##oning": 13369, "gloucester": 13370, "corrected": 13371, "dignity": 13372, "norm": 13373, "erie": 13374, "##ders": 13375, "elders": 13376, "evacuated": 13377, "sylvia": 13378, "compression": 13379, "##yar": 13380, "hartford": 13381, "pose": 13382, "backpack": 13383, "reasoning": 13384, "accepts": 13385, "24th": 13386, "wipe": 13387, "millimetres": 13388, "marcel": 13389, "##oda": 13390, "dodgers": 13391, "albion": 13392, "1790": 13393, "overwhelmed": 13394, "aerospace": 13395, "oaks": 13396, "1795": 13397, "showcase": 13398, "acknowledge": 13399, "recovering": 13400, "nolan": 13401, "ashe": 13402, "hurts": 13403, "geology": 13404, "fashioned": 13405, "disappearance": 13406, "farewell": 13407, "swollen": 13408, "shrug": 13409, "marquis": 13410, "wimbledon": 13411, "124": 13412, "rue": 13413, "1792": 13414, "commemorate": 13415, "reduces": 13416, "experiencing": 13417, "inevitable": 13418, "calcutta": 13419, "intel": 13420, "##court": 13421, "murderer": 13422, "sticking": 13423, "fisheries": 13424, "imagery": 13425, "bloom": 13426, "280": 13427, "brake": 13428, "##inus": 13429, "gustav": 13430, "hesitation": 13431, "memorable": 13432, "po": 13433, "viral": 13434, "beans": 13435, "accidents": 13436, "tunisia": 13437, "antenna": 13438, "spilled": 13439, "consort": 13440, "treatments": 13441, "aye": 13442, "perimeter": 13443, "##gard": 13444, "donation": 13445, "hostage": 13446, "migrated": 13447, "banker": 13448, "addiction": 13449, "apex": 13450, "lil": 13451, "trout": 13452, "##ously": 13453, "conscience": 13454, "##nova": 13455, "rams": 13456, "sands": 13457, "genome": 13458, "passionate": 13459, "troubles": 13460, "##lets": 13461, "##set": 13462, "amid": 13463, "##ibility": 13464, "##ret": 13465, "higgins": 13466, "exceed": 13467, "vikings": 13468, "##vie": 13469, "payne": 13470, "##zan": 13471, "muscular": 13472, "##ste": 13473, "defendant": 13474, "sucking": 13475, "##wal": 13476, "ibrahim": 13477, "fuselage": 13478, "claudia": 13479, "vfl": 13480, "europeans": 13481, "snails": 13482, "interval": 13483, "##garh": 13484, "preparatory": 13485, "statewide": 13486, "tasked": 13487, "lacrosse": 13488, "viktor": 13489, "##lation": 13490, "angola": 13491, "##hra": 13492, "flint": 13493, "implications": 13494, "employs": 13495, "teens": 13496, "patrons": 13497, "stall": 13498, "weekends": 13499, "barriers": 13500, "scrambled": 13501, "nucleus": 13502, "tehran": 13503, "jenna": 13504, "parsons": 13505, "lifelong": 13506, "robots": 13507, "displacement": 13508, "5000": 13509, "##bles": 13510, "precipitation": 13511, "##gt": 13512, "knuckles": 13513, "clutched": 13514, "1802": 13515, "marrying": 13516, "ecology": 13517, "marx": 13518, "accusations": 13519, "declare": 13520, "scars": 13521, "kolkata": 13522, "mat": 13523, "meadows": 13524, "bermuda": 13525, "skeleton": 13526, "finalists": 13527, "vintage": 13528, "crawl": 13529, "coordinate": 13530, "affects": 13531, "subjected": 13532, "orchestral": 13533, "mistaken": 13534, "##tc": 13535, "mirrors": 13536, "dipped": 13537, "relied": 13538, "260": 13539, "arches": 13540, "candle": 13541, "##nick": 13542, "incorporating": 13543, "wildly": 13544, "fond": 13545, "basilica": 13546, "owl": 13547, "fringe": 13548, "rituals": 13549, "whispering": 13550, "stirred": 13551, "feud": 13552, "tertiary": 13553, "slick": 13554, "goat": 13555, "honorable": 13556, "whereby": 13557, "skip": 13558, "ricardo": 13559, "stripes": 13560, "parachute": 13561, "adjoining": 13562, "submerged": 13563, "synthesizer": 13564, "##gren": 13565, "intend": 13566, "positively": 13567, "ninety": 13568, "phi": 13569, "beaver": 13570, "partition": 13571, "fellows": 13572, "alexis": 13573, "prohibition": 13574, "carlisle": 13575, "bizarre": 13576, "fraternity": 13577, "##bre": 13578, "doubts": 13579, "icy": 13580, "cbc": 13581, "aquatic": 13582, "sneak": 13583, "sonny": 13584, "combines": 13585, "airports": 13586, "crude": 13587, "supervised": 13588, "spatial": 13589, "merge": 13590, "alfonso": 13591, "##bic": 13592, "corrupt": 13593, "scan": 13594, "undergo": 13595, "##ams": 13596, "disabilities": 13597, "colombian": 13598, "comparing": 13599, "dolphins": 13600, "perkins": 13601, "##lish": 13602, "reprinted": 13603, "unanimous": 13604, "bounced": 13605, "hairs": 13606, "underworld": 13607, "midwest": 13608, "semester": 13609, "bucket": 13610, "paperback": 13611, "miniseries": 13612, "coventry": 13613, "demise": 13614, "##leigh": 13615, "demonstrations": 13616, "sensor": 13617, "rotating": 13618, "yan": 13619, "##hler": 13620, "arrange": 13621, "soils": 13622, "##idge": 13623, "hyderabad": 13624, "labs": 13625, "##dr": 13626, "brakes": 13627, "grandchildren": 13628, "##nde": 13629, "negotiated": 13630, "rover": 13631, "ferrari": 13632, "continuation": 13633, "directorate": 13634, "augusta": 13635, "stevenson": 13636, "counterpart": 13637, "gore": 13638, "##rda": 13639, "nursery": 13640, "rican": 13641, "ave": 13642, "collectively": 13643, "broadly": 13644, "pastoral": 13645, "repertoire": 13646, "asserted": 13647, "discovering": 13648, "nordic": 13649, "styled": 13650, "fiba": 13651, "cunningham": 13652, "harley": 13653, "middlesex": 13654, "survives": 13655, "tumor": 13656, "tempo": 13657, "zack": 13658, "aiming": 13659, "lok": 13660, "urgent": 13661, "##rade": 13662, "##nto": 13663, "devils": 13664, "##ement": 13665, "contractor": 13666, "turin": 13667, "##wl": 13668, "##ool": 13669, "bliss": 13670, "repaired": 13671, "simmons": 13672, "moan": 13673, "astronomical": 13674, "cr": 13675, "negotiate": 13676, "lyric": 13677, "1890s": 13678, "lara": 13679, "bred": 13680, "clad": 13681, "angus": 13682, "pbs": 13683, "##ience": 13684, "engineered": 13685, "posed": 13686, "##lk": 13687, "hernandez": 13688, "possessions": 13689, "elbows": 13690, "psychiatric": 13691, "strokes": 13692, "confluence": 13693, "electorate": 13694, "lifts": 13695, "campuses": 13696, "lava": 13697, "alps": 13698, "##ep": 13699, "##ution": 13700, "##date": 13701, "physicist": 13702, "woody": 13703, "##page": 13704, "##ographic": 13705, "##itis": 13706, "juliet": 13707, "reformation": 13708, "sparhawk": 13709, "320": 13710, "complement": 13711, "suppressed": 13712, "jewel": 13713, "##½": 13714, "floated": 13715, "##kas": 13716, "continuity": 13717, "sadly": 13718, "##ische": 13719, "inability": 13720, "melting": 13721, "scanning": 13722, "paula": 13723, "flour": 13724, "judaism": 13725, "safer": 13726, "vague": 13727, "##lm": 13728, "solving": 13729, "curb": 13730, "##stown": 13731, "financially": 13732, "gable": 13733, "bees": 13734, "expired": 13735, "miserable": 13736, "cassidy": 13737, "dominion": 13738, "1789": 13739, "cupped": 13740, "145": 13741, "robbery": 13742, "facto": 13743, "amos": 13744, "warden": 13745, "resume": 13746, "tallest": 13747, "marvin": 13748, "ing": 13749, "pounded": 13750, "usd": 13751, "declaring": 13752, "gasoline": 13753, "##aux": 13754, "darkened": 13755, "270": 13756, "650": 13757, "sophomore": 13758, "##mere": 13759, "erection": 13760, "gossip": 13761, "televised": 13762, "risen": 13763, "dial": 13764, "##eu": 13765, "pillars": 13766, "##link": 13767, "passages": 13768, "profound": 13769, "##tina": 13770, "arabian": 13771, "ashton": 13772, "silicon": 13773, "nail": 13774, "##ead": 13775, "##lated": 13776, "##wer": 13777, "##hardt": 13778, "fleming": 13779, "firearms": 13780, "ducked": 13781, "circuits": 13782, "blows": 13783, "waterloo": 13784, "titans": 13785, "##lina": 13786, "atom": 13787, "fireplace": 13788, "cheshire": 13789, "financed": 13790, "activation": 13791, "algorithms": 13792, "##zzi": 13793, "constituent": 13794, "catcher": 13795, "cherokee": 13796, "partnerships": 13797, "sexuality": 13798, "platoon": 13799, "tragic": 13800, "vivian": 13801, "guarded": 13802, "whiskey": 13803, "meditation": 13804, "poetic": 13805, "##late": 13806, "##nga": 13807, "##ake": 13808, "porto": 13809, "listeners": 13810, "dominance": 13811, "kendra": 13812, "mona": 13813, "chandler": 13814, "factions": 13815, "22nd": 13816, "salisbury": 13817, "attitudes": 13818, "derivative": 13819, "##ido": 13820, "##haus": 13821, "intake": 13822, "paced": 13823, "javier": 13824, "illustrator": 13825, "barrels": 13826, "bias": 13827, "cockpit": 13828, "burnett": 13829, "dreamed": 13830, "ensuing": 13831, "##anda": 13832, "receptors": 13833, "someday": 13834, "hawkins": 13835, "mattered": 13836, "##lal": 13837, "slavic": 13838, "1799": 13839, "jesuit": 13840, "cameroon": 13841, "wasted": 13842, "tai": 13843, "wax": 13844, "lowering": 13845, "victorious": 13846, "freaking": 13847, "outright": 13848, "hancock": 13849, "librarian": 13850, "sensing": 13851, "bald": 13852, "calcium": 13853, "myers": 13854, "tablet": 13855, "announcing": 13856, "barack": 13857, "shipyard": 13858, "pharmaceutical": 13859, "##uan": 13860, "greenwich": 13861, "flush": 13862, "medley": 13863, "patches": 13864, "wolfgang": 13865, "pt": 13866, "speeches": 13867, "acquiring": 13868, "exams": 13869, "nikolai": 13870, "##gg": 13871, "hayden": 13872, "kannada": 13873, "##type": 13874, "reilly": 13875, "##pt": 13876, "waitress": 13877, "abdomen": 13878, "devastated": 13879, "capped": 13880, "pseudonym": 13881, "pharmacy": 13882, "fulfill": 13883, "paraguay": 13884, "1796": 13885, "clicked": 13886, "##trom": 13887, "archipelago": 13888, "syndicated": 13889, "##hman": 13890, "lumber": 13891, "orgasm": 13892, "rejection": 13893, "clifford": 13894, "lorraine": 13895, "advent": 13896, "mafia": 13897, "rodney": 13898, "brock": 13899, "##ght": 13900, "##used": 13901, "##elia": 13902, "cassette": 13903, "chamberlain": 13904, "despair": 13905, "mongolia": 13906, "sensors": 13907, "developmental": 13908, "upstream": 13909, "##eg": 13910, "##alis": 13911, "spanning": 13912, "165": 13913, "trombone": 13914, "basque": 13915, "seeded": 13916, "interred": 13917, "renewable": 13918, "rhys": 13919, "leapt": 13920, "revision": 13921, "molecule": 13922, "##ages": 13923, "chord": 13924, "vicious": 13925, "nord": 13926, "shivered": 13927, "23rd": 13928, "arlington": 13929, "debts": 13930, "corpus": 13931, "sunrise": 13932, "bays": 13933, "blackburn": 13934, "centimetres": 13935, "##uded": 13936, "shuddered": 13937, "gm": 13938, "strangely": 13939, "gripping": 13940, "cartoons": 13941, "isabelle": 13942, "orbital": 13943, "##ppa": 13944, "seals": 13945, "proving": 13946, "##lton": 13947, "refusal": 13948, "strengthened": 13949, "bust": 13950, "assisting": 13951, "baghdad": 13952, "batsman": 13953, "portrayal": 13954, "mara": 13955, "pushes": 13956, "spears": 13957, "og": 13958, "##cock": 13959, "reside": 13960, "nathaniel": 13961, "brennan": 13962, "1776": 13963, "confirmation": 13964, "caucus": 13965, "##worthy": 13966, "markings": 13967, "yemen": 13968, "nobles": 13969, "ku": 13970, "lazy": 13971, "viewer": 13972, "catalan": 13973, "encompasses": 13974, "sawyer": 13975, "##fall": 13976, "sparked": 13977, "substances": 13978, "patents": 13979, "braves": 13980, "arranger": 13981, "evacuation": 13982, "sergio": 13983, "persuade": 13984, "dover": 13985, "tolerance": 13986, "penguin": 13987, "cum": 13988, "jockey": 13989, "insufficient": 13990, "townships": 13991, "occupying": 13992, "declining": 13993, "plural": 13994, "processed": 13995, "projection": 13996, "puppet": 13997, "flanders": 13998, "introduces": 13999, "liability": 14000, "##yon": 14001, "gymnastics": 14002, "antwerp": 14003, "taipei": 14004, "hobart": 14005, "candles": 14006, "jeep": 14007, "wes": 14008, "observers": 14009, "126": 14010, "chaplain": 14011, "bundle": 14012, "glorious": 14013, "##hine": 14014, "hazel": 14015, "flung": 14016, "sol": 14017, "excavations": 14018, "dumped": 14019, "stares": 14020, "sh": 14021, "bangalore": 14022, "triangular": 14023, "icelandic": 14024, "intervals": 14025, "expressing": 14026, "turbine": 14027, "##vers": 14028, "songwriting": 14029, "crafts": 14030, "##igo": 14031, "jasmine": 14032, "ditch": 14033, "rite": 14034, "##ways": 14035, "entertaining": 14036, "comply": 14037, "sorrow": 14038, "wrestlers": 14039, "basel": 14040, "emirates": 14041, "marian": 14042, "rivera": 14043, "helpful": 14044, "##some": 14045, "caution": 14046, "downward": 14047, "networking": 14048, "##atory": 14049, "##tered": 14050, "darted": 14051, "genocide": 14052, "emergence": 14053, "replies": 14054, "specializing": 14055, "spokesman": 14056, "convenient": 14057, "unlocked": 14058, "fading": 14059, "augustine": 14060, "concentrations": 14061, "resemblance": 14062, "elijah": 14063, "investigator": 14064, "andhra": 14065, "##uda": 14066, "promotes": 14067, "bean": 14068, "##rrell": 14069, "fleeing": 14070, "wan": 14071, "simone": 14072, "announcer": 14073, "##ame": 14074, "##bby": 14075, "lydia": 14076, "weaver": 14077, "132": 14078, "residency": 14079, "modification": 14080, "##fest": 14081, "stretches": 14082, "##ast": 14083, "alternatively": 14084, "nat": 14085, "lowe": 14086, "lacks": 14087, "##ented": 14088, "pam": 14089, "tile": 14090, "concealed": 14091, "inferior": 14092, "abdullah": 14093, "residences": 14094, "tissues": 14095, "vengeance": 14096, "##ided": 14097, "moisture": 14098, "peculiar": 14099, "groove": 14100, "zip": 14101, "bologna": 14102, "jennings": 14103, "ninja": 14104, "oversaw": 14105, "zombies": 14106, "pumping": 14107, "batch": 14108, "livingston": 14109, "emerald": 14110, "installations": 14111, "1797": 14112, "peel": 14113, "nitrogen": 14114, "rama": 14115, "##fying": 14116, "##star": 14117, "schooling": 14118, "strands": 14119, "responding": 14120, "werner": 14121, "##ost": 14122, "lime": 14123, "casa": 14124, "accurately": 14125, "targeting": 14126, "##rod": 14127, "underway": 14128, "##uru": 14129, "hemisphere": 14130, "lester": 14131, "##yard": 14132, "occupies": 14133, "2d": 14134, "griffith": 14135, "angrily": 14136, "reorganized": 14137, "##owing": 14138, "courtney": 14139, "deposited": 14140, "##dd": 14141, "##30": 14142, "estadio": 14143, "##ifies": 14144, "dunn": 14145, "exiled": 14146, "##ying": 14147, "checks": 14148, "##combe": 14149, "##о": 14150, "##fly": 14151, "successes": 14152, "unexpectedly": 14153, "blu": 14154, "assessed": 14155, "##flower": 14156, "##ه": 14157, "observing": 14158, "sacked": 14159, "spiders": 14160, "kn": 14161, "##tail": 14162, "mu": 14163, "nodes": 14164, "prosperity": 14165, "audrey": 14166, "divisional": 14167, "155": 14168, "broncos": 14169, "tangled": 14170, "adjust": 14171, "feeds": 14172, "erosion": 14173, "paolo": 14174, "surf": 14175, "directory": 14176, "snatched": 14177, "humid": 14178, "admiralty": 14179, "screwed": 14180, "gt": 14181, "reddish": 14182, "##nese": 14183, "modules": 14184, "trench": 14185, "lamps": 14186, "bind": 14187, "leah": 14188, "bucks": 14189, "competes": 14190, "##nz": 14191, "##form": 14192, "transcription": 14193, "##uc": 14194, "isles": 14195, "violently": 14196, "clutching": 14197, "pga": 14198, "cyclist": 14199, "inflation": 14200, "flats": 14201, "ragged": 14202, "unnecessary": 14203, "##hian": 14204, "stubborn": 14205, "coordinated": 14206, "harriet": 14207, "baba": 14208, "disqualified": 14209, "330": 14210, "insect": 14211, "wolfe": 14212, "##fies": 14213, "reinforcements": 14214, "rocked": 14215, "duel": 14216, "winked": 14217, "embraced": 14218, "bricks": 14219, "##raj": 14220, "hiatus": 14221, "defeats": 14222, "pending": 14223, "brightly": 14224, "jealousy": 14225, "##xton": 14226, "##hm": 14227, "##uki": 14228, "lena": 14229, "gdp": 14230, "colorful": 14231, "##dley": 14232, "stein": 14233, "kidney": 14234, "##shu": 14235, "underwear": 14236, "wanderers": 14237, "##haw": 14238, "##icus": 14239, "guardians": 14240, "m³": 14241, "roared": 14242, "habits": 14243, "##wise": 14244, "permits": 14245, "gp": 14246, "uranium": 14247, "punished": 14248, "disguise": 14249, "bundesliga": 14250, "elise": 14251, "dundee": 14252, "erotic": 14253, "partisan": 14254, "pi": 14255, "collectors": 14256, "float": 14257, "individually": 14258, "rendering": 14259, "behavioral": 14260, "bucharest": 14261, "ser": 14262, "hare": 14263, "valerie": 14264, "corporal": 14265, "nutrition": 14266, "proportional": 14267, "##isa": 14268, "immense": 14269, "##kis": 14270, "pavement": 14271, "##zie": 14272, "##eld": 14273, "sutherland": 14274, "crouched": 14275, "1775": 14276, "##lp": 14277, "suzuki": 14278, "trades": 14279, "endurance": 14280, "operas": 14281, "crosby": 14282, "prayed": 14283, "priory": 14284, "rory": 14285, "socially": 14286, "##urn": 14287, "gujarat": 14288, "##pu": 14289, "walton": 14290, "cube": 14291, "pasha": 14292, "privilege": 14293, "lennon": 14294, "floods": 14295, "thorne": 14296, "waterfall": 14297, "nipple": 14298, "scouting": 14299, "approve": 14300, "##lov": 14301, "minorities": 14302, "voter": 14303, "dwight": 14304, "extensions": 14305, "assure": 14306, "ballroom": 14307, "slap": 14308, "dripping": 14309, "privileges": 14310, "rejoined": 14311, "confessed": 14312, "demonstrating": 14313, "patriotic": 14314, "yell": 14315, "investor": 14316, "##uth": 14317, "pagan": 14318, "slumped": 14319, "squares": 14320, "##cle": 14321, "##kins": 14322, "confront": 14323, "bert": 14324, "embarrassment": 14325, "##aid": 14326, "aston": 14327, "urging": 14328, "sweater": 14329, "starr": 14330, "yuri": 14331, "brains": 14332, "williamson": 14333, "commuter": 14334, "mortar": 14335, "structured": 14336, "selfish": 14337, "exports": 14338, "##jon": 14339, "cds": 14340, "##him": 14341, "unfinished": 14342, "##rre": 14343, "mortgage": 14344, "destinations": 14345, "##nagar": 14346, "canoe": 14347, "solitary": 14348, "buchanan": 14349, "delays": 14350, "magistrate": 14351, "fk": 14352, "##pling": 14353, "motivation": 14354, "##lier": 14355, "##vier": 14356, "recruiting": 14357, "assess": 14358, "##mouth": 14359, "malik": 14360, "antique": 14361, "1791": 14362, "pius": 14363, "rahman": 14364, "reich": 14365, "tub": 14366, "zhou": 14367, "smashed": 14368, "airs": 14369, "galway": 14370, "xii": 14371, "conditioning": 14372, "honduras": 14373, "discharged": 14374, "dexter": 14375, "##pf": 14376, "lionel": 14377, "129": 14378, "debates": 14379, "lemon": 14380, "tiffany": 14381, "volunteered": 14382, "dom": 14383, "dioxide": 14384, "procession": 14385, "devi": 14386, "sic": 14387, "tremendous": 14388, "advertisements": 14389, "colts": 14390, "transferring": 14391, "verdict": 14392, "hanover": 14393, "decommissioned": 14394, "utter": 14395, "relate": 14396, "pac": 14397, "racism": 14398, "##top": 14399, "beacon": 14400, "limp": 14401, "similarity": 14402, "terra": 14403, "occurrence": 14404, "ant": 14405, "##how": 14406, "becky": 14407, "capt": 14408, "updates": 14409, "armament": 14410, "richie": 14411, "pal": 14412, "##graph": 14413, "halloween": 14414, "mayo": 14415, "##ssen": 14416, "##bone": 14417, "cara": 14418, "serena": 14419, "fcc": 14420, "dolls": 14421, "obligations": 14422, "##dling": 14423, "violated": 14424, "lafayette": 14425, "jakarta": 14426, "exploitation": 14427, "##ime": 14428, "infamous": 14429, "iconic": 14430, "##lah": 14431, "##park": 14432, "kitty": 14433, "moody": 14434, "reginald": 14435, "dread": 14436, "spill": 14437, "crystals": 14438, "olivier": 14439, "modeled": 14440, "bluff": 14441, "equilibrium": 14442, "separating": 14443, "notices": 14444, "ordnance": 14445, "extinction": 14446, "onset": 14447, "cosmic": 14448, "attachment": 14449, "sammy": 14450, "expose": 14451, "privy": 14452, "anchored": 14453, "##bil": 14454, "abbott": 14455, "admits": 14456, "bending": 14457, "baritone": 14458, "emmanuel": 14459, "policeman": 14460, "vaughan": 14461, "winged": 14462, "climax": 14463, "dresses": 14464, "denny": 14465, "polytechnic": 14466, "mohamed": 14467, "burmese": 14468, "authentic": 14469, "nikki": 14470, "genetics": 14471, "grandparents": 14472, "homestead": 14473, "gaza": 14474, "postponed": 14475, "metacritic": 14476, "una": 14477, "##sby": 14478, "##bat": 14479, "unstable": 14480, "dissertation": 14481, "##rial": 14482, "##cian": 14483, "curls": 14484, "obscure": 14485, "uncovered": 14486, "bronx": 14487, "praying": 14488, "disappearing": 14489, "##hoe": 14490, "prehistoric": 14491, "coke": 14492, "turret": 14493, "mutations": 14494, "nonprofit": 14495, "pits": 14496, "monaco": 14497, "##ي": 14498, "##usion": 14499, "prominently": 14500, "dispatched": 14501, "podium": 14502, "##mir": 14503, "uci": 14504, "##uation": 14505, "133": 14506, "fortifications": 14507, "birthplace": 14508, "kendall": 14509, "##lby": 14510, "##oll": 14511, "preacher": 14512, "rack": 14513, "goodman": 14514, "##rman": 14515, "persistent": 14516, "##ott": 14517, "countless": 14518, "jaime": 14519, "recorder": 14520, "lexington": 14521, "persecution": 14522, "jumps": 14523, "renewal": 14524, "wagons": 14525, "##11": 14526, "crushing": 14527, "##holder": 14528, "decorations": 14529, "##lake": 14530, "abundance": 14531, "wrath": 14532, "laundry": 14533, "£1": 14534, "garde": 14535, "##rp": 14536, "jeanne": 14537, "beetles": 14538, "peasant": 14539, "##sl": 14540, "splitting": 14541, "caste": 14542, "sergei": 14543, "##rer": 14544, "##ema": 14545, "scripts": 14546, "##ively": 14547, "rub": 14548, "satellites": 14549, "##vor": 14550, "inscribed": 14551, "verlag": 14552, "scrapped": 14553, "gale": 14554, "packages": 14555, "chick": 14556, "potato": 14557, "slogan": 14558, "kathleen": 14559, "arabs": 14560, "##culture": 14561, "counterparts": 14562, "reminiscent": 14563, "choral": 14564, "##tead": 14565, "rand": 14566, "retains": 14567, "bushes": 14568, "dane": 14569, "accomplish": 14570, "courtesy": 14571, "closes": 14572, "##oth": 14573, "slaughter": 14574, "hague": 14575, "krakow": 14576, "lawson": 14577, "tailed": 14578, "elias": 14579, "ginger": 14580, "##ttes": 14581, "canopy": 14582, "betrayal": 14583, "rebuilding": 14584, "turf": 14585, "##hof": 14586, "frowning": 14587, "allegiance": 14588, "brigades": 14589, "kicks": 14590, "rebuild": 14591, "polls": 14592, "alias": 14593, "nationalism": 14594, "td": 14595, "rowan": 14596, "audition": 14597, "bowie": 14598, "fortunately": 14599, "recognizes": 14600, "harp": 14601, "dillon": 14602, "horrified": 14603, "##oro": 14604, "renault": 14605, "##tics": 14606, "ropes": 14607, "##α": 14608, "presumed": 14609, "rewarded": 14610, "infrared": 14611, "wiping": 14612, "accelerated": 14613, "illustration": 14614, "##rid": 14615, "presses": 14616, "practitioners": 14617, "badminton": 14618, "##iard": 14619, "detained": 14620, "##tera": 14621, "recognizing": 14622, "relates": 14623, "misery": 14624, "##sies": 14625, "##tly": 14626, "reproduction": 14627, "piercing": 14628, "potatoes": 14629, "thornton": 14630, "esther": 14631, "manners": 14632, "hbo": 14633, "##aan": 14634, "ours": 14635, "bullshit": 14636, "ernie": 14637, "perennial": 14638, "sensitivity": 14639, "illuminated": 14640, "rupert": 14641, "##jin": 14642, "##iss": 14643, "##ear": 14644, "rfc": 14645, "nassau": 14646, "##dock": 14647, "staggered": 14648, "socialism": 14649, "##haven": 14650, "appointments": 14651, "nonsense": 14652, "prestige": 14653, "sharma": 14654, "haul": 14655, "##tical": 14656, "solidarity": 14657, "gps": 14658, "##ook": 14659, "##rata": 14660, "igor": 14661, "pedestrian": 14662, "##uit": 14663, "baxter": 14664, "tenants": 14665, "wires": 14666, "medication": 14667, "unlimited": 14668, "guiding": 14669, "impacts": 14670, "diabetes": 14671, "##rama": 14672, "sasha": 14673, "pas": 14674, "clive": 14675, "extraction": 14676, "131": 14677, "continually": 14678, "constraints": 14679, "##bilities": 14680, "sonata": 14681, "hunted": 14682, "sixteenth": 14683, "chu": 14684, "planting": 14685, "quote": 14686, "mayer": 14687, "pretended": 14688, "abs": 14689, "spat": 14690, "##hua": 14691, "ceramic": 14692, "##cci": 14693, "curtains": 14694, "pigs": 14695, "pitching": 14696, "##dad": 14697, "latvian": 14698, "sore": 14699, "dayton": 14700, "##sted": 14701, "##qi": 14702, "patrols": 14703, "slice": 14704, "playground": 14705, "##nted": 14706, "shone": 14707, "stool": 14708, "apparatus": 14709, "inadequate": 14710, "mates": 14711, "treason": 14712, "##ija": 14713, "desires": 14714, "##liga": 14715, "##croft": 14716, "somalia": 14717, "laurent": 14718, "mir": 14719, "leonardo": 14720, "oracle": 14721, "grape": 14722, "obliged": 14723, "chevrolet": 14724, "thirteenth": 14725, "stunning": 14726, "enthusiastic": 14727, "##ede": 14728, "accounted": 14729, "concludes": 14730, "currents": 14731, "basil": 14732, "##kovic": 14733, "drought": 14734, "##rica": 14735, "mai": 14736, "##aire": 14737, "shove": 14738, "posting": 14739, "##shed": 14740, "pilgrimage": 14741, "humorous": 14742, "packing": 14743, "fry": 14744, "pencil": 14745, "wines": 14746, "smells": 14747, "144": 14748, "marilyn": 14749, "aching": 14750, "newest": 14751, "clung": 14752, "bon": 14753, "neighbours": 14754, "sanctioned": 14755, "##pie": 14756, "mug": 14757, "##stock": 14758, "drowning": 14759, "##mma": 14760, "hydraulic": 14761, "##vil": 14762, "hiring": 14763, "reminder": 14764, "lilly": 14765, "investigators": 14766, "##ncies": 14767, "sour": 14768, "##eous": 14769, "compulsory": 14770, "packet": 14771, "##rion": 14772, "##graphic": 14773, "##elle": 14774, "cannes": 14775, "##inate": 14776, "depressed": 14777, "##rit": 14778, "heroic": 14779, "importantly": 14780, "theresa": 14781, "##tled": 14782, "conway": 14783, "saturn": 14784, "marginal": 14785, "rae": 14786, "##xia": 14787, "corresponds": 14788, "royce": 14789, "pact": 14790, "jasper": 14791, "explosives": 14792, "packaging": 14793, "aluminium": 14794, "##ttered": 14795, "denotes": 14796, "rhythmic": 14797, "spans": 14798, "assignments": 14799, "hereditary": 14800, "outlined": 14801, "originating": 14802, "sundays": 14803, "lad": 14804, "reissued": 14805, "greeting": 14806, "beatrice": 14807, "##dic": 14808, "pillar": 14809, "marcos": 14810, "plots": 14811, "handbook": 14812, "alcoholic": 14813, "judiciary": 14814, "avant": 14815, "slides": 14816, "extract": 14817, "masculine": 14818, "blur": 14819, "##eum": 14820, "##force": 14821, "homage": 14822, "trembled": 14823, "owens": 14824, "hymn": 14825, "trey": 14826, "omega": 14827, "signaling": 14828, "socks": 14829, "accumulated": 14830, "reacted": 14831, "attic": 14832, "theo": 14833, "lining": 14834, "angie": 14835, "distraction": 14836, "primera": 14837, "talbot": 14838, "##key": 14839, "1200": 14840, "ti": 14841, "creativity": 14842, "billed": 14843, "##hey": 14844, "deacon": 14845, "eduardo": 14846, "identifies": 14847, "proposition": 14848, "dizzy": 14849, "gunner": 14850, "hogan": 14851, "##yam": 14852, "##pping": 14853, "##hol": 14854, "ja": 14855, "##chan": 14856, "jensen": 14857, "reconstructed": 14858, "##berger": 14859, "clearance": 14860, "darius": 14861, "##nier": 14862, "abe": 14863, "harlem": 14864, "plea": 14865, "dei": 14866, "circled": 14867, "emotionally": 14868, "notation": 14869, "fascist": 14870, "neville": 14871, "exceeded": 14872, "upwards": 14873, "viable": 14874, "ducks": 14875, "##fo": 14876, "workforce": 14877, "racer": 14878, "limiting": 14879, "shri": 14880, "##lson": 14881, "possesses": 14882, "1600": 14883, "kerr": 14884, "moths": 14885, "devastating": 14886, "laden": 14887, "disturbing": 14888, "locking": 14889, "##cture": 14890, "gal": 14891, "fearing": 14892, "accreditation": 14893, "flavor": 14894, "aide": 14895, "1870s": 14896, "mountainous": 14897, "##baum": 14898, "melt": 14899, "##ures": 14900, "motel": 14901, "texture": 14902, "servers": 14903, "soda": 14904, "##mb": 14905, "herd": 14906, "##nium": 14907, "erect": 14908, "puzzled": 14909, "hum": 14910, "peggy": 14911, "examinations": 14912, "gould": 14913, "testified": 14914, "geoff": 14915, "ren": 14916, "devised": 14917, "sacks": 14918, "##law": 14919, "denial": 14920, "posters": 14921, "grunted": 14922, "cesar": 14923, "tutor": 14924, "ec": 14925, "gerry": 14926, "offerings": 14927, "byrne": 14928, "falcons": 14929, "combinations": 14930, "ct": 14931, "incoming": 14932, "pardon": 14933, "rocking": 14934, "26th": 14935, "avengers": 14936, "flared": 14937, "mankind": 14938, "seller": 14939, "uttar": 14940, "loch": 14941, "nadia": 14942, "stroking": 14943, "exposing": 14944, "##hd": 14945, "fertile": 14946, "ancestral": 14947, "instituted": 14948, "##has": 14949, "noises": 14950, "prophecy": 14951, "taxation": 14952, "eminent": 14953, "vivid": 14954, "pol": 14955, "##bol": 14956, "dart": 14957, "indirect": 14958, "multimedia": 14959, "notebook": 14960, "upside": 14961, "displaying": 14962, "adrenaline": 14963, "referenced": 14964, "geometric": 14965, "##iving": 14966, "progression": 14967, "##ddy": 14968, "blunt": 14969, "announce": 14970, "##far": 14971, "implementing": 14972, "##lav": 14973, "aggression": 14974, "liaison": 14975, "cooler": 14976, "cares": 14977, "headache": 14978, "plantations": 14979, "gorge": 14980, "dots": 14981, "impulse": 14982, "thickness": 14983, "ashamed": 14984, "averaging": 14985, "kathy": 14986, "obligation": 14987, "precursor": 14988, "137": 14989, "fowler": 14990, "symmetry": 14991, "thee": 14992, "225": 14993, "hears": 14994, "##rai": 14995, "undergoing": 14996, "ads": 14997, "butcher": 14998, "bowler": 14999, "##lip": 15000, "cigarettes": 15001, "subscription": 15002, "goodness": 15003, "##ically": 15004, "browne": 15005, "##hos": 15006, "##tech": 15007, "kyoto": 15008, "donor": 15009, "##erty": 15010, "damaging": 15011, "friction": 15012, "drifting": 15013, "expeditions": 15014, "hardened": 15015, "prostitution": 15016, "152": 15017, "fauna": 15018, "blankets": 15019, "claw": 15020, "tossing": 15021, "snarled": 15022, "butterflies": 15023, "recruits": 15024, "investigative": 15025, "coated": 15026, "healed": 15027, "138": 15028, "communal": 15029, "hai": 15030, "xiii": 15031, "academics": 15032, "boone": 15033, "psychologist": 15034, "restless": 15035, "lahore": 15036, "stephens": 15037, "mba": 15038, "brendan": 15039, "foreigners": 15040, "printer": 15041, "##pc": 15042, "ached": 15043, "explode": 15044, "27th": 15045, "deed": 15046, "scratched": 15047, "dared": 15048, "##pole": 15049, "cardiac": 15050, "1780": 15051, "okinawa": 15052, "proto": 15053, "commando": 15054, "compelled": 15055, "oddly": 15056, "electrons": 15057, "##base": 15058, "replica": 15059, "thanksgiving": 15060, "##rist": 15061, "sheila": 15062, "deliberate": 15063, "stafford": 15064, "tidal": 15065, "representations": 15066, "hercules": 15067, "ou": 15068, "##path": 15069, "##iated": 15070, "kidnapping": 15071, "lenses": 15072, "##tling": 15073, "deficit": 15074, "samoa": 15075, "mouths": 15076, "consuming": 15077, "computational": 15078, "maze": 15079, "granting": 15080, "smirk": 15081, "razor": 15082, "fixture": 15083, "ideals": 15084, "inviting": 15085, "aiden": 15086, "nominal": 15087, "##vs": 15088, "issuing": 15089, "julio": 15090, "pitt": 15091, "ramsey": 15092, "docks": 15093, "##oss": 15094, "exhaust": 15095, "##owed": 15096, "bavarian": 15097, "draped": 15098, "anterior": 15099, "mating": 15100, "ethiopian": 15101, "explores": 15102, "noticing": 15103, "##nton": 15104, "discarded": 15105, "convenience": 15106, "hoffman": 15107, "endowment": 15108, "beasts": 15109, "cartridge": 15110, "mormon": 15111, "paternal": 15112, "probe": 15113, "sleeves": 15114, "interfere": 15115, "lump": 15116, "deadline": 15117, "##rail": 15118, "jenks": 15119, "bulldogs": 15120, "scrap": 15121, "alternating": 15122, "justified": 15123, "reproductive": 15124, "nam": 15125, "seize": 15126, "descending": 15127, "secretariat": 15128, "kirby": 15129, "coupe": 15130, "grouped": 15131, "smash": 15132, "panther": 15133, "sedan": 15134, "tapping": 15135, "##18": 15136, "lola": 15137, "cheer": 15138, "germanic": 15139, "unfortunate": 15140, "##eter": 15141, "unrelated": 15142, "##fan": 15143, "subordinate": 15144, "##sdale": 15145, "suzanne": 15146, "advertisement": 15147, "##ility": 15148, "horsepower": 15149, "##lda": 15150, "cautiously": 15151, "discourse": 15152, "luigi": 15153, "##mans": 15154, "##fields": 15155, "noun": 15156, "prevalent": 15157, "mao": 15158, "schneider": 15159, "everett": 15160, "surround": 15161, "governorate": 15162, "kira": 15163, "##avia": 15164, "westward": 15165, "##take": 15166, "misty": 15167, "rails": 15168, "sustainability": 15169, "134": 15170, "unused": 15171, "##rating": 15172, "packs": 15173, "toast": 15174, "unwilling": 15175, "regulate": 15176, "thy": 15177, "suffrage": 15178, "nile": 15179, "awe": 15180, "assam": 15181, "definitions": 15182, "travelers": 15183, "affordable": 15184, "##rb": 15185, "conferred": 15186, "sells": 15187, "undefeated": 15188, "beneficial": 15189, "torso": 15190, "basal": 15191, "repeating": 15192, "remixes": 15193, "##pass": 15194, "bahrain": 15195, "cables": 15196, "fang": 15197, "##itated": 15198, "excavated": 15199, "numbering": 15200, "statutory": 15201, "##rey": 15202, "deluxe": 15203, "##lian": 15204, "forested": 15205, "ramirez": 15206, "derbyshire": 15207, "zeus": 15208, "slamming": 15209, "transfers": 15210, "astronomer": 15211, "banana": 15212, "lottery": 15213, "berg": 15214, "histories": 15215, "bamboo": 15216, "##uchi": 15217, "resurrection": 15218, "posterior": 15219, "bowls": 15220, "vaguely": 15221, "##thi": 15222, "thou": 15223, "preserving": 15224, "tensed": 15225, "offence": 15226, "##inas": 15227, "meyrick": 15228, "callum": 15229, "ridden": 15230, "watt": 15231, "langdon": 15232, "tying": 15233, "lowland": 15234, "snorted": 15235, "daring": 15236, "truman": 15237, "##hale": 15238, "##girl": 15239, "aura": 15240, "overly": 15241, "filing": 15242, "weighing": 15243, "goa": 15244, "infections": 15245, "philanthropist": 15246, "saunders": 15247, "eponymous": 15248, "##owski": 15249, "latitude": 15250, "perspectives": 15251, "reviewing": 15252, "mets": 15253, "commandant": 15254, "radial": 15255, "##kha": 15256, "flashlight": 15257, "reliability": 15258, "koch": 15259, "vowels": 15260, "amazed": 15261, "ada": 15262, "elaine": 15263, "supper": 15264, "##rth": 15265, "##encies": 15266, "predator": 15267, "debated": 15268, "soviets": 15269, "cola": 15270, "##boards": 15271, "##nah": 15272, "compartment": 15273, "crooked": 15274, "arbitrary": 15275, "fourteenth": 15276, "##ctive": 15277, "havana": 15278, "majors": 15279, "steelers": 15280, "clips": 15281, "profitable": 15282, "ambush": 15283, "exited": 15284, "packers": 15285, "##tile": 15286, "nude": 15287, "cracks": 15288, "fungi": 15289, "##е": 15290, "limb": 15291, "trousers": 15292, "josie": 15293, "shelby": 15294, "tens": 15295, "frederic": 15296, "##ος": 15297, "definite": 15298, "smoothly": 15299, "constellation": 15300, "insult": 15301, "baton": 15302, "discs": 15303, "lingering": 15304, "##nco": 15305, "conclusions": 15306, "lent": 15307, "staging": 15308, "becker": 15309, "grandpa": 15310, "shaky": 15311, "##tron": 15312, "einstein": 15313, "obstacles": 15314, "sk": 15315, "adverse": 15316, "elle": 15317, "economically": 15318, "##moto": 15319, "mccartney": 15320, "thor": 15321, "dismissal": 15322, "motions": 15323, "readings": 15324, "nostrils": 15325, "treatise": 15326, "##pace": 15327, "squeezing": 15328, "evidently": 15329, "prolonged": 15330, "1783": 15331, "venezuelan": 15332, "je": 15333, "marguerite": 15334, "beirut": 15335, "takeover": 15336, "shareholders": 15337, "##vent": 15338, "denise": 15339, "digit": 15340, "airplay": 15341, "norse": 15342, "##bbling": 15343, "imaginary": 15344, "pills": 15345, "hubert": 15346, "blaze": 15347, "vacated": 15348, "eliminating": 15349, "##ello": 15350, "vine": 15351, "mansfield": 15352, "##tty": 15353, "retrospective": 15354, "barrow": 15355, "borne": 15356, "clutch": 15357, "bail": 15358, "forensic": 15359, "weaving": 15360, "##nett": 15361, "##witz": 15362, "desktop": 15363, "citadel": 15364, "promotions": 15365, "worrying": 15366, "dorset": 15367, "ieee": 15368, "subdivided": 15369, "##iating": 15370, "manned": 15371, "expeditionary": 15372, "pickup": 15373, "synod": 15374, "chuckle": 15375, "185": 15376, "barney": 15377, "##rz": 15378, "##ffin": 15379, "functionality": 15380, "karachi": 15381, "litigation": 15382, "meanings": 15383, "uc": 15384, "lick": 15385, "turbo": 15386, "anders": 15387, "##ffed": 15388, "execute": 15389, "curl": 15390, "oppose": 15391, "ankles": 15392, "typhoon": 15393, "##د": 15394, "##ache": 15395, "##asia": 15396, "linguistics": 15397, "compassion": 15398, "pressures": 15399, "grazing": 15400, "perfection": 15401, "##iting": 15402, "immunity": 15403, "monopoly": 15404, "muddy": 15405, "backgrounds": 15406, "136": 15407, "namibia": 15408, "francesca": 15409, "monitors": 15410, "attracting": 15411, "stunt": 15412, "tuition": 15413, "##ии": 15414, "vegetable": 15415, "##mates": 15416, "##quent": 15417, "mgm": 15418, "jen": 15419, "complexes": 15420, "forts": 15421, "##ond": 15422, "cellar": 15423, "bites": 15424, "seventeenth": 15425, "royals": 15426, "flemish": 15427, "failures": 15428, "mast": 15429, "charities": 15430, "##cular": 15431, "peruvian": 15432, "capitals": 15433, "macmillan": 15434, "ipswich": 15435, "outward": 15436, "frigate": 15437, "postgraduate": 15438, "folds": 15439, "employing": 15440, "##ouse": 15441, "concurrently": 15442, "fiery": 15443, "##tai": 15444, "contingent": 15445, "nightmares": 15446, "monumental": 15447, "nicaragua": 15448, "##kowski": 15449, "lizard": 15450, "mal": 15451, "fielding": 15452, "gig": 15453, "reject": 15454, "##pad": 15455, "harding": 15456, "##ipe": 15457, "coastline": 15458, "##cin": 15459, "##nos": 15460, "beethoven": 15461, "humphrey": 15462, "innovations": 15463, "##tam": 15464, "##nge": 15465, "norris": 15466, "doris": 15467, "solicitor": 15468, "huang": 15469, "obey": 15470, "141": 15471, "##lc": 15472, "niagara": 15473, "##tton": 15474, "shelves": 15475, "aug": 15476, "bourbon": 15477, "curry": 15478, "nightclub": 15479, "specifications": 15480, "hilton": 15481, "##ndo": 15482, "centennial": 15483, "dispersed": 15484, "worm": 15485, "neglected": 15486, "briggs": 15487, "sm": 15488, "font": 15489, "kuala": 15490, "uneasy": 15491, "plc": 15492, "##nstein": 15493, "##bound": 15494, "##aking": 15495, "##burgh": 15496, "awaiting": 15497, "pronunciation": 15498, "##bbed": 15499, "##quest": 15500, "eh": 15501, "optimal": 15502, "zhu": 15503, "raped": 15504, "greens": 15505, "presided": 15506, "brenda": 15507, "worries": 15508, "##life": 15509, "venetian": 15510, "marxist": 15511, "turnout": 15512, "##lius": 15513, "refined": 15514, "braced": 15515, "sins": 15516, "grasped": 15517, "sunderland": 15518, "nickel": 15519, "speculated": 15520, "lowell": 15521, "cyrillic": 15522, "communism": 15523, "fundraising": 15524, "resembling": 15525, "colonists": 15526, "mutant": 15527, "freddie": 15528, "usc": 15529, "##mos": 15530, "gratitude": 15531, "##run": 15532, "mural": 15533, "##lous": 15534, "chemist": 15535, "wi": 15536, "reminds": 15537, "28th": 15538, "steals": 15539, "tess": 15540, "pietro": 15541, "##ingen": 15542, "promoter": 15543, "ri": 15544, "microphone": 15545, "honoured": 15546, "rai": 15547, "sant": 15548, "##qui": 15549, "feather": 15550, "##nson": 15551, "burlington": 15552, "kurdish": 15553, "terrorists": 15554, "deborah": 15555, "sickness": 15556, "##wed": 15557, "##eet": 15558, "hazard": 15559, "irritated": 15560, "desperation": 15561, "veil": 15562, "clarity": 15563, "##rik": 15564, "jewels": 15565, "xv": 15566, "##gged": 15567, "##ows": 15568, "##cup": 15569, "berkshire": 15570, "unfair": 15571, "mysteries": 15572, "orchid": 15573, "winced": 15574, "exhaustion": 15575, "renovations": 15576, "stranded": 15577, "obe": 15578, "infinity": 15579, "##nies": 15580, "adapt": 15581, "redevelopment": 15582, "thanked": 15583, "registry": 15584, "olga": 15585, "domingo": 15586, "noir": 15587, "tudor": 15588, "ole": 15589, "##atus": 15590, "commenting": 15591, "behaviors": 15592, "##ais": 15593, "crisp": 15594, "pauline": 15595, "probable": 15596, "stirling": 15597, "wigan": 15598, "##bian": 15599, "paralympics": 15600, "panting": 15601, "surpassed": 15602, "##rew": 15603, "luca": 15604, "barred": 15605, "pony": 15606, "famed": 15607, "##sters": 15608, "cassandra": 15609, "waiter": 15610, "carolyn": 15611, "exported": 15612, "##orted": 15613, "andres": 15614, "destructive": 15615, "deeds": 15616, "jonah": 15617, "castles": 15618, "vacancy": 15619, "suv": 15620, "##glass": 15621, "1788": 15622, "orchard": 15623, "yep": 15624, "famine": 15625, "belarusian": 15626, "sprang": 15627, "##forth": 15628, "skinny": 15629, "##mis": 15630, "administrators": 15631, "rotterdam": 15632, "zambia": 15633, "zhao": 15634, "boiler": 15635, "discoveries": 15636, "##ride": 15637, "##physics": 15638, "lucius": 15639, "disappointing": 15640, "outreach": 15641, "spoon": 15642, "##frame": 15643, "qualifications": 15644, "unanimously": 15645, "enjoys": 15646, "regency": 15647, "##iidae": 15648, "stade": 15649, "realism": 15650, "veterinary": 15651, "rodgers": 15652, "dump": 15653, "alain": 15654, "chestnut": 15655, "castile": 15656, "censorship": 15657, "rumble": 15658, "gibbs": 15659, "##itor": 15660, "communion": 15661, "reggae": 15662, "inactivated": 15663, "logs": 15664, "loads": 15665, "##houses": 15666, "homosexual": 15667, "##iano": 15668, "ale": 15669, "informs": 15670, "##cas": 15671, "phrases": 15672, "plaster": 15673, "linebacker": 15674, "ambrose": 15675, "kaiser": 15676, "fascinated": 15677, "850": 15678, "limerick": 15679, "recruitment": 15680, "forge": 15681, "mastered": 15682, "##nding": 15683, "leinster": 15684, "rooted": 15685, "threaten": 15686, "##strom": 15687, "borneo": 15688, "##hes": 15689, "suggestions": 15690, "scholarships": 15691, "propeller": 15692, "documentaries": 15693, "patronage": 15694, "coats": 15695, "constructing": 15696, "invest": 15697, "neurons": 15698, "comet": 15699, "entirety": 15700, "shouts": 15701, "identities": 15702, "annoying": 15703, "unchanged": 15704, "wary": 15705, "##antly": 15706, "##ogy": 15707, "neat": 15708, "oversight": 15709, "##kos": 15710, "phillies": 15711, "replay": 15712, "constance": 15713, "##kka": 15714, "incarnation": 15715, "humble": 15716, "skies": 15717, "minus": 15718, "##acy": 15719, "smithsonian": 15720, "##chel": 15721, "guerrilla": 15722, "jar": 15723, "cadets": 15724, "##plate": 15725, "surplus": 15726, "audit": 15727, "##aru": 15728, "cracking": 15729, "joanna": 15730, "louisa": 15731, "pacing": 15732, "##lights": 15733, "intentionally": 15734, "##iri": 15735, "diner": 15736, "nwa": 15737, "imprint": 15738, "australians": 15739, "tong": 15740, "unprecedented": 15741, "bunker": 15742, "naive": 15743, "specialists": 15744, "ark": 15745, "nichols": 15746, "railing": 15747, "leaked": 15748, "pedal": 15749, "##uka": 15750, "shrub": 15751, "longing": 15752, "roofs": 15753, "v8": 15754, "captains": 15755, "neural": 15756, "tuned": 15757, "##ntal": 15758, "##jet": 15759, "emission": 15760, "medina": 15761, "frantic": 15762, "codex": 15763, "definitive": 15764, "sid": 15765, "abolition": 15766, "intensified": 15767, "stocks": 15768, "enrique": 15769, "sustain": 15770, "genoa": 15771, "oxide": 15772, "##written": 15773, "clues": 15774, "cha": 15775, "##gers": 15776, "tributaries": 15777, "fragment": 15778, "venom": 15779, "##rity": 15780, "##ente": 15781, "##sca": 15782, "muffled": 15783, "vain": 15784, "sire": 15785, "laos": 15786, "##ingly": 15787, "##hana": 15788, "hastily": 15789, "snapping": 15790, "surfaced": 15791, "sentiment": 15792, "motive": 15793, "##oft": 15794, "contests": 15795, "approximate": 15796, "mesa": 15797, "luckily": 15798, "dinosaur": 15799, "exchanges": 15800, "propelled": 15801, "accord": 15802, "bourne": 15803, "relieve": 15804, "tow": 15805, "masks": 15806, "offended": 15807, "##ues": 15808, "cynthia": 15809, "##mmer": 15810, "rains": 15811, "bartender": 15812, "zinc": 15813, "reviewers": 15814, "lois": 15815, "##sai": 15816, "legged": 15817, "arrogant": 15818, "rafe": 15819, "rosie": 15820, "comprise": 15821, "handicap": 15822, "blockade": 15823, "inlet": 15824, "lagoon": 15825, "copied": 15826, "drilling": 15827, "shelley": 15828, "petals": 15829, "##inian": 15830, "mandarin": 15831, "obsolete": 15832, "##inated": 15833, "onward": 15834, "arguably": 15835, "productivity": 15836, "cindy": 15837, "praising": 15838, "seldom": 15839, "busch": 15840, "discusses": 15841, "raleigh": 15842, "shortage": 15843, "ranged": 15844, "stanton": 15845, "encouragement": 15846, "firstly": 15847, "conceded": 15848, "overs": 15849, "temporal": 15850, "##uke": 15851, "cbe": 15852, "##bos": 15853, "woo": 15854, "certainty": 15855, "pumps": 15856, "##pton": 15857, "stalked": 15858, "##uli": 15859, "lizzie": 15860, "periodic": 15861, "thieves": 15862, "weaker": 15863, "##night": 15864, "gases": 15865, "shoving": 15866, "chooses": 15867, "wc": 15868, "##chemical": 15869, "prompting": 15870, "weights": 15871, "##kill": 15872, "robust": 15873, "flanked": 15874, "sticky": 15875, "hu": 15876, "tuberculosis": 15877, "##eb": 15878, "##eal": 15879, "christchurch": 15880, "resembled": 15881, "wallet": 15882, "reese": 15883, "inappropriate": 15884, "pictured": 15885, "distract": 15886, "fixing": 15887, "fiddle": 15888, "giggled": 15889, "burger": 15890, "heirs": 15891, "hairy": 15892, "mechanic": 15893, "torque": 15894, "apache": 15895, "obsessed": 15896, "chiefly": 15897, "cheng": 15898, "logging": 15899, "##tag": 15900, "extracted": 15901, "meaningful": 15902, "numb": 15903, "##vsky": 15904, "gloucestershire": 15905, "reminding": 15906, "##bay": 15907, "unite": 15908, "##lit": 15909, "breeds": 15910, "diminished": 15911, "clown": 15912, "glove": 15913, "1860s": 15914, "##ن": 15915, "##ug": 15916, "archibald": 15917, "focal": 15918, "freelance": 15919, "sliced": 15920, "depiction": 15921, "##yk": 15922, "organism": 15923, "switches": 15924, "sights": 15925, "stray": 15926, "crawling": 15927, "##ril": 15928, "lever": 15929, "leningrad": 15930, "interpretations": 15931, "loops": 15932, "anytime": 15933, "reel": 15934, "alicia": 15935, "delighted": 15936, "##ech": 15937, "inhaled": 15938, "xiv": 15939, "suitcase": 15940, "bernie": 15941, "vega": 15942, "licenses": 15943, "northampton": 15944, "exclusion": 15945, "induction": 15946, "monasteries": 15947, "racecourse": 15948, "homosexuality": 15949, "##right": 15950, "##sfield": 15951, "##rky": 15952, "dimitri": 15953, "michele": 15954, "alternatives": 15955, "ions": 15956, "commentators": 15957, "genuinely": 15958, "objected": 15959, "pork": 15960, "hospitality": 15961, "fencing": 15962, "stephan": 15963, "warships": 15964, "peripheral": 15965, "wit": 15966, "drunken": 15967, "wrinkled": 15968, "quentin": 15969, "spends": 15970, "departing": 15971, "chung": 15972, "numerical": 15973, "spokesperson": 15974, "##zone": 15975, "johannesburg": 15976, "caliber": 15977, "killers": 15978, "##udge": 15979, "assumes": 15980, "neatly": 15981, "demographic": 15982, "abigail": 15983, "bloc": 15984, "##vel": 15985, "mounting": 15986, "##lain": 15987, "bentley": 15988, "slightest": 15989, "xu": 15990, "recipients": 15991, "##jk": 15992, "merlin": 15993, "##writer": 15994, "seniors": 15995, "prisons": 15996, "blinking": 15997, "hindwings": 15998, "flickered": 15999, "kappa": 16000, "##hel": 16001, "80s": 16002, "strengthening": 16003, "appealing": 16004, "brewing": 16005, "gypsy": 16006, "mali": 16007, "lashes": 16008, "hulk": 16009, "unpleasant": 16010, "harassment": 16011, "bio": 16012, "treaties": 16013, "predict": 16014, "instrumentation": 16015, "pulp": 16016, "troupe": 16017, "boiling": 16018, "mantle": 16019, "##ffe": 16020, "ins": 16021, "##vn": 16022, "dividing": 16023, "handles": 16024, "verbs": 16025, "##onal": 16026, "coconut": 16027, "senegal": 16028, "340": 16029, "thorough": 16030, "gum": 16031, "momentarily": 16032, "##sto": 16033, "cocaine": 16034, "panicked": 16035, "destined": 16036, "##turing": 16037, "teatro": 16038, "denying": 16039, "weary": 16040, "captained": 16041, "mans": 16042, "##hawks": 16043, "##code": 16044, "wakefield": 16045, "bollywood": 16046, "thankfully": 16047, "##16": 16048, "cyril": 16049, "##wu": 16050, "amendments": 16051, "##bahn": 16052, "consultation": 16053, "stud": 16054, "reflections": 16055, "kindness": 16056, "1787": 16057, "internally": 16058, "##ovo": 16059, "tex": 16060, "mosaic": 16061, "distribute": 16062, "paddy": 16063, "seeming": 16064, "143": 16065, "##hic": 16066, "piers": 16067, "##15": 16068, "##mura": 16069, "##verse": 16070, "popularly": 16071, "winger": 16072, "kang": 16073, "sentinel": 16074, "mccoy": 16075, "##anza": 16076, "covenant": 16077, "##bag": 16078, "verge": 16079, "fireworks": 16080, "suppress": 16081, "thrilled": 16082, "dominate": 16083, "##jar": 16084, "swansea": 16085, "##60": 16086, "142": 16087, "reconciliation": 16088, "##ndi": 16089, "stiffened": 16090, "cue": 16091, "dorian": 16092, "##uf": 16093, "damascus": 16094, "amor": 16095, "ida": 16096, "foremost": 16097, "##aga": 16098, "porsche": 16099, "unseen": 16100, "dir": 16101, "##had": 16102, "##azi": 16103, "stony": 16104, "lexi": 16105, "melodies": 16106, "##nko": 16107, "angular": 16108, "integer": 16109, "podcast": 16110, "ants": 16111, "inherent": 16112, "jaws": 16113, "justify": 16114, "persona": 16115, "##olved": 16116, "josephine": 16117, "##nr": 16118, "##ressed": 16119, "customary": 16120, "flashes": 16121, "gala": 16122, "cyrus": 16123, "glaring": 16124, "backyard": 16125, "ariel": 16126, "physiology": 16127, "greenland": 16128, "html": 16129, "stir": 16130, "avon": 16131, "atletico": 16132, "finch": 16133, "methodology": 16134, "ked": 16135, "##lent": 16136, "mas": 16137, "catholicism": 16138, "townsend": 16139, "branding": 16140, "quincy": 16141, "fits": 16142, "containers": 16143, "1777": 16144, "ashore": 16145, "aragon": 16146, "##19": 16147, "forearm": 16148, "poisoning": 16149, "##sd": 16150, "adopting": 16151, "conquer": 16152, "grinding": 16153, "amnesty": 16154, "keller": 16155, "finances": 16156, "evaluate": 16157, "forged": 16158, "lankan": 16159, "instincts": 16160, "##uto": 16161, "guam": 16162, "bosnian": 16163, "photographed": 16164, "workplace": 16165, "desirable": 16166, "protector": 16167, "##dog": 16168, "allocation": 16169, "intently": 16170, "encourages": 16171, "willy": 16172, "##sten": 16173, "bodyguard": 16174, "electro": 16175, "brighter": 16176, "##ν": 16177, "bihar": 16178, "##chev": 16179, "lasts": 16180, "opener": 16181, "amphibious": 16182, "sal": 16183, "verde": 16184, "arte": 16185, "##cope": 16186, "captivity": 16187, "vocabulary": 16188, "yields": 16189, "##tted": 16190, "agreeing": 16191, "desmond": 16192, "pioneered": 16193, "##chus": 16194, "strap": 16195, "campaigned": 16196, "railroads": 16197, "##ович": 16198, "emblem": 16199, "##dre": 16200, "stormed": 16201, "501": 16202, "##ulous": 16203, "marijuana": 16204, "northumberland": 16205, "##gn": 16206, "##nath": 16207, "bowen": 16208, "landmarks": 16209, "beaumont": 16210, "##qua": 16211, "danube": 16212, "##bler": 16213, "attorneys": 16214, "th": 16215, "ge": 16216, "flyers": 16217, "critique": 16218, "villains": 16219, "cass": 16220, "mutation": 16221, "acc": 16222, "##0s": 16223, "colombo": 16224, "mckay": 16225, "motif": 16226, "sampling": 16227, "concluding": 16228, "syndicate": 16229, "##rell": 16230, "neon": 16231, "stables": 16232, "ds": 16233, "warnings": 16234, "clint": 16235, "mourning": 16236, "wilkinson": 16237, "##tated": 16238, "merrill": 16239, "leopard": 16240, "evenings": 16241, "exhaled": 16242, "emil": 16243, "sonia": 16244, "ezra": 16245, "discrete": 16246, "stove": 16247, "farrell": 16248, "fifteenth": 16249, "prescribed": 16250, "superhero": 16251, "##rier": 16252, "worms": 16253, "helm": 16254, "wren": 16255, "##duction": 16256, "##hc": 16257, "expo": 16258, "##rator": 16259, "hq": 16260, "unfamiliar": 16261, "antony": 16262, "prevents": 16263, "acceleration": 16264, "fiercely": 16265, "mari": 16266, "painfully": 16267, "calculations": 16268, "cheaper": 16269, "ign": 16270, "clifton": 16271, "irvine": 16272, "davenport": 16273, "mozambique": 16274, "##np": 16275, "pierced": 16276, "##evich": 16277, "wonders": 16278, "##wig": 16279, "##cate": 16280, "##iling": 16281, "crusade": 16282, "ware": 16283, "##uel": 16284, "enzymes": 16285, "reasonably": 16286, "mls": 16287, "##coe": 16288, "mater": 16289, "ambition": 16290, "bunny": 16291, "eliot": 16292, "kernel": 16293, "##fin": 16294, "asphalt": 16295, "headmaster": 16296, "torah": 16297, "aden": 16298, "lush": 16299, "pins": 16300, "waived": 16301, "##care": 16302, "##yas": 16303, "joao": 16304, "substrate": 16305, "enforce": 16306, "##grad": 16307, "##ules": 16308, "alvarez": 16309, "selections": 16310, "epidemic": 16311, "tempted": 16312, "##bit": 16313, "bremen": 16314, "translates": 16315, "ensured": 16316, "waterfront": 16317, "29th": 16318, "forrest": 16319, "manny": 16320, "malone": 16321, "kramer": 16322, "reigning": 16323, "cookies": 16324, "simpler": 16325, "absorption": 16326, "205": 16327, "engraved": 16328, "##ffy": 16329, "evaluated": 16330, "1778": 16331, "haze": 16332, "146": 16333, "comforting": 16334, "crossover": 16335, "##abe": 16336, "thorn": 16337, "##rift": 16338, "##imo": 16339, "##pop": 16340, "suppression": 16341, "fatigue": 16342, "cutter": 16343, "##tr": 16344, "201": 16345, "wurttemberg": 16346, "##orf": 16347, "enforced": 16348, "hovering": 16349, "proprietary": 16350, "gb": 16351, "samurai": 16352, "syllable": 16353, "ascent": 16354, "lacey": 16355, "tick": 16356, "lars": 16357, "tractor": 16358, "merchandise": 16359, "rep": 16360, "bouncing": 16361, "defendants": 16362, "##yre": 16363, "huntington": 16364, "##ground": 16365, "##oko": 16366, "standardized": 16367, "##hor": 16368, "##hima": 16369, "assassinated": 16370, "nu": 16371, "predecessors": 16372, "rainy": 16373, "liar": 16374, "assurance": 16375, "lyrical": 16376, "##uga": 16377, "secondly": 16378, "flattened": 16379, "ios": 16380, "parameter": 16381, "undercover": 16382, "##mity": 16383, "bordeaux": 16384, "punish": 16385, "ridges": 16386, "markers": 16387, "exodus": 16388, "inactive": 16389, "hesitate": 16390, "debbie": 16391, "nyc": 16392, "pledge": 16393, "savoy": 16394, "nagar": 16395, "offset": 16396, "organist": 16397, "##tium": 16398, "hesse": 16399, "marin": 16400, "converting": 16401, "##iver": 16402, "diagram": 16403, "propulsion": 16404, "pu": 16405, "validity": 16406, "reverted": 16407, "supportive": 16408, "##dc": 16409, "ministries": 16410, "clans": 16411, "responds": 16412, "proclamation": 16413, "##inae": 16414, "##ø": 16415, "##rea": 16416, "ein": 16417, "pleading": 16418, "patriot": 16419, "sf": 16420, "birch": 16421, "islanders": 16422, "strauss": 16423, "hates": 16424, "##dh": 16425, "brandenburg": 16426, "concession": 16427, "rd": 16428, "##ob": 16429, "1900s": 16430, "killings": 16431, "textbook": 16432, "antiquity": 16433, "cinematography": 16434, "wharf": 16435, "embarrassing": 16436, "setup": 16437, "creed": 16438, "farmland": 16439, "inequality": 16440, "centred": 16441, "signatures": 16442, "fallon": 16443, "370": 16444, "##ingham": 16445, "##uts": 16446, "ceylon": 16447, "gazing": 16448, "directive": 16449, "laurie": 16450, "##tern": 16451, "globally": 16452, "##uated": 16453, "##dent": 16454, "allah": 16455, "excavation": 16456, "threads": 16457, "##cross": 16458, "148": 16459, "frantically": 16460, "icc": 16461, "utilize": 16462, "determines": 16463, "respiratory": 16464, "thoughtful": 16465, "receptions": 16466, "##dicate": 16467, "merging": 16468, "chandra": 16469, "seine": 16470, "147": 16471, "builders": 16472, "builds": 16473, "diagnostic": 16474, "dev": 16475, "visibility": 16476, "goddamn": 16477, "analyses": 16478, "dhaka": 16479, "cho": 16480, "proves": 16481, "chancel": 16482, "concurrent": 16483, "curiously": 16484, "canadians": 16485, "pumped": 16486, "restoring": 16487, "1850s": 16488, "turtles": 16489, "jaguar": 16490, "sinister": 16491, "spinal": 16492, "traction": 16493, "declan": 16494, "vows": 16495, "1784": 16496, "glowed": 16497, "capitalism": 16498, "swirling": 16499, "install": 16500, "universidad": 16501, "##lder": 16502, "##oat": 16503, "soloist": 16504, "##genic": 16505, "##oor": 16506, "coincidence": 16507, "beginnings": 16508, "nissan": 16509, "dip": 16510, "resorts": 16511, "caucasus": 16512, "combustion": 16513, "infectious": 16514, "##eno": 16515, "pigeon": 16516, "serpent": 16517, "##itating": 16518, "conclude": 16519, "masked": 16520, "salad": 16521, "jew": 16522, "##gr": 16523, "surreal": 16524, "toni": 16525, "##wc": 16526, "harmonica": 16527, "151": 16528, "##gins": 16529, "##etic": 16530, "##coat": 16531, "fishermen": 16532, "intending": 16533, "bravery": 16534, "##wave": 16535, "klaus": 16536, "titan": 16537, "wembley": 16538, "taiwanese": 16539, "ransom": 16540, "40th": 16541, "incorrect": 16542, "hussein": 16543, "eyelids": 16544, "jp": 16545, "cooke": 16546, "dramas": 16547, "utilities": 16548, "##etta": 16549, "##print": 16550, "eisenhower": 16551, "principally": 16552, "granada": 16553, "lana": 16554, "##rak": 16555, "openings": 16556, "concord": 16557, "##bl": 16558, "bethany": 16559, "connie": 16560, "morality": 16561, "sega": 16562, "##mons": 16563, "##nard": 16564, "earnings": 16565, "##kara": 16566, "##cine": 16567, "wii": 16568, "communes": 16569, "##rel": 16570, "coma": 16571, "composing": 16572, "softened": 16573, "severed": 16574, "grapes": 16575, "##17": 16576, "nguyen": 16577, "analyzed": 16578, "warlord": 16579, "hubbard": 16580, "heavenly": 16581, "behave": 16582, "slovenian": 16583, "##hit": 16584, "##ony": 16585, "hailed": 16586, "filmmakers": 16587, "trance": 16588, "caldwell": 16589, "skye": 16590, "unrest": 16591, "coward": 16592, "likelihood": 16593, "##aging": 16594, "bern": 16595, "sci": 16596, "taliban": 16597, "honolulu": 16598, "propose": 16599, "##wang": 16600, "1700": 16601, "browser": 16602, "imagining": 16603, "cobra": 16604, "contributes": 16605, "dukes": 16606, "instinctively": 16607, "conan": 16608, "violinist": 16609, "##ores": 16610, "accessories": 16611, "gradual": 16612, "##amp": 16613, "quotes": 16614, "sioux": 16615, "##dating": 16616, "undertake": 16617, "intercepted": 16618, "sparkling": 16619, "compressed": 16620, "139": 16621, "fungus": 16622, "tombs": 16623, "haley": 16624, "imposing": 16625, "rests": 16626, "degradation": 16627, "lincolnshire": 16628, "retailers": 16629, "wetlands": 16630, "tulsa": 16631, "distributor": 16632, "dungeon": 16633, "nun": 16634, "greenhouse": 16635, "convey": 16636, "atlantis": 16637, "aft": 16638, "exits": 16639, "oman": 16640, "dresser": 16641, "lyons": 16642, "##sti": 16643, "joking": 16644, "eddy": 16645, "judgement": 16646, "omitted": 16647, "digits": 16648, "##cts": 16649, "##game": 16650, "juniors": 16651, "##rae": 16652, "cents": 16653, "stricken": 16654, "une": 16655, "##ngo": 16656, "wizards": 16657, "weir": 16658, "breton": 16659, "nan": 16660, "technician": 16661, "fibers": 16662, "liking": 16663, "royalty": 16664, "##cca": 16665, "154": 16666, "persia": 16667, "terribly": 16668, "magician": 16669, "##rable": 16670, "##unt": 16671, "vance": 16672, "cafeteria": 16673, "booker": 16674, "camille": 16675, "warmer": 16676, "##static": 16677, "consume": 16678, "cavern": 16679, "gaps": 16680, "compass": 16681, "contemporaries": 16682, "foyer": 16683, "soothing": 16684, "graveyard": 16685, "maj": 16686, "plunged": 16687, "blush": 16688, "##wear": 16689, "cascade": 16690, "demonstrates": 16691, "ordinance": 16692, "##nov": 16693, "boyle": 16694, "##lana": 16695, "rockefeller": 16696, "shaken": 16697, "banjo": 16698, "izzy": 16699, "##ense": 16700, "breathless": 16701, "vines": 16702, "##32": 16703, "##eman": 16704, "alterations": 16705, "chromosome": 16706, "dwellings": 16707, "feudal": 16708, "mole": 16709, "153": 16710, "catalonia": 16711, "relics": 16712, "tenant": 16713, "mandated": 16714, "##fm": 16715, "fridge": 16716, "hats": 16717, "honesty": 16718, "patented": 16719, "raul": 16720, "heap": 16721, "cruisers": 16722, "accusing": 16723, "enlightenment": 16724, "infants": 16725, "wherein": 16726, "chatham": 16727, "contractors": 16728, "zen": 16729, "affinity": 16730, "hc": 16731, "osborne": 16732, "piston": 16733, "156": 16734, "traps": 16735, "maturity": 16736, "##rana": 16737, "lagos": 16738, "##zal": 16739, "peering": 16740, "##nay": 16741, "attendant": 16742, "dealers": 16743, "protocols": 16744, "subset": 16745, "prospects": 16746, "biographical": 16747, "##cre": 16748, "artery": 16749, "##zers": 16750, "insignia": 16751, "nuns": 16752, "endured": 16753, "##eration": 16754, "recommend": 16755, "schwartz": 16756, "serbs": 16757, "berger": 16758, "cromwell": 16759, "crossroads": 16760, "##ctor": 16761, "enduring": 16762, "clasped": 16763, "grounded": 16764, "##bine": 16765, "marseille": 16766, "twitched": 16767, "abel": 16768, "choke": 16769, "https": 16770, "catalyst": 16771, "moldova": 16772, "italians": 16773, "##tist": 16774, "disastrous": 16775, "wee": 16776, "##oured": 16777, "##nti": 16778, "wwf": 16779, "nope": 16780, "##piration": 16781, "##asa": 16782, "expresses": 16783, "thumbs": 16784, "167": 16785, "##nza": 16786, "coca": 16787, "1781": 16788, "cheating": 16789, "##ption": 16790, "skipped": 16791, "sensory": 16792, "heidelberg": 16793, "spies": 16794, "satan": 16795, "dangers": 16796, "semifinal": 16797, "202": 16798, "bohemia": 16799, "whitish": 16800, "confusing": 16801, "shipbuilding": 16802, "relies": 16803, "surgeons": 16804, "landings": 16805, "ravi": 16806, "baku": 16807, "moor": 16808, "suffix": 16809, "alejandro": 16810, "##yana": 16811, "litre": 16812, "upheld": 16813, "##unk": 16814, "rajasthan": 16815, "##rek": 16816, "coaster": 16817, "insists": 16818, "posture": 16819, "scenarios": 16820, "etienne": 16821, "favoured": 16822, "appoint": 16823, "transgender": 16824, "elephants": 16825, "poked": 16826, "greenwood": 16827, "defences": 16828, "fulfilled": 16829, "militant": 16830, "somali": 16831, "1758": 16832, "chalk": 16833, "potent": 16834, "##ucci": 16835, "migrants": 16836, "wink": 16837, "assistants": 16838, "nos": 16839, "restriction": 16840, "activism": 16841, "niger": 16842, "##ario": 16843, "colon": 16844, "shaun": 16845, "##sat": 16846, "daphne": 16847, "##erated": 16848, "swam": 16849, "congregations": 16850, "reprise": 16851, "considerations": 16852, "magnet": 16853, "playable": 16854, "xvi": 16855, "##р": 16856, "overthrow": 16857, "tobias": 16858, "knob": 16859, "chavez": 16860, "coding": 16861, "##mers": 16862, "propped": 16863, "katrina": 16864, "orient": 16865, "newcomer": 16866, "##suke": 16867, "temperate": 16868, "##pool": 16869, "farmhouse": 16870, "interrogation": 16871, "##vd": 16872, "committing": 16873, "##vert": 16874, "forthcoming": 16875, "strawberry": 16876, "joaquin": 16877, "macau": 16878, "ponds": 16879, "shocking": 16880, "siberia": 16881, "##cellular": 16882, "chant": 16883, "contributors": 16884, "##nant": 16885, "##ologists": 16886, "sped": 16887, "absorb": 16888, "hail": 16889, "1782": 16890, "spared": 16891, "##hore": 16892, "barbados": 16893, "karate": 16894, "opus": 16895, "originates": 16896, "saul": 16897, "##xie": 16898, "evergreen": 16899, "leaped": 16900, "##rock": 16901, "correlation": 16902, "exaggerated": 16903, "weekday": 16904, "unification": 16905, "bump": 16906, "tracing": 16907, "brig": 16908, "afb": 16909, "pathways": 16910, "utilizing": 16911, "##ners": 16912, "mod": 16913, "mb": 16914, "disturbance": 16915, "kneeling": 16916, "##stad": 16917, "##guchi": 16918, "100th": 16919, "pune": 16920, "##thy": 16921, "decreasing": 16922, "168": 16923, "manipulation": 16924, "miriam": 16925, "academia": 16926, "ecosystem": 16927, "occupational": 16928, "rbi": 16929, "##lem": 16930, "rift": 16931, "##14": 16932, "rotary": 16933, "stacked": 16934, "incorporation": 16935, "awakening": 16936, "generators": 16937, "guerrero": 16938, "racist": 16939, "##omy": 16940, "cyber": 16941, "derivatives": 16942, "culminated": 16943, "allie": 16944, "annals": 16945, "panzer": 16946, "sainte": 16947, "wikipedia": 16948, "pops": 16949, "zu": 16950, "austro": 16951, "##vate": 16952, "algerian": 16953, "politely": 16954, "nicholson": 16955, "mornings": 16956, "educate": 16957, "tastes": 16958, "thrill": 16959, "dartmouth": 16960, "##gating": 16961, "db": 16962, "##jee": 16963, "regan": 16964, "differing": 16965, "concentrating": 16966, "choreography": 16967, "divinity": 16968, "##media": 16969, "pledged": 16970, "alexandre": 16971, "routing": 16972, "gregor": 16973, "madeline": 16974, "##idal": 16975, "apocalypse": 16976, "##hora": 16977, "gunfire": 16978, "culminating": 16979, "elves": 16980, "fined": 16981, "liang": 16982, "lam": 16983, "programmed": 16984, "tar": 16985, "guessing": 16986, "transparency": 16987, "gabrielle": 16988, "##gna": 16989, "cancellation": 16990, "flexibility": 16991, "##lining": 16992, "accession": 16993, "shea": 16994, "stronghold": 16995, "nets": 16996, "specializes": 16997, "##rgan": 16998, "abused": 16999, "hasan": 17000, "sgt": 17001, "ling": 17002, "exceeding": 17003, "##₄": 17004, "admiration": 17005, "supermarket": 17006, "##ark": 17007, "photographers": 17008, "specialised": 17009, "tilt": 17010, "resonance": 17011, "hmm": 17012, "perfume": 17013, "380": 17014, "sami": 17015, "threatens": 17016, "garland": 17017, "botany": 17018, "guarding": 17019, "boiled": 17020, "greet": 17021, "puppy": 17022, "russo": 17023, "supplier": 17024, "wilmington": 17025, "vibrant": 17026, "vijay": 17027, "##bius": 17028, "paralympic": 17029, "grumbled": 17030, "paige": 17031, "faa": 17032, "licking": 17033, "margins": 17034, "hurricanes": 17035, "##gong": 17036, "fest": 17037, "grenade": 17038, "ripping": 17039, "##uz": 17040, "counseling": 17041, "weigh": 17042, "##sian": 17043, "needles": 17044, "wiltshire": 17045, "edison": 17046, "costly": 17047, "##not": 17048, "fulton": 17049, "tramway": 17050, "redesigned": 17051, "staffordshire": 17052, "cache": 17053, "gasping": 17054, "watkins": 17055, "sleepy": 17056, "candidacy": 17057, "##group": 17058, "monkeys": 17059, "timeline": 17060, "throbbing": 17061, "##bid": 17062, "##sos": 17063, "berth": 17064, "uzbekistan": 17065, "vanderbilt": 17066, "bothering": 17067, "overturned": 17068, "ballots": 17069, "gem": 17070, "##iger": 17071, "sunglasses": 17072, "subscribers": 17073, "hooker": 17074, "compelling": 17075, "ang": 17076, "exceptionally": 17077, "saloon": 17078, "stab": 17079, "##rdi": 17080, "carla": 17081, "terrifying": 17082, "rom": 17083, "##vision": 17084, "coil": 17085, "##oids": 17086, "satisfying": 17087, "vendors": 17088, "31st": 17089, "mackay": 17090, "deities": 17091, "overlooked": 17092, "ambient": 17093, "bahamas": 17094, "felipe": 17095, "olympia": 17096, "whirled": 17097, "botanist": 17098, "advertised": 17099, "tugging": 17100, "##dden": 17101, "disciples": 17102, "morales": 17103, "unionist": 17104, "rites": 17105, "foley": 17106, "morse": 17107, "motives": 17108, "creepy": 17109, "##₀": 17110, "soo": 17111, "##sz": 17112, "bargain": 17113, "highness": 17114, "frightening": 17115, "turnpike": 17116, "tory": 17117, "reorganization": 17118, "##cer": 17119, "depict": 17120, "biographer": 17121, "##walk": 17122, "unopposed": 17123, "manifesto": 17124, "##gles": 17125, "institut": 17126, "emile": 17127, "accidental": 17128, "kapoor": 17129, "##dam": 17130, "kilkenny": 17131, "cortex": 17132, "lively": 17133, "##13": 17134, "romanesque": 17135, "jain": 17136, "shan": 17137, "cannons": 17138, "##ood": 17139, "##ske": 17140, "petrol": 17141, "echoing": 17142, "amalgamated": 17143, "disappears": 17144, "cautious": 17145, "proposes": 17146, "sanctions": 17147, "trenton": 17148, "##ر": 17149, "flotilla": 17150, "aus": 17151, "contempt": 17152, "tor": 17153, "canary": 17154, "cote": 17155, "theirs": 17156, "##hun": 17157, "conceptual": 17158, "deleted": 17159, "fascinating": 17160, "paso": 17161, "blazing": 17162, "elf": 17163, "honourable": 17164, "hutchinson": 17165, "##eiro": 17166, "##outh": 17167, "##zin": 17168, "surveyor": 17169, "tee": 17170, "amidst": 17171, "wooded": 17172, "reissue": 17173, "intro": 17174, "##ono": 17175, "cobb": 17176, "shelters": 17177, "newsletter": 17178, "hanson": 17179, "brace": 17180, "encoding": 17181, "confiscated": 17182, "dem": 17183, "caravan": 17184, "marino": 17185, "scroll": 17186, "melodic": 17187, "cows": 17188, "imam": 17189, "##adi": 17190, "##aneous": 17191, "northward": 17192, "searches": 17193, "biodiversity": 17194, "cora": 17195, "310": 17196, "roaring": 17197, "##bers": 17198, "connell": 17199, "theologian": 17200, "halo": 17201, "compose": 17202, "pathetic": 17203, "unmarried": 17204, "dynamo": 17205, "##oot": 17206, "az": 17207, "calculation": 17208, "toulouse": 17209, "deserves": 17210, "humour": 17211, "nr": 17212, "forgiveness": 17213, "tam": 17214, "undergone": 17215, "martyr": 17216, "pamela": 17217, "myths": 17218, "whore": 17219, "counselor": 17220, "hicks": 17221, "290": 17222, "heavens": 17223, "battleship": 17224, "electromagnetic": 17225, "##bbs": 17226, "stellar": 17227, "establishments": 17228, "presley": 17229, "hopped": 17230, "##chin": 17231, "temptation": 17232, "90s": 17233, "wills": 17234, "nas": 17235, "##yuan": 17236, "nhs": 17237, "##nya": 17238, "seminars": 17239, "##yev": 17240, "adaptations": 17241, "gong": 17242, "asher": 17243, "lex": 17244, "indicator": 17245, "sikh": 17246, "tobago": 17247, "cites": 17248, "goin": 17249, "##yte": 17250, "satirical": 17251, "##gies": 17252, "characterised": 17253, "correspond": 17254, "bubbles": 17255, "lure": 17256, "participates": 17257, "##vid": 17258, "eruption": 17259, "skate": 17260, "therapeutic": 17261, "1785": 17262, "canals": 17263, "wholesale": 17264, "defaulted": 17265, "sac": 17266, "460": 17267, "petit": 17268, "##zzled": 17269, "virgil": 17270, "leak": 17271, "ravens": 17272, "256": 17273, "portraying": 17274, "##yx": 17275, "ghetto": 17276, "creators": 17277, "dams": 17278, "portray": 17279, "vicente": 17280, "##rington": 17281, "fae": 17282, "namesake": 17283, "bounty": 17284, "##arium": 17285, "joachim": 17286, "##ota": 17287, "##iser": 17288, "aforementioned": 17289, "axle": 17290, "snout": 17291, "depended": 17292, "dismantled": 17293, "reuben": 17294, "480": 17295, "##ibly": 17296, "gallagher": 17297, "##lau": 17298, "##pd": 17299, "earnest": 17300, "##ieu": 17301, "##iary": 17302, "inflicted": 17303, "objections": 17304, "##llar": 17305, "asa": 17306, "gritted": 17307, "##athy": 17308, "jericho": 17309, "##sea": 17310, "##was": 17311, "flick": 17312, "underside": 17313, "ceramics": 17314, "undead": 17315, "substituted": 17316, "195": 17317, "eastward": 17318, "undoubtedly": 17319, "wheeled": 17320, "chimney": 17321, "##iche": 17322, "guinness": 17323, "cb": 17324, "##ager": 17325, "siding": 17326, "##bell": 17327, "traitor": 17328, "baptiste": 17329, "disguised": 17330, "inauguration": 17331, "149": 17332, "tipperary": 17333, "choreographer": 17334, "perched": 17335, "warmed": 17336, "stationary": 17337, "eco": 17338, "##ike": 17339, "##ntes": 17340, "bacterial": 17341, "##aurus": 17342, "flores": 17343, "phosphate": 17344, "##core": 17345, "attacker": 17346, "invaders": 17347, "alvin": 17348, "intersects": 17349, "a1": 17350, "indirectly": 17351, "immigrated": 17352, "businessmen": 17353, "cornelius": 17354, "valves": 17355, "narrated": 17356, "pill": 17357, "sober": 17358, "ul": 17359, "nationale": 17360, "monastic": 17361, "applicants": 17362, "scenery": 17363, "##jack": 17364, "161": 17365, "motifs": 17366, "constitutes": 17367, "cpu": 17368, "##osh": 17369, "jurisdictions": 17370, "sd": 17371, "tuning": 17372, "irritation": 17373, "woven": 17374, "##uddin": 17375, "fertility": 17376, "gao": 17377, "##erie": 17378, "antagonist": 17379, "impatient": 17380, "glacial": 17381, "hides": 17382, "boarded": 17383, "denominations": 17384, "interception": 17385, "##jas": 17386, "cookie": 17387, "nicola": 17388, "##tee": 17389, "algebraic": 17390, "marquess": 17391, "bahn": 17392, "parole": 17393, "buyers": 17394, "bait": 17395, "turbines": 17396, "paperwork": 17397, "bestowed": 17398, "natasha": 17399, "renee": 17400, "oceans": 17401, "purchases": 17402, "157": 17403, "vaccine": 17404, "215": 17405, "##tock": 17406, "fixtures": 17407, "playhouse": 17408, "integrate": 17409, "jai": 17410, "oswald": 17411, "intellectuals": 17412, "##cky": 17413, "booked": 17414, "nests": 17415, "mortimer": 17416, "##isi": 17417, "obsession": 17418, "sept": 17419, "##gler": 17420, "##sum": 17421, "440": 17422, "scrutiny": 17423, "simultaneous": 17424, "squinted": 17425, "##shin": 17426, "collects": 17427, "oven": 17428, "shankar": 17429, "penned": 17430, "remarkably": 17431, "##я": 17432, "slips": 17433, "luggage": 17434, "spectral": 17435, "1786": 17436, "collaborations": 17437, "louie": 17438, "consolidation": 17439, "##ailed": 17440, "##ivating": 17441, "420": 17442, "hoover": 17443, "blackpool": 17444, "harness": 17445, "ignition": 17446, "vest": 17447, "tails": 17448, "belmont": 17449, "mongol": 17450, "skinner": 17451, "##nae": 17452, "visually": 17453, "mage": 17454, "derry": 17455, "##tism": 17456, "##unce": 17457, "stevie": 17458, "transitional": 17459, "##rdy": 17460, "redskins": 17461, "drying": 17462, "prep": 17463, "prospective": 17464, "##21": 17465, "annoyance": 17466, "oversee": 17467, "##loaded": 17468, "fills": 17469, "##books": 17470, "##iki": 17471, "announces": 17472, "fda": 17473, "scowled": 17474, "respects": 17475, "prasad": 17476, "mystic": 17477, "tucson": 17478, "##vale": 17479, "revue": 17480, "springer": 17481, "bankrupt": 17482, "1772": 17483, "aristotle": 17484, "salvatore": 17485, "habsburg": 17486, "##geny": 17487, "dal": 17488, "natal": 17489, "nut": 17490, "pod": 17491, "chewing": 17492, "darts": 17493, "moroccan": 17494, "walkover": 17495, "rosario": 17496, "lenin": 17497, "punjabi": 17498, "##ße": 17499, "grossed": 17500, "scattering": 17501, "wired": 17502, "invasive": 17503, "hui": 17504, "polynomial": 17505, "corridors": 17506, "wakes": 17507, "gina": 17508, "portrays": 17509, "##cratic": 17510, "arid": 17511, "retreating": 17512, "erich": 17513, "irwin": 17514, "sniper": 17515, "##dha": 17516, "linen": 17517, "lindsey": 17518, "maneuver": 17519, "butch": 17520, "shutting": 17521, "socio": 17522, "bounce": 17523, "commemorative": 17524, "postseason": 17525, "jeremiah": 17526, "pines": 17527, "275": 17528, "mystical": 17529, "beads": 17530, "bp": 17531, "abbas": 17532, "furnace": 17533, "bidding": 17534, "consulted": 17535, "assaulted": 17536, "empirical": 17537, "rubble": 17538, "enclosure": 17539, "sob": 17540, "weakly": 17541, "cancel": 17542, "polly": 17543, "yielded": 17544, "##emann": 17545, "curly": 17546, "prediction": 17547, "battered": 17548, "70s": 17549, "vhs": 17550, "jacqueline": 17551, "render": 17552, "sails": 17553, "barked": 17554, "detailing": 17555, "grayson": 17556, "riga": 17557, "sloane": 17558, "raging": 17559, "##yah": 17560, "herbs": 17561, "bravo": 17562, "##athlon": 17563, "alloy": 17564, "giggle": 17565, "imminent": 17566, "suffers": 17567, "assumptions": 17568, "waltz": 17569, "##itate": 17570, "accomplishments": 17571, "##ited": 17572, "bathing": 17573, "remixed": 17574, "deception": 17575, "prefix": 17576, "##emia": 17577, "deepest": 17578, "##tier": 17579, "##eis": 17580, "balkan": 17581, "frogs": 17582, "##rong": 17583, "slab": 17584, "##pate": 17585, "philosophers": 17586, "peterborough": 17587, "grains": 17588, "imports": 17589, "dickinson": 17590, "rwanda": 17591, "##atics": 17592, "1774": 17593, "dirk": 17594, "lan": 17595, "tablets": 17596, "##rove": 17597, "clone": 17598, "##rice": 17599, "caretaker": 17600, "hostilities": 17601, "mclean": 17602, "##gre": 17603, "regimental": 17604, "treasures": 17605, "norms": 17606, "impose": 17607, "tsar": 17608, "tango": 17609, "diplomacy": 17610, "variously": 17611, "complain": 17612, "192": 17613, "recognise": 17614, "arrests": 17615, "1779": 17616, "celestial": 17617, "pulitzer": 17618, "##dus": 17619, "bing": 17620, "libretto": 17621, "##moor": 17622, "adele": 17623, "splash": 17624, "##rite": 17625, "expectation": 17626, "lds": 17627, "confronts": 17628, "##izer": 17629, "spontaneous": 17630, "harmful": 17631, "wedge": 17632, "entrepreneurs": 17633, "buyer": 17634, "##ope": 17635, "bilingual": 17636, "translate": 17637, "rugged": 17638, "conner": 17639, "circulated": 17640, "uae": 17641, "eaton": 17642, "##gra": 17643, "##zzle": 17644, "lingered": 17645, "lockheed": 17646, "vishnu": 17647, "reelection": 17648, "alonso": 17649, "##oom": 17650, "joints": 17651, "yankee": 17652, "headline": 17653, "cooperate": 17654, "heinz": 17655, "laureate": 17656, "invading": 17657, "##sford": 17658, "echoes": 17659, "scandinavian": 17660, "##dham": 17661, "hugging": 17662, "vitamin": 17663, "salute": 17664, "micah": 17665, "hind": 17666, "trader": 17667, "##sper": 17668, "radioactive": 17669, "##ndra": 17670, "militants": 17671, "poisoned": 17672, "ratified": 17673, "remark": 17674, "campeonato": 17675, "deprived": 17676, "wander": 17677, "prop": 17678, "##dong": 17679, "outlook": 17680, "##tani": 17681, "##rix": 17682, "##eye": 17683, "chiang": 17684, "darcy": 17685, "##oping": 17686, "mandolin": 17687, "spice": 17688, "statesman": 17689, "babylon": 17690, "182": 17691, "walled": 17692, "forgetting": 17693, "afro": 17694, "##cap": 17695, "158": 17696, "giorgio": 17697, "buffer": 17698, "##polis": 17699, "planetary": 17700, "##gis": 17701, "overlap": 17702, "terminals": 17703, "kinda": 17704, "centenary": 17705, "##bir": 17706, "arising": 17707, "manipulate": 17708, "elm": 17709, "ke": 17710, "1770": 17711, "ak": 17712, "##tad": 17713, "chrysler": 17714, "mapped": 17715, "moose": 17716, "pomeranian": 17717, "quad": 17718, "macarthur": 17719, "assemblies": 17720, "shoreline": 17721, "recalls": 17722, "stratford": 17723, "##rted": 17724, "noticeable": 17725, "##evic": 17726, "imp": 17727, "##rita": 17728, "##sque": 17729, "accustomed": 17730, "supplying": 17731, "tents": 17732, "disgusted": 17733, "vogue": 17734, "sipped": 17735, "filters": 17736, "khz": 17737, "reno": 17738, "selecting": 17739, "luftwaffe": 17740, "mcmahon": 17741, "tyne": 17742, "masterpiece": 17743, "carriages": 17744, "collided": 17745, "dunes": 17746, "exercised": 17747, "flare": 17748, "remembers": 17749, "muzzle": 17750, "##mobile": 17751, "heck": 17752, "##rson": 17753, "burgess": 17754, "lunged": 17755, "middleton": 17756, "boycott": 17757, "bilateral": 17758, "##sity": 17759, "hazardous": 17760, "lumpur": 17761, "multiplayer": 17762, "spotlight": 17763, "jackets": 17764, "goldman": 17765, "liege": 17766, "porcelain": 17767, "rag": 17768, "waterford": 17769, "benz": 17770, "attracts": 17771, "hopeful": 17772, "battling": 17773, "ottomans": 17774, "kensington": 17775, "baked": 17776, "hymns": 17777, "cheyenne": 17778, "lattice": 17779, "levine": 17780, "borrow": 17781, "polymer": 17782, "clashes": 17783, "michaels": 17784, "monitored": 17785, "commitments": 17786, "denounced": 17787, "##25": 17788, "##von": 17789, "cavity": 17790, "##oney": 17791, "hobby": 17792, "akin": 17793, "##holders": 17794, "futures": 17795, "intricate": 17796, "cornish": 17797, "patty": 17798, "##oned": 17799, "illegally": 17800, "dolphin": 17801, "##lag": 17802, "barlow": 17803, "yellowish": 17804, "maddie": 17805, "apologized": 17806, "luton": 17807, "plagued": 17808, "##puram": 17809, "nana": 17810, "##rds": 17811, "sway": 17812, "fanny": 17813, "łodz": 17814, "##rino": 17815, "psi": 17816, "suspicions": 17817, "hanged": 17818, "##eding": 17819, "initiate": 17820, "charlton": 17821, "##por": 17822, "nak": 17823, "competent": 17824, "235": 17825, "analytical": 17826, "annex": 17827, "wardrobe": 17828, "reservations": 17829, "##rma": 17830, "sect": 17831, "162": 17832, "fairfax": 17833, "hedge": 17834, "piled": 17835, "buckingham": 17836, "uneven": 17837, "bauer": 17838, "simplicity": 17839, "snyder": 17840, "interpret": 17841, "accountability": 17842, "donors": 17843, "moderately": 17844, "byrd": 17845, "continents": 17846, "##cite": 17847, "##max": 17848, "disciple": 17849, "hr": 17850, "jamaican": 17851, "ping": 17852, "nominees": 17853, "##uss": 17854, "mongolian": 17855, "diver": 17856, "attackers": 17857, "eagerly": 17858, "ideological": 17859, "pillows": 17860, "miracles": 17861, "apartheid": 17862, "revolver": 17863, "sulfur": 17864, "clinics": 17865, "moran": 17866, "163": 17867, "##enko": 17868, "ile": 17869, "katy": 17870, "rhetoric": 17871, "##icated": 17872, "chronology": 17873, "recycling": 17874, "##hrer": 17875, "elongated": 17876, "mughal": 17877, "pascal": 17878, "profiles": 17879, "vibration": 17880, "databases": 17881, "domination": 17882, "##fare": 17883, "##rant": 17884, "matthias": 17885, "digest": 17886, "rehearsal": 17887, "polling": 17888, "weiss": 17889, "initiation": 17890, "reeves": 17891, "clinging": 17892, "flourished": 17893, "impress": 17894, "ngo": 17895, "##hoff": 17896, "##ume": 17897, "buckley": 17898, "symposium": 17899, "rhythms": 17900, "weed": 17901, "emphasize": 17902, "transforming": 17903, "##taking": 17904, "##gence": 17905, "##yman": 17906, "accountant": 17907, "analyze": 17908, "flicker": 17909, "foil": 17910, "priesthood": 17911, "voluntarily": 17912, "decreases": 17913, "##80": 17914, "##hya": 17915, "slater": 17916, "sv": 17917, "charting": 17918, "mcgill": 17919, "##lde": 17920, "moreno": 17921, "##iu": 17922, "besieged": 17923, "zur": 17924, "robes": 17925, "##phic": 17926, "admitting": 17927, "api": 17928, "deported": 17929, "turmoil": 17930, "peyton": 17931, "earthquakes": 17932, "##ares": 17933, "nationalists": 17934, "beau": 17935, "clair": 17936, "brethren": 17937, "interrupt": 17938, "welch": 17939, "curated": 17940, "galerie": 17941, "requesting": 17942, "164": 17943, "##ested": 17944, "impending": 17945, "steward": 17946, "viper": 17947, "##vina": 17948, "complaining": 17949, "beautifully": 17950, "brandy": 17951, "foam": 17952, "nl": 17953, "1660": 17954, "##cake": 17955, "alessandro": 17956, "punches": 17957, "laced": 17958, "explanations": 17959, "##lim": 17960, "attribute": 17961, "clit": 17962, "reggie": 17963, "discomfort": 17964, "##cards": 17965, "smoothed": 17966, "whales": 17967, "##cene": 17968, "adler": 17969, "countered": 17970, "duffy": 17971, "disciplinary": 17972, "widening": 17973, "recipe": 17974, "reliance": 17975, "conducts": 17976, "goats": 17977, "gradient": 17978, "preaching": 17979, "##shaw": 17980, "matilda": 17981, "quasi": 17982, "striped": 17983, "meridian": 17984, "cannabis": 17985, "cordoba": 17986, "certificates": 17987, "##agh": 17988, "##tering": 17989, "graffiti": 17990, "hangs": 17991, "pilgrims": 17992, "repeats": 17993, "##ych": 17994, "revive": 17995, "urine": 17996, "etat": 17997, "##hawk": 17998, "fueled": 17999, "belts": 18000, "fuzzy": 18001, "susceptible": 18002, "##hang": 18003, "mauritius": 18004, "salle": 18005, "sincere": 18006, "beers": 18007, "hooks": 18008, "##cki": 18009, "arbitration": 18010, "entrusted": 18011, "advise": 18012, "sniffed": 18013, "seminar": 18014, "junk": 18015, "donnell": 18016, "processors": 18017, "principality": 18018, "strapped": 18019, "celia": 18020, "mendoza": 18021, "everton": 18022, "fortunes": 18023, "prejudice": 18024, "starving": 18025, "reassigned": 18026, "steamer": 18027, "##lund": 18028, "tuck": 18029, "evenly": 18030, "foreman": 18031, "##ffen": 18032, "dans": 18033, "375": 18034, "envisioned": 18035, "slit": 18036, "##xy": 18037, "baseman": 18038, "liberia": 18039, "rosemary": 18040, "##weed": 18041, "electrified": 18042, "periodically": 18043, "potassium": 18044, "stride": 18045, "contexts": 18046, "sperm": 18047, "slade": 18048, "mariners": 18049, "influx": 18050, "bianca": 18051, "subcommittee": 18052, "##rane": 18053, "spilling": 18054, "icao": 18055, "estuary": 18056, "##nock": 18057, "delivers": 18058, "iphone": 18059, "##ulata": 18060, "isa": 18061, "mira": 18062, "bohemian": 18063, "dessert": 18064, "##sbury": 18065, "welcoming": 18066, "proudly": 18067, "slowing": 18068, "##chs": 18069, "musee": 18070, "ascension": 18071, "russ": 18072, "##vian": 18073, "waits": 18074, "##psy": 18075, "africans": 18076, "exploit": 18077, "##morphic": 18078, "gov": 18079, "eccentric": 18080, "crab": 18081, "peck": 18082, "##ull": 18083, "entrances": 18084, "formidable": 18085, "marketplace": 18086, "groom": 18087, "bolted": 18088, "metabolism": 18089, "patton": 18090, "robbins": 18091, "courier": 18092, "payload": 18093, "endure": 18094, "##ifier": 18095, "andes": 18096, "refrigerator": 18097, "##pr": 18098, "ornate": 18099, "##uca": 18100, "ruthless": 18101, "illegitimate": 18102, "masonry": 18103, "strasbourg": 18104, "bikes": 18105, "adobe": 18106, "##³": 18107, "apples": 18108, "quintet": 18109, "willingly": 18110, "niche": 18111, "bakery": 18112, "corpses": 18113, "energetic": 18114, "##cliffe": 18115, "##sser": 18116, "##ards": 18117, "177": 18118, "centimeters": 18119, "centro": 18120, "fuscous": 18121, "cretaceous": 18122, "rancho": 18123, "##yde": 18124, "andrei": 18125, "telecom": 18126, "tottenham": 18127, "oasis": 18128, "ordination": 18129, "vulnerability": 18130, "presiding": 18131, "corey": 18132, "cp": 18133, "penguins": 18134, "sims": 18135, "##pis": 18136, "malawi": 18137, "piss": 18138, "##48": 18139, "correction": 18140, "##cked": 18141, "##ffle": 18142, "##ryn": 18143, "countdown": 18144, "detectives": 18145, "psychiatrist": 18146, "psychedelic": 18147, "dinosaurs": 18148, "blouse": 18149, "##get": 18150, "choi": 18151, "vowed": 18152, "##oz": 18153, "randomly": 18154, "##pol": 18155, "49ers": 18156, "scrub": 18157, "blanche": 18158, "bruins": 18159, "dusseldorf": 18160, "##using": 18161, "unwanted": 18162, "##ums": 18163, "212": 18164, "dominique": 18165, "elevations": 18166, "headlights": 18167, "om": 18168, "laguna": 18169, "##oga": 18170, "1750": 18171, "famously": 18172, "ignorance": 18173, "shrewsbury": 18174, "##aine": 18175, "ajax": 18176, "breuning": 18177, "che": 18178, "confederacy": 18179, "greco": 18180, "overhaul": 18181, "##screen": 18182, "paz": 18183, "skirts": 18184, "disagreement": 18185, "cruelty": 18186, "jagged": 18187, "phoebe": 18188, "shifter": 18189, "hovered": 18190, "viruses": 18191, "##wes": 18192, "mandy": 18193, "##lined": 18194, "##gc": 18195, "landlord": 18196, "squirrel": 18197, "dashed": 18198, "##ι": 18199, "ornamental": 18200, "gag": 18201, "wally": 18202, "grange": 18203, "literal": 18204, "spurs": 18205, "undisclosed": 18206, "proceeding": 18207, "yin": 18208, "##text": 18209, "billie": 18210, "orphan": 18211, "spanned": 18212, "humidity": 18213, "indy": 18214, "weighted": 18215, "presentations": 18216, "explosions": 18217, "lucian": 18218, "##tary": 18219, "vaughn": 18220, "hindus": 18221, "##anga": 18222, "##hell": 18223, "psycho": 18224, "171": 18225, "daytona": 18226, "protects": 18227, "efficiently": 18228, "rematch": 18229, "sly": 18230, "tandem": 18231, "##oya": 18232, "rebranded": 18233, "impaired": 18234, "hee": 18235, "metropolis": 18236, "peach": 18237, "godfrey": 18238, "diaspora": 18239, "ethnicity": 18240, "prosperous": 18241, "gleaming": 18242, "dar": 18243, "grossing": 18244, "playback": 18245, "##rden": 18246, "stripe": 18247, "pistols": 18248, "##tain": 18249, "births": 18250, "labelled": 18251, "##cating": 18252, "172": 18253, "rudy": 18254, "alba": 18255, "##onne": 18256, "aquarium": 18257, "hostility": 18258, "##gb": 18259, "##tase": 18260, "shudder": 18261, "sumatra": 18262, "hardest": 18263, "lakers": 18264, "consonant": 18265, "creeping": 18266, "demos": 18267, "homicide": 18268, "capsule": 18269, "zeke": 18270, "liberties": 18271, "expulsion": 18272, "pueblo": 18273, "##comb": 18274, "trait": 18275, "transporting": 18276, "##ddin": 18277, "##neck": 18278, "##yna": 18279, "depart": 18280, "gregg": 18281, "mold": 18282, "ledge": 18283, "hangar": 18284, "oldham": 18285, "playboy": 18286, "termination": 18287, "analysts": 18288, "gmbh": 18289, "romero": 18290, "##itic": 18291, "insist": 18292, "cradle": 18293, "filthy": 18294, "brightness": 18295, "slash": 18296, "shootout": 18297, "deposed": 18298, "bordering": 18299, "##truct": 18300, "isis": 18301, "microwave": 18302, "tumbled": 18303, "sheltered": 18304, "cathy": 18305, "werewolves": 18306, "messy": 18307, "andersen": 18308, "convex": 18309, "clapped": 18310, "clinched": 18311, "satire": 18312, "wasting": 18313, "edo": 18314, "vc": 18315, "rufus": 18316, "##jak": 18317, "mont": 18318, "##etti": 18319, "poznan": 18320, "##keeping": 18321, "restructuring": 18322, "transverse": 18323, "##rland": 18324, "azerbaijani": 18325, "slovene": 18326, "gestures": 18327, "roommate": 18328, "choking": 18329, "shear": 18330, "##quist": 18331, "vanguard": 18332, "oblivious": 18333, "##hiro": 18334, "disagreed": 18335, "baptism": 18336, "##lich": 18337, "coliseum": 18338, "##aceae": 18339, "salvage": 18340, "societe": 18341, "cory": 18342, "locke": 18343, "relocation": 18344, "relying": 18345, "versailles": 18346, "ahl": 18347, "swelling": 18348, "##elo": 18349, "cheerful": 18350, "##word": 18351, "##edes": 18352, "gin": 18353, "sarajevo": 18354, "obstacle": 18355, "diverted": 18356, "##nac": 18357, "messed": 18358, "thoroughbred": 18359, "fluttered": 18360, "utrecht": 18361, "chewed": 18362, "acquaintance": 18363, "assassins": 18364, "dispatch": 18365, "mirza": 18366, "##wart": 18367, "nike": 18368, "salzburg": 18369, "swell": 18370, "yen": 18371, "##gee": 18372, "idle": 18373, "ligue": 18374, "samson": 18375, "##nds": 18376, "##igh": 18377, "playful": 18378, "spawned": 18379, "##cise": 18380, "tease": 18381, "##case": 18382, "burgundy": 18383, "##bot": 18384, "stirring": 18385, "skeptical": 18386, "interceptions": 18387, "marathi": 18388, "##dies": 18389, "bedrooms": 18390, "aroused": 18391, "pinch": 18392, "##lik": 18393, "preferences": 18394, "tattoos": 18395, "buster": 18396, "digitally": 18397, "projecting": 18398, "rust": 18399, "##ital": 18400, "kitten": 18401, "priorities": 18402, "addison": 18403, "pseudo": 18404, "##guard": 18405, "dusk": 18406, "icons": 18407, "sermon": 18408, "##psis": 18409, "##iba": 18410, "bt": 18411, "##lift": 18412, "##xt": 18413, "ju": 18414, "truce": 18415, "rink": 18416, "##dah": 18417, "##wy": 18418, "defects": 18419, "psychiatry": 18420, "offences": 18421, "calculate": 18422, "glucose": 18423, "##iful": 18424, "##rized": 18425, "##unda": 18426, "francaise": 18427, "##hari": 18428, "richest": 18429, "warwickshire": 18430, "carly": 18431, "1763": 18432, "purity": 18433, "redemption": 18434, "lending": 18435, "##cious": 18436, "muse": 18437, "bruises": 18438, "cerebral": 18439, "aero": 18440, "carving": 18441, "##name": 18442, "preface": 18443, "terminology": 18444, "invade": 18445, "monty": 18446, "##int": 18447, "anarchist": 18448, "blurred": 18449, "##iled": 18450, "rossi": 18451, "treats": 18452, "guts": 18453, "shu": 18454, "foothills": 18455, "ballads": 18456, "undertaking": 18457, "premise": 18458, "cecilia": 18459, "affiliates": 18460, "blasted": 18461, "conditional": 18462, "wilder": 18463, "minors": 18464, "drone": 18465, "rudolph": 18466, "buffy": 18467, "swallowing": 18468, "horton": 18469, "attested": 18470, "##hop": 18471, "rutherford": 18472, "howell": 18473, "primetime": 18474, "livery": 18475, "penal": 18476, "##bis": 18477, "minimize": 18478, "hydro": 18479, "wrecked": 18480, "wrought": 18481, "palazzo": 18482, "##gling": 18483, "cans": 18484, "vernacular": 18485, "friedman": 18486, "nobleman": 18487, "shale": 18488, "walnut": 18489, "danielle": 18490, "##ection": 18491, "##tley": 18492, "sears": 18493, "##kumar": 18494, "chords": 18495, "lend": 18496, "flipping": 18497, "streamed": 18498, "por": 18499, "dracula": 18500, "gallons": 18501, "sacrifices": 18502, "gamble": 18503, "orphanage": 18504, "##iman": 18505, "mckenzie": 18506, "##gible": 18507, "boxers": 18508, "daly": 18509, "##balls": 18510, "##ان": 18511, "208": 18512, "##ific": 18513, "##rative": 18514, "##iq": 18515, "exploited": 18516, "slated": 18517, "##uity": 18518, "circling": 18519, "hillary": 18520, "pinched": 18521, "goldberg": 18522, "provost": 18523, "campaigning": 18524, "lim": 18525, "piles": 18526, "ironically": 18527, "jong": 18528, "mohan": 18529, "successors": 18530, "usaf": 18531, "##tem": 18532, "##ught": 18533, "autobiographical": 18534, "haute": 18535, "preserves": 18536, "##ending": 18537, "acquitted": 18538, "comparisons": 18539, "203": 18540, "hydroelectric": 18541, "gangs": 18542, "cypriot": 18543, "torpedoes": 18544, "rushes": 18545, "chrome": 18546, "derive": 18547, "bumps": 18548, "instability": 18549, "fiat": 18550, "pets": 18551, "##mbe": 18552, "silas": 18553, "dye": 18554, "reckless": 18555, "settler": 18556, "##itation": 18557, "info": 18558, "heats": 18559, "##writing": 18560, "176": 18561, "canonical": 18562, "maltese": 18563, "fins": 18564, "mushroom": 18565, "stacy": 18566, "aspen": 18567, "avid": 18568, "##kur": 18569, "##loading": 18570, "vickers": 18571, "gaston": 18572, "hillside": 18573, "statutes": 18574, "wilde": 18575, "gail": 18576, "kung": 18577, "sabine": 18578, "comfortably": 18579, "motorcycles": 18580, "##rgo": 18581, "169": 18582, "pneumonia": 18583, "fetch": 18584, "##sonic": 18585, "axel": 18586, "faintly": 18587, "parallels": 18588, "##oop": 18589, "mclaren": 18590, "spouse": 18591, "compton": 18592, "interdisciplinary": 18593, "miner": 18594, "##eni": 18595, "181": 18596, "clamped": 18597, "##chal": 18598, "##llah": 18599, "separates": 18600, "versa": 18601, "##mler": 18602, "scarborough": 18603, "labrador": 18604, "##lity": 18605, "##osing": 18606, "rutgers": 18607, "hurdles": 18608, "como": 18609, "166": 18610, "burt": 18611, "divers": 18612, "##100": 18613, "wichita": 18614, "cade": 18615, "coincided": 18616, "##erson": 18617, "bruised": 18618, "mla": 18619, "##pper": 18620, "vineyard": 18621, "##ili": 18622, "##brush": 18623, "notch": 18624, "mentioning": 18625, "jase": 18626, "hearted": 18627, "kits": 18628, "doe": 18629, "##acle": 18630, "pomerania": 18631, "##ady": 18632, "ronan": 18633, "seizure": 18634, "pavel": 18635, "problematic": 18636, "##zaki": 18637, "domenico": 18638, "##ulin": 18639, "catering": 18640, "penelope": 18641, "dependence": 18642, "parental": 18643, "emilio": 18644, "ministerial": 18645, "atkinson": 18646, "##bolic": 18647, "clarkson": 18648, "chargers": 18649, "colby": 18650, "grill": 18651, "peeked": 18652, "arises": 18653, "summon": 18654, "##aged": 18655, "fools": 18656, "##grapher": 18657, "faculties": 18658, "qaeda": 18659, "##vial": 18660, "garner": 18661, "refurbished": 18662, "##hwa": 18663, "geelong": 18664, "disasters": 18665, "nudged": 18666, "bs": 18667, "shareholder": 18668, "lori": 18669, "algae": 18670, "reinstated": 18671, "rot": 18672, "##ades": 18673, "##nous": 18674, "invites": 18675, "stainless": 18676, "183": 18677, "inclusive": 18678, "##itude": 18679, "diocesan": 18680, "til": 18681, "##icz": 18682, "denomination": 18683, "##xa": 18684, "benton": 18685, "floral": 18686, "registers": 18687, "##ider": 18688, "##erman": 18689, "##kell": 18690, "absurd": 18691, "brunei": 18692, "guangzhou": 18693, "hitter": 18694, "retaliation": 18695, "##uled": 18696, "##eve": 18697, "blanc": 18698, "nh": 18699, "consistency": 18700, "contamination": 18701, "##eres": 18702, "##rner": 18703, "dire": 18704, "palermo": 18705, "broadcasters": 18706, "diaries": 18707, "inspire": 18708, "vols": 18709, "brewer": 18710, "tightening": 18711, "ky": 18712, "mixtape": 18713, "hormone": 18714, "##tok": 18715, "stokes": 18716, "##color": 18717, "##dly": 18718, "##ssi": 18719, "pg": 18720, "##ometer": 18721, "##lington": 18722, "sanitation": 18723, "##tility": 18724, "intercontinental": 18725, "apps": 18726, "##adt": 18727, "¹⁄₂": 18728, "cylinders": 18729, "economies": 18730, "favourable": 18731, "unison": 18732, "croix": 18733, "gertrude": 18734, "odyssey": 18735, "vanity": 18736, "dangling": 18737, "##logists": 18738, "upgrades": 18739, "dice": 18740, "middleweight": 18741, "practitioner": 18742, "##ight": 18743, "206": 18744, "henrik": 18745, "parlor": 18746, "orion": 18747, "angered": 18748, "lac": 18749, "python": 18750, "blurted": 18751, "##rri": 18752, "sensual": 18753, "intends": 18754, "swings": 18755, "angled": 18756, "##phs": 18757, "husky": 18758, "attain": 18759, "peerage": 18760, "precinct": 18761, "textiles": 18762, "cheltenham": 18763, "shuffled": 18764, "dai": 18765, "confess": 18766, "tasting": 18767, "bhutan": 18768, "##riation": 18769, "tyrone": 18770, "segregation": 18771, "abrupt": 18772, "ruiz": 18773, "##rish": 18774, "smirked": 18775, "blackwell": 18776, "confidential": 18777, "browning": 18778, "amounted": 18779, "##put": 18780, "vase": 18781, "scarce": 18782, "fabulous": 18783, "raided": 18784, "staple": 18785, "guyana": 18786, "unemployed": 18787, "glider": 18788, "shay": 18789, "##tow": 18790, "carmine": 18791, "troll": 18792, "intervene": 18793, "squash": 18794, "superstar": 18795, "##uce": 18796, "cylindrical": 18797, "len": 18798, "roadway": 18799, "researched": 18800, "handy": 18801, "##rium": 18802, "##jana": 18803, "meta": 18804, "lao": 18805, "declares": 18806, "##rring": 18807, "##tadt": 18808, "##elin": 18809, "##kova": 18810, "willem": 18811, "shrubs": 18812, "napoleonic": 18813, "realms": 18814, "skater": 18815, "qi": 18816, "volkswagen": 18817, "##ł": 18818, "tad": 18819, "hara": 18820, "archaeologist": 18821, "awkwardly": 18822, "eerie": 18823, "##kind": 18824, "wiley": 18825, "##heimer": 18826, "##24": 18827, "titus": 18828, "organizers": 18829, "cfl": 18830, "crusaders": 18831, "lama": 18832, "usb": 18833, "vent": 18834, "enraged": 18835, "thankful": 18836, "occupants": 18837, "maximilian": 18838, "##gaard": 18839, "possessing": 18840, "textbooks": 18841, "##oran": 18842, "collaborator": 18843, "quaker": 18844, "##ulo": 18845, "avalanche": 18846, "mono": 18847, "silky": 18848, "straits": 18849, "isaiah": 18850, "mustang": 18851, "surged": 18852, "resolutions": 18853, "potomac": 18854, "descend": 18855, "cl": 18856, "kilograms": 18857, "plato": 18858, "strains": 18859, "saturdays": 18860, "##olin": 18861, "bernstein": 18862, "##ype": 18863, "holstein": 18864, "ponytail": 18865, "##watch": 18866, "belize": 18867, "conversely": 18868, "heroine": 18869, "perpetual": 18870, "##ylus": 18871, "charcoal": 18872, "piedmont": 18873, "glee": 18874, "negotiating": 18875, "backdrop": 18876, "prologue": 18877, "##jah": 18878, "##mmy": 18879, "pasadena": 18880, "climbs": 18881, "ramos": 18882, "sunni": 18883, "##holm": 18884, "##tner": 18885, "##tri": 18886, "anand": 18887, "deficiency": 18888, "hertfordshire": 18889, "stout": 18890, "##avi": 18891, "aperture": 18892, "orioles": 18893, "##irs": 18894, "doncaster": 18895, "intrigued": 18896, "bombed": 18897, "coating": 18898, "otis": 18899, "##mat": 18900, "cocktail": 18901, "##jit": 18902, "##eto": 18903, "amir": 18904, "arousal": 18905, "sar": 18906, "##proof": 18907, "##act": 18908, "##ories": 18909, "dixie": 18910, "pots": 18911, "##bow": 18912, "whereabouts": 18913, "159": 18914, "##fted": 18915, "drains": 18916, "bullying": 18917, "cottages": 18918, "scripture": 18919, "coherent": 18920, "fore": 18921, "poe": 18922, "appetite": 18923, "##uration": 18924, "sampled": 18925, "##ators": 18926, "##dp": 18927, "derrick": 18928, "rotor": 18929, "jays": 18930, "peacock": 18931, "installment": 18932, "##rro": 18933, "advisors": 18934, "##coming": 18935, "rodeo": 18936, "scotch": 18937, "##mot": 18938, "##db": 18939, "##fen": 18940, "##vant": 18941, "ensued": 18942, "rodrigo": 18943, "dictatorship": 18944, "martyrs": 18945, "twenties": 18946, "##н": 18947, "towed": 18948, "incidence": 18949, "marta": 18950, "rainforest": 18951, "sai": 18952, "scaled": 18953, "##cles": 18954, "oceanic": 18955, "qualifiers": 18956, "symphonic": 18957, "mcbride": 18958, "dislike": 18959, "generalized": 18960, "aubrey": 18961, "colonization": 18962, "##iation": 18963, "##lion": 18964, "##ssing": 18965, "disliked": 18966, "lublin": 18967, "salesman": 18968, "##ulates": 18969, "spherical": 18970, "whatsoever": 18971, "sweating": 18972, "avalon": 18973, "contention": 18974, "punt": 18975, "severity": 18976, "alderman": 18977, "atari": 18978, "##dina": 18979, "##grant": 18980, "##rop": 18981, "scarf": 18982, "seville": 18983, "vertices": 18984, "annexation": 18985, "fairfield": 18986, "fascination": 18987, "inspiring": 18988, "launches": 18989, "palatinate": 18990, "regretted": 18991, "##rca": 18992, "feral": 18993, "##iom": 18994, "elk": 18995, "nap": 18996, "olsen": 18997, "reddy": 18998, "yong": 18999, "##leader": 19000, "##iae": 19001, "garment": 19002, "transports": 19003, "feng": 19004, "gracie": 19005, "outrage": 19006, "viceroy": 19007, "insides": 19008, "##esis": 19009, "breakup": 19010, "grady": 19011, "organizer": 19012, "softer": 19013, "grimaced": 19014, "222": 19015, "murals": 19016, "galicia": 19017, "arranging": 19018, "vectors": 19019, "##rsten": 19020, "bas": 19021, "##sb": 19022, "##cens": 19023, "sloan": 19024, "##eka": 19025, "bitten": 19026, "ara": 19027, "fender": 19028, "nausea": 19029, "bumped": 19030, "kris": 19031, "banquet": 19032, "comrades": 19033, "detector": 19034, "persisted": 19035, "##llan": 19036, "adjustment": 19037, "endowed": 19038, "cinemas": 19039, "##shot": 19040, "sellers": 19041, "##uman": 19042, "peek": 19043, "epa": 19044, "kindly": 19045, "neglect": 19046, "simpsons": 19047, "talon": 19048, "mausoleum": 19049, "runaway": 19050, "hangul": 19051, "lookout": 19052, "##cic": 19053, "rewards": 19054, "coughed": 19055, "acquainted": 19056, "chloride": 19057, "##ald": 19058, "quicker": 19059, "accordion": 19060, "neolithic": 19061, "##qa": 19062, "artemis": 19063, "coefficient": 19064, "lenny": 19065, "pandora": 19066, "tx": 19067, "##xed": 19068, "ecstasy": 19069, "litter": 19070, "segunda": 19071, "chairperson": 19072, "gemma": 19073, "hiss": 19074, "rumor": 19075, "vow": 19076, "nasal": 19077, "antioch": 19078, "compensate": 19079, "patiently": 19080, "transformers": 19081, "##eded": 19082, "judo": 19083, "morrow": 19084, "penis": 19085, "posthumous": 19086, "philips": 19087, "bandits": 19088, "husbands": 19089, "denote": 19090, "flaming": 19091, "##any": 19092, "##phones": 19093, "langley": 19094, "yorker": 19095, "1760": 19096, "walters": 19097, "##uo": 19098, "##kle": 19099, "gubernatorial": 19100, "fatty": 19101, "samsung": 19102, "leroy": 19103, "outlaw": 19104, "##nine": 19105, "unpublished": 19106, "poole": 19107, "jakob": 19108, "##ᵢ": 19109, "##ₙ": 19110, "crete": 19111, "distorted": 19112, "superiority": 19113, "##dhi": 19114, "intercept": 19115, "crust": 19116, "mig": 19117, "claus": 19118, "crashes": 19119, "positioning": 19120, "188": 19121, "stallion": 19122, "301": 19123, "frontal": 19124, "armistice": 19125, "##estinal": 19126, "elton": 19127, "aj": 19128, "encompassing": 19129, "camel": 19130, "commemorated": 19131, "malaria": 19132, "woodward": 19133, "calf": 19134, "cigar": 19135, "penetrate": 19136, "##oso": 19137, "willard": 19138, "##rno": 19139, "##uche": 19140, "illustrate": 19141, "amusing": 19142, "convergence": 19143, "noteworthy": 19144, "##lma": 19145, "##rva": 19146, "journeys": 19147, "realise": 19148, "manfred": 19149, "##sable": 19150, "410": 19151, "##vocation": 19152, "hearings": 19153, "fiance": 19154, "##posed": 19155, "educators": 19156, "provoked": 19157, "adjusting": 19158, "##cturing": 19159, "modular": 19160, "stockton": 19161, "paterson": 19162, "vlad": 19163, "rejects": 19164, "electors": 19165, "selena": 19166, "maureen": 19167, "##tres": 19168, "uber": 19169, "##rce": 19170, "swirled": 19171, "##num": 19172, "proportions": 19173, "nanny": 19174, "pawn": 19175, "naturalist": 19176, "parma": 19177, "apostles": 19178, "awoke": 19179, "ethel": 19180, "wen": 19181, "##bey": 19182, "monsoon": 19183, "overview": 19184, "##inating": 19185, "mccain": 19186, "rendition": 19187, "risky": 19188, "adorned": 19189, "##ih": 19190, "equestrian": 19191, "germain": 19192, "nj": 19193, "conspicuous": 19194, "confirming": 19195, "##yoshi": 19196, "shivering": 19197, "##imeter": 19198, "milestone": 19199, "rumours": 19200, "flinched": 19201, "bounds": 19202, "smacked": 19203, "token": 19204, "##bei": 19205, "lectured": 19206, "automobiles": 19207, "##shore": 19208, "impacted": 19209, "##iable": 19210, "nouns": 19211, "nero": 19212, "##leaf": 19213, "ismail": 19214, "prostitute": 19215, "trams": 19216, "##lace": 19217, "bridget": 19218, "sud": 19219, "stimulus": 19220, "impressions": 19221, "reins": 19222, "revolves": 19223, "##oud": 19224, "##gned": 19225, "giro": 19226, "honeymoon": 19227, "##swell": 19228, "criterion": 19229, "##sms": 19230, "##uil": 19231, "libyan": 19232, "prefers": 19233, "##osition": 19234, "211": 19235, "preview": 19236, "sucks": 19237, "accusation": 19238, "bursts": 19239, "metaphor": 19240, "diffusion": 19241, "tolerate": 19242, "faye": 19243, "betting": 19244, "cinematographer": 19245, "liturgical": 19246, "specials": 19247, "bitterly": 19248, "humboldt": 19249, "##ckle": 19250, "flux": 19251, "rattled": 19252, "##itzer": 19253, "archaeologists": 19254, "odor": 19255, "authorised": 19256, "marshes": 19257, "discretion": 19258, "##ов": 19259, "alarmed": 19260, "archaic": 19261, "inverse": 19262, "##leton": 19263, "explorers": 19264, "##pine": 19265, "drummond": 19266, "tsunami": 19267, "woodlands": 19268, "##minate": 19269, "##tland": 19270, "booklet": 19271, "insanity": 19272, "owning": 19273, "insert": 19274, "crafted": 19275, "calculus": 19276, "##tore": 19277, "receivers": 19278, "##bt": 19279, "stung": 19280, "##eca": 19281, "##nched": 19282, "prevailing": 19283, "travellers": 19284, "eyeing": 19285, "lila": 19286, "graphs": 19287, "##borne": 19288, "178": 19289, "julien": 19290, "##won": 19291, "morale": 19292, "adaptive": 19293, "therapist": 19294, "erica": 19295, "cw": 19296, "libertarian": 19297, "bowman": 19298, "pitches": 19299, "vita": 19300, "##ional": 19301, "crook": 19302, "##ads": 19303, "##entation": 19304, "caledonia": 19305, "mutiny": 19306, "##sible": 19307, "1840s": 19308, "automation": 19309, "##ß": 19310, "flock": 19311, "##pia": 19312, "ironic": 19313, "pathology": 19314, "##imus": 19315, "remarried": 19316, "##22": 19317, "joker": 19318, "withstand": 19319, "energies": 19320, "##att": 19321, "shropshire": 19322, "hostages": 19323, "madeleine": 19324, "tentatively": 19325, "conflicting": 19326, "mateo": 19327, "recipes": 19328, "euros": 19329, "ol": 19330, "mercenaries": 19331, "nico": 19332, "##ndon": 19333, "albuquerque": 19334, "augmented": 19335, "mythical": 19336, "bel": 19337, "freud": 19338, "##child": 19339, "cough": 19340, "##lica": 19341, "365": 19342, "freddy": 19343, "lillian": 19344, "genetically": 19345, "nuremberg": 19346, "calder": 19347, "209": 19348, "bonn": 19349, "outdoors": 19350, "paste": 19351, "suns": 19352, "urgency": 19353, "vin": 19354, "restraint": 19355, "tyson": 19356, "##cera": 19357, "##selle": 19358, "barrage": 19359, "bethlehem": 19360, "kahn": 19361, "##par": 19362, "mounts": 19363, "nippon": 19364, "barony": 19365, "happier": 19366, "ryu": 19367, "makeshift": 19368, "sheldon": 19369, "blushed": 19370, "castillo": 19371, "barking": 19372, "listener": 19373, "taped": 19374, "bethel": 19375, "fluent": 19376, "headlines": 19377, "pornography": 19378, "rum": 19379, "disclosure": 19380, "sighing": 19381, "mace": 19382, "doubling": 19383, "gunther": 19384, "manly": 19385, "##plex": 19386, "rt": 19387, "interventions": 19388, "physiological": 19389, "forwards": 19390, "emerges": 19391, "##tooth": 19392, "##gny": 19393, "compliment": 19394, "rib": 19395, "recession": 19396, "visibly": 19397, "barge": 19398, "faults": 19399, "connector": 19400, "exquisite": 19401, "prefect": 19402, "##rlin": 19403, "patio": 19404, "##cured": 19405, "elevators": 19406, "brandt": 19407, "italics": 19408, "pena": 19409, "173": 19410, "wasp": 19411, "satin": 19412, "ea": 19413, "botswana": 19414, "graceful": 19415, "respectable": 19416, "##jima": 19417, "##rter": 19418, "##oic": 19419, "franciscan": 19420, "generates": 19421, "##dl": 19422, "alfredo": 19423, "disgusting": 19424, "##olate": 19425, "##iously": 19426, "sherwood": 19427, "warns": 19428, "cod": 19429, "promo": 19430, "cheryl": 19431, "sino": 19432, "##ة": 19433, "##escu": 19434, "twitch": 19435, "##zhi": 19436, "brownish": 19437, "thom": 19438, "ortiz": 19439, "##dron": 19440, "densely": 19441, "##beat": 19442, "carmel": 19443, "reinforce": 19444, "##bana": 19445, "187": 19446, "anastasia": 19447, "downhill": 19448, "vertex": 19449, "contaminated": 19450, "remembrance": 19451, "harmonic": 19452, "homework": 19453, "##sol": 19454, "fiancee": 19455, "gears": 19456, "olds": 19457, "angelica": 19458, "loft": 19459, "ramsay": 19460, "quiz": 19461, "colliery": 19462, "sevens": 19463, "##cape": 19464, "autism": 19465, "##hil": 19466, "walkway": 19467, "##boats": 19468, "ruben": 19469, "abnormal": 19470, "ounce": 19471, "khmer": 19472, "##bbe": 19473, "zachary": 19474, "bedside": 19475, "morphology": 19476, "punching": 19477, "##olar": 19478, "sparrow": 19479, "convinces": 19480, "##35": 19481, "hewitt": 19482, "queer": 19483, "remastered": 19484, "rods": 19485, "mabel": 19486, "solemn": 19487, "notified": 19488, "lyricist": 19489, "symmetric": 19490, "##xide": 19491, "174": 19492, "encore": 19493, "passports": 19494, "wildcats": 19495, "##uni": 19496, "baja": 19497, "##pac": 19498, "mildly": 19499, "##ease": 19500, "bleed": 19501, "commodity": 19502, "mounds": 19503, "glossy": 19504, "orchestras": 19505, "##omo": 19506, "damian": 19507, "prelude": 19508, "ambitions": 19509, "##vet": 19510, "awhile": 19511, "remotely": 19512, "##aud": 19513, "asserts": 19514, "imply": 19515, "##iques": 19516, "distinctly": 19517, "modelling": 19518, "remedy": 19519, "##dded": 19520, "windshield": 19521, "dani": 19522, "xiao": 19523, "##endra": 19524, "audible": 19525, "powerplant": 19526, "1300": 19527, "invalid": 19528, "elemental": 19529, "acquisitions": 19530, "##hala": 19531, "immaculate": 19532, "libby": 19533, "plata": 19534, "smuggling": 19535, "ventilation": 19536, "denoted": 19537, "minh": 19538, "##morphism": 19539, "430": 19540, "differed": 19541, "dion": 19542, "kelley": 19543, "lore": 19544, "mocking": 19545, "sabbath": 19546, "spikes": 19547, "hygiene": 19548, "drown": 19549, "runoff": 19550, "stylized": 19551, "tally": 19552, "liberated": 19553, "aux": 19554, "interpreter": 19555, "righteous": 19556, "aba": 19557, "siren": 19558, "reaper": 19559, "pearce": 19560, "millie": 19561, "##cier": 19562, "##yra": 19563, "gaius": 19564, "##iso": 19565, "captures": 19566, "##ttering": 19567, "dorm": 19568, "claudio": 19569, "##sic": 19570, "benches": 19571, "knighted": 19572, "blackness": 19573, "##ored": 19574, "discount": 19575, "fumble": 19576, "oxidation": 19577, "routed": 19578, "##ς": 19579, "novak": 19580, "perpendicular": 19581, "spoiled": 19582, "fracture": 19583, "splits": 19584, "##urt": 19585, "pads": 19586, "topology": 19587, "##cats": 19588, "axes": 19589, "fortunate": 19590, "offenders": 19591, "protestants": 19592, "esteem": 19593, "221": 19594, "broadband": 19595, "convened": 19596, "frankly": 19597, "hound": 19598, "prototypes": 19599, "isil": 19600, "facilitated": 19601, "keel": 19602, "##sher": 19603, "sahara": 19604, "awaited": 19605, "bubba": 19606, "orb": 19607, "prosecutors": 19608, "186": 19609, "hem": 19610, "520": 19611, "##xing": 19612, "relaxing": 19613, "remnant": 19614, "romney": 19615, "sorted": 19616, "slalom": 19617, "stefano": 19618, "ulrich": 19619, "##active": 19620, "exemption": 19621, "folder": 19622, "pauses": 19623, "foliage": 19624, "hitchcock": 19625, "epithet": 19626, "204": 19627, "criticisms": 19628, "##aca": 19629, "ballistic": 19630, "brody": 19631, "hinduism": 19632, "chaotic": 19633, "youths": 19634, "equals": 19635, "##pala": 19636, "pts": 19637, "thicker": 19638, "analogous": 19639, "capitalist": 19640, "improvised": 19641, "overseeing": 19642, "sinatra": 19643, "ascended": 19644, "beverage": 19645, "##tl": 19646, "straightforward": 19647, "##kon": 19648, "curran": 19649, "##west": 19650, "bois": 19651, "325": 19652, "induce": 19653, "surveying": 19654, "emperors": 19655, "sax": 19656, "unpopular": 19657, "##kk": 19658, "cartoonist": 19659, "fused": 19660, "##mble": 19661, "unto": 19662, "##yuki": 19663, "localities": 19664, "##cko": 19665, "##ln": 19666, "darlington": 19667, "slain": 19668, "academie": 19669, "lobbying": 19670, "sediment": 19671, "puzzles": 19672, "##grass": 19673, "defiance": 19674, "dickens": 19675, "manifest": 19676, "tongues": 19677, "alumnus": 19678, "arbor": 19679, "coincide": 19680, "184": 19681, "appalachian": 19682, "mustafa": 19683, "examiner": 19684, "cabaret": 19685, "traumatic": 19686, "yves": 19687, "bracelet": 19688, "draining": 19689, "heroin": 19690, "magnum": 19691, "baths": 19692, "odessa": 19693, "consonants": 19694, "mitsubishi": 19695, "##gua": 19696, "kellan": 19697, "vaudeville": 19698, "##fr": 19699, "joked": 19700, "null": 19701, "straps": 19702, "probation": 19703, "##ław": 19704, "ceded": 19705, "interfaces": 19706, "##pas": 19707, "##zawa": 19708, "blinding": 19709, "viet": 19710, "224": 19711, "rothschild": 19712, "museo": 19713, "640": 19714, "huddersfield": 19715, "##vr": 19716, "tactic": 19717, "##storm": 19718, "brackets": 19719, "dazed": 19720, "incorrectly": 19721, "##vu": 19722, "reg": 19723, "glazed": 19724, "fearful": 19725, "manifold": 19726, "benefited": 19727, "irony": 19728, "##sun": 19729, "stumbling": 19730, "##rte": 19731, "willingness": 19732, "balkans": 19733, "mei": 19734, "wraps": 19735, "##aba": 19736, "injected": 19737, "##lea": 19738, "gu": 19739, "syed": 19740, "harmless": 19741, "##hammer": 19742, "bray": 19743, "takeoff": 19744, "poppy": 19745, "timor": 19746, "cardboard": 19747, "astronaut": 19748, "purdue": 19749, "weeping": 19750, "southbound": 19751, "cursing": 19752, "stalls": 19753, "diagonal": 19754, "##neer": 19755, "lamar": 19756, "bryce": 19757, "comte": 19758, "weekdays": 19759, "harrington": 19760, "##uba": 19761, "negatively": 19762, "##see": 19763, "lays": 19764, "grouping": 19765, "##cken": 19766, "##henko": 19767, "affirmed": 19768, "halle": 19769, "modernist": 19770, "##lai": 19771, "hodges": 19772, "smelling": 19773, "aristocratic": 19774, "baptized": 19775, "dismiss": 19776, "justification": 19777, "oilers": 19778, "##now": 19779, "coupling": 19780, "qin": 19781, "snack": 19782, "healer": 19783, "##qing": 19784, "gardener": 19785, "layla": 19786, "battled": 19787, "formulated": 19788, "stephenson": 19789, "gravitational": 19790, "##gill": 19791, "##jun": 19792, "1768": 19793, "granny": 19794, "coordinating": 19795, "suites": 19796, "##cd": 19797, "##ioned": 19798, "monarchs": 19799, "##cote": 19800, "##hips": 19801, "sep": 19802, "blended": 19803, "apr": 19804, "barrister": 19805, "deposition": 19806, "fia": 19807, "mina": 19808, "policemen": 19809, "paranoid": 19810, "##pressed": 19811, "churchyard": 19812, "covert": 19813, "crumpled": 19814, "creep": 19815, "abandoning": 19816, "tr": 19817, "transmit": 19818, "conceal": 19819, "barr": 19820, "understands": 19821, "readiness": 19822, "spire": 19823, "##cology": 19824, "##enia": 19825, "##erry": 19826, "610": 19827, "startling": 19828, "unlock": 19829, "vida": 19830, "bowled": 19831, "slots": 19832, "##nat": 19833, "##islav": 19834, "spaced": 19835, "trusting": 19836, "admire": 19837, "rig": 19838, "##ink": 19839, "slack": 19840, "##70": 19841, "mv": 19842, "207": 19843, "casualty": 19844, "##wei": 19845, "classmates": 19846, "##odes": 19847, "##rar": 19848, "##rked": 19849, "amherst": 19850, "furnished": 19851, "evolve": 19852, "foundry": 19853, "menace": 19854, "mead": 19855, "##lein": 19856, "flu": 19857, "wesleyan": 19858, "##kled": 19859, "monterey": 19860, "webber": 19861, "##vos": 19862, "wil": 19863, "##mith": 19864, "##на": 19865, "bartholomew": 19866, "justices": 19867, "restrained": 19868, "##cke": 19869, "amenities": 19870, "191": 19871, "mediated": 19872, "sewage": 19873, "trenches": 19874, "ml": 19875, "mainz": 19876, "##thus": 19877, "1800s": 19878, "##cula": 19879, "##inski": 19880, "caine": 19881, "bonding": 19882, "213": 19883, "converts": 19884, "spheres": 19885, "superseded": 19886, "marianne": 19887, "crypt": 19888, "sweaty": 19889, "ensign": 19890, "historia": 19891, "##br": 19892, "spruce": 19893, "##post": 19894, "##ask": 19895, "forks": 19896, "thoughtfully": 19897, "yukon": 19898, "pamphlet": 19899, "ames": 19900, "##uter": 19901, "karma": 19902, "##yya": 19903, "bryn": 19904, "negotiation": 19905, "sighs": 19906, "incapable": 19907, "##mbre": 19908, "##ntial": 19909, "actresses": 19910, "taft": 19911, "##mill": 19912, "luce": 19913, "prevailed": 19914, "##amine": 19915, "1773": 19916, "motionless": 19917, "envoy": 19918, "testify": 19919, "investing": 19920, "sculpted": 19921, "instructors": 19922, "provence": 19923, "kali": 19924, "cullen": 19925, "horseback": 19926, "##while": 19927, "goodwin": 19928, "##jos": 19929, "gaa": 19930, "norte": 19931, "##ldon": 19932, "modify": 19933, "wavelength": 19934, "abd": 19935, "214": 19936, "skinned": 19937, "sprinter": 19938, "forecast": 19939, "scheduling": 19940, "marries": 19941, "squared": 19942, "tentative": 19943, "##chman": 19944, "boer": 19945, "##isch": 19946, "bolts": 19947, "swap": 19948, "fisherman": 19949, "assyrian": 19950, "impatiently": 19951, "guthrie": 19952, "martins": 19953, "murdoch": 19954, "194": 19955, "tanya": 19956, "nicely": 19957, "dolly": 19958, "lacy": 19959, "med": 19960, "##45": 19961, "syn": 19962, "decks": 19963, "fashionable": 19964, "millionaire": 19965, "##ust": 19966, "surfing": 19967, "##ml": 19968, "##ision": 19969, "heaved": 19970, "tammy": 19971, "consulate": 19972, "attendees": 19973, "routinely": 19974, "197": 19975, "fuse": 19976, "saxophonist": 19977, "backseat": 19978, "malaya": 19979, "##lord": 19980, "scowl": 19981, "tau": 19982, "##ishly": 19983, "193": 19984, "sighted": 19985, "steaming": 19986, "##rks": 19987, "303": 19988, "911": 19989, "##holes": 19990, "##hong": 19991, "ching": 19992, "##wife": 19993, "bless": 19994, "conserved": 19995, "jurassic": 19996, "stacey": 19997, "unix": 19998, "zion": 19999, "chunk": 20000, "rigorous": 20001, "blaine": 20002, "198": 20003, "peabody": 20004, "slayer": 20005, "dismay": 20006, "brewers": 20007, "nz": 20008, "##jer": 20009, "det": 20010, "##glia": 20011, "glover": 20012, "postwar": 20013, "int": 20014, "penetration": 20015, "sylvester": 20016, "imitation": 20017, "vertically": 20018, "airlift": 20019, "heiress": 20020, "knoxville": 20021, "viva": 20022, "##uin": 20023, "390": 20024, "macon": 20025, "##rim": 20026, "##fighter": 20027, "##gonal": 20028, "janice": 20029, "##orescence": 20030, "##wari": 20031, "marius": 20032, "belongings": 20033, "leicestershire": 20034, "196": 20035, "blanco": 20036, "inverted": 20037, "preseason": 20038, "sanity": 20039, "sobbing": 20040, "##due": 20041, "##elt": 20042, "##dled": 20043, "collingwood": 20044, "regeneration": 20045, "flickering": 20046, "shortest": 20047, "##mount": 20048, "##osi": 20049, "feminism": 20050, "##lat": 20051, "sherlock": 20052, "cabinets": 20053, "fumbled": 20054, "northbound": 20055, "precedent": 20056, "snaps": 20057, "##mme": 20058, "researching": 20059, "##akes": 20060, "guillaume": 20061, "insights": 20062, "manipulated": 20063, "vapor": 20064, "neighbour": 20065, "sap": 20066, "gangster": 20067, "frey": 20068, "f1": 20069, "stalking": 20070, "scarcely": 20071, "callie": 20072, "barnett": 20073, "tendencies": 20074, "audi": 20075, "doomed": 20076, "assessing": 20077, "slung": 20078, "panchayat": 20079, "ambiguous": 20080, "bartlett": 20081, "##etto": 20082, "distributing": 20083, "violating": 20084, "wolverhampton": 20085, "##hetic": 20086, "swami": 20087, "histoire": 20088, "##urus": 20089, "liable": 20090, "pounder": 20091, "groin": 20092, "hussain": 20093, "larsen": 20094, "popping": 20095, "surprises": 20096, "##atter": 20097, "vie": 20098, "curt": 20099, "##station": 20100, "mute": 20101, "relocate": 20102, "musicals": 20103, "authorization": 20104, "richter": 20105, "##sef": 20106, "immortality": 20107, "tna": 20108, "bombings": 20109, "##press": 20110, "deteriorated": 20111, "yiddish": 20112, "##acious": 20113, "robbed": 20114, "colchester": 20115, "cs": 20116, "pmid": 20117, "ao": 20118, "verified": 20119, "balancing": 20120, "apostle": 20121, "swayed": 20122, "recognizable": 20123, "oxfordshire": 20124, "retention": 20125, "nottinghamshire": 20126, "contender": 20127, "judd": 20128, "invitational": 20129, "shrimp": 20130, "uhf": 20131, "##icient": 20132, "cleaner": 20133, "longitudinal": 20134, "tanker": 20135, "##mur": 20136, "acronym": 20137, "broker": 20138, "koppen": 20139, "sundance": 20140, "suppliers": 20141, "##gil": 20142, "4000": 20143, "clipped": 20144, "fuels": 20145, "petite": 20146, "##anne": 20147, "landslide": 20148, "helene": 20149, "diversion": 20150, "populous": 20151, "landowners": 20152, "auspices": 20153, "melville": 20154, "quantitative": 20155, "##xes": 20156, "ferries": 20157, "nicky": 20158, "##llus": 20159, "doo": 20160, "haunting": 20161, "roche": 20162, "carver": 20163, "downed": 20164, "unavailable": 20165, "##pathy": 20166, "approximation": 20167, "hiroshima": 20168, "##hue": 20169, "garfield": 20170, "valle": 20171, "comparatively": 20172, "keyboardist": 20173, "traveler": 20174, "##eit": 20175, "congestion": 20176, "calculating": 20177, "subsidiaries": 20178, "##bate": 20179, "serb": 20180, "modernization": 20181, "fairies": 20182, "deepened": 20183, "ville": 20184, "averages": 20185, "##lore": 20186, "inflammatory": 20187, "tonga": 20188, "##itch": 20189, "co₂": 20190, "squads": 20191, "##hea": 20192, "gigantic": 20193, "serum": 20194, "enjoyment": 20195, "retailer": 20196, "verona": 20197, "35th": 20198, "cis": 20199, "##phobic": 20200, "magna": 20201, "technicians": 20202, "##vati": 20203, "arithmetic": 20204, "##sport": 20205, "levin": 20206, "##dation": 20207, "amtrak": 20208, "chow": 20209, "sienna": 20210, "##eyer": 20211, "backstage": 20212, "entrepreneurship": 20213, "##otic": 20214, "learnt": 20215, "tao": 20216, "##udy": 20217, "worcestershire": 20218, "formulation": 20219, "baggage": 20220, "hesitant": 20221, "bali": 20222, "sabotage": 20223, "##kari": 20224, "barren": 20225, "enhancing": 20226, "murmur": 20227, "pl": 20228, "freshly": 20229, "putnam": 20230, "syntax": 20231, "aces": 20232, "medicines": 20233, "resentment": 20234, "bandwidth": 20235, "##sier": 20236, "grins": 20237, "chili": 20238, "guido": 20239, "##sei": 20240, "framing": 20241, "implying": 20242, "gareth": 20243, "lissa": 20244, "genevieve": 20245, "pertaining": 20246, "admissions": 20247, "geo": 20248, "thorpe": 20249, "proliferation": 20250, "sato": 20251, "bela": 20252, "analyzing": 20253, "parting": 20254, "##gor": 20255, "awakened": 20256, "##isman": 20257, "huddled": 20258, "secrecy": 20259, "##kling": 20260, "hush": 20261, "gentry": 20262, "540": 20263, "dungeons": 20264, "##ego": 20265, "coasts": 20266, "##utz": 20267, "sacrificed": 20268, "##chule": 20269, "landowner": 20270, "mutually": 20271, "prevalence": 20272, "programmer": 20273, "adolescent": 20274, "disrupted": 20275, "seaside": 20276, "gee": 20277, "trusts": 20278, "vamp": 20279, "georgie": 20280, "##nesian": 20281, "##iol": 20282, "schedules": 20283, "sindh": 20284, "##market": 20285, "etched": 20286, "hm": 20287, "sparse": 20288, "bey": 20289, "beaux": 20290, "scratching": 20291, "gliding": 20292, "unidentified": 20293, "216": 20294, "collaborating": 20295, "gems": 20296, "jesuits": 20297, "oro": 20298, "accumulation": 20299, "shaping": 20300, "mbe": 20301, "anal": 20302, "##xin": 20303, "231": 20304, "enthusiasts": 20305, "newscast": 20306, "##egan": 20307, "janata": 20308, "dewey": 20309, "parkinson": 20310, "179": 20311, "ankara": 20312, "biennial": 20313, "towering": 20314, "dd": 20315, "inconsistent": 20316, "950": 20317, "##chet": 20318, "thriving": 20319, "terminate": 20320, "cabins": 20321, "furiously": 20322, "eats": 20323, "advocating": 20324, "donkey": 20325, "marley": 20326, "muster": 20327, "phyllis": 20328, "leiden": 20329, "##user": 20330, "grassland": 20331, "glittering": 20332, "iucn": 20333, "loneliness": 20334, "217": 20335, "memorandum": 20336, "armenians": 20337, "##ddle": 20338, "popularized": 20339, "rhodesia": 20340, "60s": 20341, "lame": 20342, "##illon": 20343, "sans": 20344, "bikini": 20345, "header": 20346, "orbits": 20347, "##xx": 20348, "##finger": 20349, "##ulator": 20350, "sharif": 20351, "spines": 20352, "biotechnology": 20353, "strolled": 20354, "naughty": 20355, "yates": 20356, "##wire": 20357, "fremantle": 20358, "milo": 20359, "##mour": 20360, "abducted": 20361, "removes": 20362, "##atin": 20363, "humming": 20364, "wonderland": 20365, "##chrome": 20366, "##ester": 20367, "hume": 20368, "pivotal": 20369, "##rates": 20370, "armand": 20371, "grams": 20372, "believers": 20373, "elector": 20374, "rte": 20375, "apron": 20376, "bis": 20377, "scraped": 20378, "##yria": 20379, "endorsement": 20380, "initials": 20381, "##llation": 20382, "eps": 20383, "dotted": 20384, "hints": 20385, "buzzing": 20386, "emigration": 20387, "nearer": 20388, "##tom": 20389, "indicators": 20390, "##ulu": 20391, "coarse": 20392, "neutron": 20393, "protectorate": 20394, "##uze": 20395, "directional": 20396, "exploits": 20397, "pains": 20398, "loire": 20399, "1830s": 20400, "proponents": 20401, "guggenheim": 20402, "rabbits": 20403, "ritchie": 20404, "305": 20405, "hectare": 20406, "inputs": 20407, "hutton": 20408, "##raz": 20409, "verify": 20410, "##ako": 20411, "boilers": 20412, "longitude": 20413, "##lev": 20414, "skeletal": 20415, "yer": 20416, "emilia": 20417, "citrus": 20418, "compromised": 20419, "##gau": 20420, "pokemon": 20421, "prescription": 20422, "paragraph": 20423, "eduard": 20424, "cadillac": 20425, "attire": 20426, "categorized": 20427, "kenyan": 20428, "weddings": 20429, "charley": 20430, "##bourg": 20431, "entertain": 20432, "monmouth": 20433, "##lles": 20434, "nutrients": 20435, "davey": 20436, "mesh": 20437, "incentive": 20438, "practised": 20439, "ecosystems": 20440, "kemp": 20441, "subdued": 20442, "overheard": 20443, "##rya": 20444, "bodily": 20445, "maxim": 20446, "##nius": 20447, "apprenticeship": 20448, "ursula": 20449, "##fight": 20450, "lodged": 20451, "rug": 20452, "silesian": 20453, "unconstitutional": 20454, "patel": 20455, "inspected": 20456, "coyote": 20457, "unbeaten": 20458, "##hak": 20459, "34th": 20460, "disruption": 20461, "convict": 20462, "parcel": 20463, "##cl": 20464, "##nham": 20465, "collier": 20466, "implicated": 20467, "mallory": 20468, "##iac": 20469, "##lab": 20470, "susannah": 20471, "winkler": 20472, "##rber": 20473, "shia": 20474, "phelps": 20475, "sediments": 20476, "graphical": 20477, "robotic": 20478, "##sner": 20479, "adulthood": 20480, "mart": 20481, "smoked": 20482, "##isto": 20483, "kathryn": 20484, "clarified": 20485, "##aran": 20486, "divides": 20487, "convictions": 20488, "oppression": 20489, "pausing": 20490, "burying": 20491, "##mt": 20492, "federico": 20493, "mathias": 20494, "eileen": 20495, "##tana": 20496, "kite": 20497, "hunched": 20498, "##acies": 20499, "189": 20500, "##atz": 20501, "disadvantage": 20502, "liza": 20503, "kinetic": 20504, "greedy": 20505, "paradox": 20506, "yokohama": 20507, "dowager": 20508, "trunks": 20509, "ventured": 20510, "##gement": 20511, "gupta": 20512, "vilnius": 20513, "olaf": 20514, "##thest": 20515, "crimean": 20516, "hopper": 20517, "##ej": 20518, "progressively": 20519, "arturo": 20520, "mouthed": 20521, "arrondissement": 20522, "##fusion": 20523, "rubin": 20524, "simulcast": 20525, "oceania": 20526, "##orum": 20527, "##stra": 20528, "##rred": 20529, "busiest": 20530, "intensely": 20531, "navigator": 20532, "cary": 20533, "##vine": 20534, "##hini": 20535, "##bies": 20536, "fife": 20537, "rowe": 20538, "rowland": 20539, "posing": 20540, "insurgents": 20541, "shafts": 20542, "lawsuits": 20543, "activate": 20544, "conor": 20545, "inward": 20546, "culturally": 20547, "garlic": 20548, "265": 20549, "##eering": 20550, "eclectic": 20551, "##hui": 20552, "##kee": 20553, "##nl": 20554, "furrowed": 20555, "vargas": 20556, "meteorological": 20557, "rendezvous": 20558, "##aus": 20559, "culinary": 20560, "commencement": 20561, "##dition": 20562, "quota": 20563, "##notes": 20564, "mommy": 20565, "salaries": 20566, "overlapping": 20567, "mule": 20568, "##iology": 20569, "##mology": 20570, "sums": 20571, "wentworth": 20572, "##isk": 20573, "##zione": 20574, "mainline": 20575, "subgroup": 20576, "##illy": 20577, "hack": 20578, "plaintiff": 20579, "verdi": 20580, "bulb": 20581, "differentiation": 20582, "engagements": 20583, "multinational": 20584, "supplemented": 20585, "bertrand": 20586, "caller": 20587, "regis": 20588, "##naire": 20589, "##sler": 20590, "##arts": 20591, "##imated": 20592, "blossom": 20593, "propagation": 20594, "kilometer": 20595, "viaduct": 20596, "vineyards": 20597, "##uate": 20598, "beckett": 20599, "optimization": 20600, "golfer": 20601, "songwriters": 20602, "seminal": 20603, "semitic": 20604, "thud": 20605, "volatile": 20606, "evolving": 20607, "ridley": 20608, "##wley": 20609, "trivial": 20610, "distributions": 20611, "scandinavia": 20612, "jiang": 20613, "##ject": 20614, "wrestled": 20615, "insistence": 20616, "##dio": 20617, "emphasizes": 20618, "napkin": 20619, "##ods": 20620, "adjunct": 20621, "rhyme": 20622, "##ricted": 20623, "##eti": 20624, "hopeless": 20625, "surrounds": 20626, "tremble": 20627, "32nd": 20628, "smoky": 20629, "##ntly": 20630, "oils": 20631, "medicinal": 20632, "padded": 20633, "steer": 20634, "wilkes": 20635, "219": 20636, "255": 20637, "concessions": 20638, "hue": 20639, "uniquely": 20640, "blinded": 20641, "landon": 20642, "yahoo": 20643, "##lane": 20644, "hendrix": 20645, "commemorating": 20646, "dex": 20647, "specify": 20648, "chicks": 20649, "##ggio": 20650, "intercity": 20651, "1400": 20652, "morley": 20653, "##torm": 20654, "highlighting": 20655, "##oting": 20656, "pang": 20657, "oblique": 20658, "stalled": 20659, "##liner": 20660, "flirting": 20661, "newborn": 20662, "1769": 20663, "bishopric": 20664, "shaved": 20665, "232": 20666, "currie": 20667, "##ush": 20668, "dharma": 20669, "spartan": 20670, "##ooped": 20671, "favorites": 20672, "smug": 20673, "novella": 20674, "sirens": 20675, "abusive": 20676, "creations": 20677, "espana": 20678, "##lage": 20679, "paradigm": 20680, "semiconductor": 20681, "sheen": 20682, "##rdo": 20683, "##yen": 20684, "##zak": 20685, "nrl": 20686, "renew": 20687, "##pose": 20688, "##tur": 20689, "adjutant": 20690, "marches": 20691, "norma": 20692, "##enity": 20693, "ineffective": 20694, "weimar": 20695, "grunt": 20696, "##gat": 20697, "lordship": 20698, "plotting": 20699, "expenditure": 20700, "infringement": 20701, "lbs": 20702, "refrain": 20703, "av": 20704, "mimi": 20705, "mistakenly": 20706, "postmaster": 20707, "1771": 20708, "##bara": 20709, "ras": 20710, "motorsports": 20711, "tito": 20712, "199": 20713, "subjective": 20714, "##zza": 20715, "bully": 20716, "stew": 20717, "##kaya": 20718, "prescott": 20719, "1a": 20720, "##raphic": 20721, "##zam": 20722, "bids": 20723, "styling": 20724, "paranormal": 20725, "reeve": 20726, "sneaking": 20727, "exploding": 20728, "katz": 20729, "akbar": 20730, "migrant": 20731, "syllables": 20732, "indefinitely": 20733, "##ogical": 20734, "destroys": 20735, "replaces": 20736, "applause": 20737, "##phine": 20738, "pest": 20739, "##fide": 20740, "218": 20741, "articulated": 20742, "bertie": 20743, "##thing": 20744, "##cars": 20745, "##ptic": 20746, "courtroom": 20747, "crowley": 20748, "aesthetics": 20749, "cummings": 20750, "tehsil": 20751, "hormones": 20752, "titanic": 20753, "dangerously": 20754, "##ibe": 20755, "stadion": 20756, "jaenelle": 20757, "auguste": 20758, "ciudad": 20759, "##chu": 20760, "mysore": 20761, "partisans": 20762, "##sio": 20763, "lucan": 20764, "philipp": 20765, "##aly": 20766, "debating": 20767, "henley": 20768, "interiors": 20769, "##rano": 20770, "##tious": 20771, "homecoming": 20772, "beyonce": 20773, "usher": 20774, "henrietta": 20775, "prepares": 20776, "weeds": 20777, "##oman": 20778, "ely": 20779, "plucked": 20780, "##pire": 20781, "##dable": 20782, "luxurious": 20783, "##aq": 20784, "artifact": 20785, "password": 20786, "pasture": 20787, "juno": 20788, "maddy": 20789, "minsk": 20790, "##dder": 20791, "##ologies": 20792, "##rone": 20793, "assessments": 20794, "martian": 20795, "royalist": 20796, "1765": 20797, "examines": 20798, "##mani": 20799, "##rge": 20800, "nino": 20801, "223": 20802, "parry": 20803, "scooped": 20804, "relativity": 20805, "##eli": 20806, "##uting": 20807, "##cao": 20808, "congregational": 20809, "noisy": 20810, "traverse": 20811, "##agawa": 20812, "strikeouts": 20813, "nickelodeon": 20814, "obituary": 20815, "transylvania": 20816, "binds": 20817, "depictions": 20818, "polk": 20819, "trolley": 20820, "##yed": 20821, "##lard": 20822, "breeders": 20823, "##under": 20824, "dryly": 20825, "hokkaido": 20826, "1762": 20827, "strengths": 20828, "stacks": 20829, "bonaparte": 20830, "connectivity": 20831, "neared": 20832, "prostitutes": 20833, "stamped": 20834, "anaheim": 20835, "gutierrez": 20836, "sinai": 20837, "##zzling": 20838, "bram": 20839, "fresno": 20840, "madhya": 20841, "##86": 20842, "proton": 20843, "##lena": 20844, "##llum": 20845, "##phon": 20846, "reelected": 20847, "wanda": 20848, "##anus": 20849, "##lb": 20850, "ample": 20851, "distinguishing": 20852, "##yler": 20853, "grasping": 20854, "sermons": 20855, "tomato": 20856, "bland": 20857, "stimulation": 20858, "avenues": 20859, "##eux": 20860, "spreads": 20861, "scarlett": 20862, "fern": 20863, "pentagon": 20864, "assert": 20865, "baird": 20866, "chesapeake": 20867, "ir": 20868, "calmed": 20869, "distortion": 20870, "fatalities": 20871, "##olis": 20872, "correctional": 20873, "pricing": 20874, "##astic": 20875, "##gina": 20876, "prom": 20877, "dammit": 20878, "ying": 20879, "collaborate": 20880, "##chia": 20881, "welterweight": 20882, "33rd": 20883, "pointer": 20884, "substitution": 20885, "bonded": 20886, "umpire": 20887, "communicating": 20888, "multitude": 20889, "paddle": 20890, "##obe": 20891, "federally": 20892, "intimacy": 20893, "##insky": 20894, "betray": 20895, "ssr": 20896, "##lett": 20897, "##lean": 20898, "##lves": 20899, "##therapy": 20900, "airbus": 20901, "##tery": 20902, "functioned": 20903, "ud": 20904, "bearer": 20905, "biomedical": 20906, "netflix": 20907, "##hire": 20908, "##nca": 20909, "condom": 20910, "brink": 20911, "ik": 20912, "##nical": 20913, "macy": 20914, "##bet": 20915, "flap": 20916, "gma": 20917, "experimented": 20918, "jelly": 20919, "lavender": 20920, "##icles": 20921, "##ulia": 20922, "munro": 20923, "##mian": 20924, "##tial": 20925, "rye": 20926, "##rle": 20927, "60th": 20928, "gigs": 20929, "hottest": 20930, "rotated": 20931, "predictions": 20932, "fuji": 20933, "bu": 20934, "##erence": 20935, "##omi": 20936, "barangay": 20937, "##fulness": 20938, "##sas": 20939, "clocks": 20940, "##rwood": 20941, "##liness": 20942, "cereal": 20943, "roe": 20944, "wight": 20945, "decker": 20946, "uttered": 20947, "babu": 20948, "onion": 20949, "xml": 20950, "forcibly": 20951, "##df": 20952, "petra": 20953, "sarcasm": 20954, "hartley": 20955, "peeled": 20956, "storytelling": 20957, "##42": 20958, "##xley": 20959, "##ysis": 20960, "##ffa": 20961, "fibre": 20962, "kiel": 20963, "auditor": 20964, "fig": 20965, "harald": 20966, "greenville": 20967, "##berries": 20968, "geographically": 20969, "nell": 20970, "quartz": 20971, "##athic": 20972, "cemeteries": 20973, "##lr": 20974, "crossings": 20975, "nah": 20976, "holloway": 20977, "reptiles": 20978, "chun": 20979, "sichuan": 20980, "snowy": 20981, "660": 20982, "corrections": 20983, "##ivo": 20984, "zheng": 20985, "ambassadors": 20986, "blacksmith": 20987, "fielded": 20988, "fluids": 20989, "hardcover": 20990, "turnover": 20991, "medications": 20992, "melvin": 20993, "academies": 20994, "##erton": 20995, "ro": 20996, "roach": 20997, "absorbing": 20998, "spaniards": 20999, "colton": 21000, "##founded": 21001, "outsider": 21002, "espionage": 21003, "kelsey": 21004, "245": 21005, "edible": 21006, "##ulf": 21007, "dora": 21008, "establishes": 21009, "##sham": 21010, "##tries": 21011, "contracting": 21012, "##tania": 21013, "cinematic": 21014, "costello": 21015, "nesting": 21016, "##uron": 21017, "connolly": 21018, "duff": 21019, "##nology": 21020, "mma": 21021, "##mata": 21022, "fergus": 21023, "sexes": 21024, "gi": 21025, "optics": 21026, "spectator": 21027, "woodstock": 21028, "banning": 21029, "##hee": 21030, "##fle": 21031, "differentiate": 21032, "outfielder": 21033, "refinery": 21034, "226": 21035, "312": 21036, "gerhard": 21037, "horde": 21038, "lair": 21039, "drastically": 21040, "##udi": 21041, "landfall": 21042, "##cheng": 21043, "motorsport": 21044, "odi": 21045, "##achi": 21046, "predominant": 21047, "quay": 21048, "skins": 21049, "##ental": 21050, "edna": 21051, "harshly": 21052, "complementary": 21053, "murdering": 21054, "##aves": 21055, "wreckage": 21056, "##90": 21057, "ono": 21058, "outstretched": 21059, "lennox": 21060, "munitions": 21061, "galen": 21062, "reconcile": 21063, "470": 21064, "scalp": 21065, "bicycles": 21066, "gillespie": 21067, "questionable": 21068, "rosenberg": 21069, "guillermo": 21070, "hostel": 21071, "jarvis": 21072, "kabul": 21073, "volvo": 21074, "opium": 21075, "yd": 21076, "##twined": 21077, "abuses": 21078, "decca": 21079, "outpost": 21080, "##cino": 21081, "sensible": 21082, "neutrality": 21083, "##64": 21084, "ponce": 21085, "anchorage": 21086, "atkins": 21087, "turrets": 21088, "inadvertently": 21089, "disagree": 21090, "libre": 21091, "vodka": 21092, "reassuring": 21093, "weighs": 21094, "##yal": 21095, "glide": 21096, "jumper": 21097, "ceilings": 21098, "repertory": 21099, "outs": 21100, "stain": 21101, "##bial": 21102, "envy": 21103, "##ucible": 21104, "smashing": 21105, "heightened": 21106, "policing": 21107, "hyun": 21108, "mixes": 21109, "lai": 21110, "prima": 21111, "##ples": 21112, "celeste": 21113, "##bina": 21114, "lucrative": 21115, "intervened": 21116, "kc": 21117, "manually": 21118, "##rned": 21119, "stature": 21120, "staffed": 21121, "bun": 21122, "bastards": 21123, "nairobi": 21124, "priced": 21125, "##auer": 21126, "thatcher": 21127, "##kia": 21128, "tripped": 21129, "comune": 21130, "##ogan": 21131, "##pled": 21132, "brasil": 21133, "incentives": 21134, "emanuel": 21135, "hereford": 21136, "musica": 21137, "##kim": 21138, "benedictine": 21139, "biennale": 21140, "##lani": 21141, "eureka": 21142, "gardiner": 21143, "rb": 21144, "knocks": 21145, "sha": 21146, "##ael": 21147, "##elled": 21148, "##onate": 21149, "efficacy": 21150, "ventura": 21151, "masonic": 21152, "sanford": 21153, "maize": 21154, "leverage": 21155, "##feit": 21156, "capacities": 21157, "santana": 21158, "##aur": 21159, "novelty": 21160, "vanilla": 21161, "##cter": 21162, "##tour": 21163, "benin": 21164, "##oir": 21165, "##rain": 21166, "neptune": 21167, "drafting": 21168, "tallinn": 21169, "##cable": 21170, "humiliation": 21171, "##boarding": 21172, "schleswig": 21173, "fabian": 21174, "bernardo": 21175, "liturgy": 21176, "spectacle": 21177, "sweeney": 21178, "pont": 21179, "routledge": 21180, "##tment": 21181, "cosmos": 21182, "ut": 21183, "hilt": 21184, "sleek": 21185, "universally": 21186, "##eville": 21187, "##gawa": 21188, "typed": 21189, "##dry": 21190, "favors": 21191, "allegheny": 21192, "glaciers": 21193, "##rly": 21194, "recalling": 21195, "aziz": 21196, "##log": 21197, "parasite": 21198, "requiem": 21199, "auf": 21200, "##berto": 21201, "##llin": 21202, "illumination": 21203, "##breaker": 21204, "##issa": 21205, "festivities": 21206, "bows": 21207, "govern": 21208, "vibe": 21209, "vp": 21210, "333": 21211, "sprawled": 21212, "larson": 21213, "pilgrim": 21214, "bwf": 21215, "leaping": 21216, "##rts": 21217, "##ssel": 21218, "alexei": 21219, "greyhound": 21220, "hoarse": 21221, "##dler": 21222, "##oration": 21223, "seneca": 21224, "##cule": 21225, "gaping": 21226, "##ulously": 21227, "##pura": 21228, "cinnamon": 21229, "##gens": 21230, "##rricular": 21231, "craven": 21232, "fantasies": 21233, "houghton": 21234, "engined": 21235, "reigned": 21236, "dictator": 21237, "supervising": 21238, "##oris": 21239, "bogota": 21240, "commentaries": 21241, "unnatural": 21242, "fingernails": 21243, "spirituality": 21244, "tighten": 21245, "##tm": 21246, "canadiens": 21247, "protesting": 21248, "intentional": 21249, "cheers": 21250, "sparta": 21251, "##ytic": 21252, "##iere": 21253, "##zine": 21254, "widen": 21255, "belgarath": 21256, "controllers": 21257, "dodd": 21258, "iaaf": 21259, "navarre": 21260, "##ication": 21261, "defect": 21262, "squire": 21263, "steiner": 21264, "whisky": 21265, "##mins": 21266, "560": 21267, "inevitably": 21268, "tome": 21269, "##gold": 21270, "chew": 21271, "##uid": 21272, "##lid": 21273, "elastic": 21274, "##aby": 21275, "streaked": 21276, "alliances": 21277, "jailed": 21278, "regal": 21279, "##ined": 21280, "##phy": 21281, "czechoslovak": 21282, "narration": 21283, "absently": 21284, "##uld": 21285, "bluegrass": 21286, "guangdong": 21287, "quran": 21288, "criticizing": 21289, "hose": 21290, "hari": 21291, "##liest": 21292, "##owa": 21293, "skier": 21294, "streaks": 21295, "deploy": 21296, "##lom": 21297, "raft": 21298, "bose": 21299, "dialed": 21300, "huff": 21301, "##eira": 21302, "haifa": 21303, "simplest": 21304, "bursting": 21305, "endings": 21306, "ib": 21307, "sultanate": 21308, "##titled": 21309, "franks": 21310, "whitman": 21311, "ensures": 21312, "sven": 21313, "##ggs": 21314, "collaborators": 21315, "forster": 21316, "organising": 21317, "ui": 21318, "banished": 21319, "napier": 21320, "injustice": 21321, "teller": 21322, "layered": 21323, "thump": 21324, "##otti": 21325, "roc": 21326, "battleships": 21327, "evidenced": 21328, "fugitive": 21329, "sadie": 21330, "robotics": 21331, "##roud": 21332, "equatorial": 21333, "geologist": 21334, "##iza": 21335, "yielding": 21336, "##bron": 21337, "##sr": 21338, "internationale": 21339, "mecca": 21340, "##diment": 21341, "sbs": 21342, "skyline": 21343, "toad": 21344, "uploaded": 21345, "reflective": 21346, "undrafted": 21347, "lal": 21348, "leafs": 21349, "bayern": 21350, "##dai": 21351, "lakshmi": 21352, "shortlisted": 21353, "##stick": 21354, "##wicz": 21355, "camouflage": 21356, "donate": 21357, "af": 21358, "christi": 21359, "lau": 21360, "##acio": 21361, "disclosed": 21362, "nemesis": 21363, "1761": 21364, "assemble": 21365, "straining": 21366, "northamptonshire": 21367, "tal": 21368, "##asi": 21369, "bernardino": 21370, "premature": 21371, "heidi": 21372, "42nd": 21373, "coefficients": 21374, "galactic": 21375, "reproduce": 21376, "buzzed": 21377, "sensations": 21378, "zionist": 21379, "monsieur": 21380, "myrtle": 21381, "##eme": 21382, "archery": 21383, "strangled": 21384, "musically": 21385, "viewpoint": 21386, "antiquities": 21387, "bei": 21388, "trailers": 21389, "seahawks": 21390, "cured": 21391, "pee": 21392, "preferring": 21393, "tasmanian": 21394, "lange": 21395, "sul": 21396, "##mail": 21397, "##working": 21398, "colder": 21399, "overland": 21400, "lucivar": 21401, "massey": 21402, "gatherings": 21403, "haitian": 21404, "##smith": 21405, "disapproval": 21406, "flaws": 21407, "##cco": 21408, "##enbach": 21409, "1766": 21410, "npr": 21411, "##icular": 21412, "boroughs": 21413, "creole": 21414, "forums": 21415, "techno": 21416, "1755": 21417, "dent": 21418, "abdominal": 21419, "streetcar": 21420, "##eson": 21421, "##stream": 21422, "procurement": 21423, "gemini": 21424, "predictable": 21425, "##tya": 21426, "acheron": 21427, "christoph": 21428, "feeder": 21429, "fronts": 21430, "vendor": 21431, "bernhard": 21432, "jammu": 21433, "tumors": 21434, "slang": 21435, "##uber": 21436, "goaltender": 21437, "twists": 21438, "curving": 21439, "manson": 21440, "vuelta": 21441, "mer": 21442, "peanut": 21443, "confessions": 21444, "pouch": 21445, "unpredictable": 21446, "allowance": 21447, "theodor": 21448, "vascular": 21449, "##factory": 21450, "bala": 21451, "authenticity": 21452, "metabolic": 21453, "coughing": 21454, "nanjing": 21455, "##cea": 21456, "pembroke": 21457, "##bard": 21458, "splendid": 21459, "36th": 21460, "ff": 21461, "hourly": 21462, "##ahu": 21463, "elmer": 21464, "handel": 21465, "##ivate": 21466, "awarding": 21467, "thrusting": 21468, "dl": 21469, "experimentation": 21470, "##hesion": 21471, "##46": 21472, "caressed": 21473, "entertained": 21474, "steak": 21475, "##rangle": 21476, "biologist": 21477, "orphans": 21478, "baroness": 21479, "oyster": 21480, "stepfather": 21481, "##dridge": 21482, "mirage": 21483, "reefs": 21484, "speeding": 21485, "##31": 21486, "barons": 21487, "1764": 21488, "227": 21489, "inhabit": 21490, "preached": 21491, "repealed": 21492, "##tral": 21493, "honoring": 21494, "boogie": 21495, "captives": 21496, "administer": 21497, "johanna": 21498, "##imate": 21499, "gel": 21500, "suspiciously": 21501, "1767": 21502, "sobs": 21503, "##dington": 21504, "backbone": 21505, "hayward": 21506, "garry": 21507, "##folding": 21508, "##nesia": 21509, "maxi": 21510, "##oof": 21511, "##ppe": 21512, "ellison": 21513, "galileo": 21514, "##stand": 21515, "crimea": 21516, "frenzy": 21517, "amour": 21518, "bumper": 21519, "matrices": 21520, "natalia": 21521, "baking": 21522, "garth": 21523, "palestinians": 21524, "##grove": 21525, "smack": 21526, "conveyed": 21527, "ensembles": 21528, "gardening": 21529, "##manship": 21530, "##rup": 21531, "##stituting": 21532, "1640": 21533, "harvesting": 21534, "topography": 21535, "jing": 21536, "shifters": 21537, "dormitory": 21538, "##carriage": 21539, "##lston": 21540, "ist": 21541, "skulls": 21542, "##stadt": 21543, "dolores": 21544, "jewellery": 21545, "sarawak": 21546, "##wai": 21547, "##zier": 21548, "fences": 21549, "christy": 21550, "confinement": 21551, "tumbling": 21552, "credibility": 21553, "fir": 21554, "stench": 21555, "##bria": 21556, "##plication": 21557, "##nged": 21558, "##sam": 21559, "virtues": 21560, "##belt": 21561, "marjorie": 21562, "pba": 21563, "##eem": 21564, "##made": 21565, "celebrates": 21566, "schooner": 21567, "agitated": 21568, "barley": 21569, "fulfilling": 21570, "anthropologist": 21571, "##pro": 21572, "restrict": 21573, "novi": 21574, "regulating": 21575, "##nent": 21576, "padres": 21577, "##rani": 21578, "##hesive": 21579, "loyola": 21580, "tabitha": 21581, "milky": 21582, "olson": 21583, "proprietor": 21584, "crambidae": 21585, "guarantees": 21586, "intercollegiate": 21587, "ljubljana": 21588, "hilda": 21589, "##sko": 21590, "ignorant": 21591, "hooded": 21592, "##lts": 21593, "sardinia": 21594, "##lidae": 21595, "##vation": 21596, "frontman": 21597, "privileged": 21598, "witchcraft": 21599, "##gp": 21600, "jammed": 21601, "laude": 21602, "poking": 21603, "##than": 21604, "bracket": 21605, "amazement": 21606, "yunnan": 21607, "##erus": 21608, "maharaja": 21609, "linnaeus": 21610, "264": 21611, "commissioning": 21612, "milano": 21613, "peacefully": 21614, "##logies": 21615, "akira": 21616, "rani": 21617, "regulator": 21618, "##36": 21619, "grasses": 21620, "##rance": 21621, "luzon": 21622, "crows": 21623, "compiler": 21624, "gretchen": 21625, "seaman": 21626, "edouard": 21627, "tab": 21628, "buccaneers": 21629, "ellington": 21630, "hamlets": 21631, "whig": 21632, "socialists": 21633, "##anto": 21634, "directorial": 21635, "easton": 21636, "mythological": 21637, "##kr": 21638, "##vary": 21639, "rhineland": 21640, "semantic": 21641, "taut": 21642, "dune": 21643, "inventions": 21644, "succeeds": 21645, "##iter": 21646, "replication": 21647, "branched": 21648, "##pired": 21649, "jul": 21650, "prosecuted": 21651, "kangaroo": 21652, "penetrated": 21653, "##avian": 21654, "middlesbrough": 21655, "doses": 21656, "bleak": 21657, "madam": 21658, "predatory": 21659, "relentless": 21660, "##vili": 21661, "reluctance": 21662, "##vir": 21663, "hailey": 21664, "crore": 21665, "silvery": 21666, "1759": 21667, "monstrous": 21668, "swimmers": 21669, "transmissions": 21670, "hawthorn": 21671, "informing": 21672, "##eral": 21673, "toilets": 21674, "caracas": 21675, "crouch": 21676, "kb": 21677, "##sett": 21678, "295": 21679, "cartel": 21680, "hadley": 21681, "##aling": 21682, "alexia": 21683, "yvonne": 21684, "##biology": 21685, "cinderella": 21686, "eton": 21687, "superb": 21688, "blizzard": 21689, "stabbing": 21690, "industrialist": 21691, "maximus": 21692, "##gm": 21693, "##orus": 21694, "groves": 21695, "maud": 21696, "clade": 21697, "oversized": 21698, "comedic": 21699, "##bella": 21700, "rosen": 21701, "nomadic": 21702, "fulham": 21703, "montane": 21704, "beverages": 21705, "galaxies": 21706, "redundant": 21707, "swarm": 21708, "##rot": 21709, "##folia": 21710, "##llis": 21711, "buckinghamshire": 21712, "fen": 21713, "bearings": 21714, "bahadur": 21715, "##rom": 21716, "gilles": 21717, "phased": 21718, "dynamite": 21719, "faber": 21720, "benoit": 21721, "vip": 21722, "##ount": 21723, "##wd": 21724, "booking": 21725, "fractured": 21726, "tailored": 21727, "anya": 21728, "spices": 21729, "westwood": 21730, "cairns": 21731, "auditions": 21732, "inflammation": 21733, "steamed": 21734, "##rocity": 21735, "##acion": 21736, "##urne": 21737, "skyla": 21738, "thereof": 21739, "watford": 21740, "torment": 21741, "archdeacon": 21742, "transforms": 21743, "lulu": 21744, "demeanor": 21745, "fucked": 21746, "serge": 21747, "##sor": 21748, "mckenna": 21749, "minas": 21750, "entertainer": 21751, "##icide": 21752, "caress": 21753, "originate": 21754, "residue": 21755, "##sty": 21756, "1740": 21757, "##ilised": 21758, "##org": 21759, "beech": 21760, "##wana": 21761, "subsidies": 21762, "##ghton": 21763, "emptied": 21764, "gladstone": 21765, "ru": 21766, "firefighters": 21767, "voodoo": 21768, "##rcle": 21769, "het": 21770, "nightingale": 21771, "tamara": 21772, "edmond": 21773, "ingredient": 21774, "weaknesses": 21775, "silhouette": 21776, "285": 21777, "compatibility": 21778, "withdrawing": 21779, "hampson": 21780, "##mona": 21781, "anguish": 21782, "giggling": 21783, "##mber": 21784, "bookstore": 21785, "##jiang": 21786, "southernmost": 21787, "tilting": 21788, "##vance": 21789, "bai": 21790, "economical": 21791, "rf": 21792, "briefcase": 21793, "dreadful": 21794, "hinted": 21795, "projections": 21796, "shattering": 21797, "totaling": 21798, "##rogate": 21799, "analogue": 21800, "indicted": 21801, "periodical": 21802, "fullback": 21803, "##dman": 21804, "haynes": 21805, "##tenberg": 21806, "##ffs": 21807, "##ishment": 21808, "1745": 21809, "thirst": 21810, "stumble": 21811, "penang": 21812, "vigorous": 21813, "##ddling": 21814, "##kor": 21815, "##lium": 21816, "octave": 21817, "##ove": 21818, "##enstein": 21819, "##inen": 21820, "##ones": 21821, "siberian": 21822, "##uti": 21823, "cbn": 21824, "repeal": 21825, "swaying": 21826, "##vington": 21827, "khalid": 21828, "tanaka": 21829, "unicorn": 21830, "otago": 21831, "plastered": 21832, "lobe": 21833, "riddle": 21834, "##rella": 21835, "perch": 21836, "##ishing": 21837, "croydon": 21838, "filtered": 21839, "graeme": 21840, "tripoli": 21841, "##ossa": 21842, "crocodile": 21843, "##chers": 21844, "sufi": 21845, "mined": 21846, "##tung": 21847, "inferno": 21848, "lsu": 21849, "##phi": 21850, "swelled": 21851, "utilizes": 21852, "£2": 21853, "cale": 21854, "periodicals": 21855, "styx": 21856, "hike": 21857, "informally": 21858, "coop": 21859, "lund": 21860, "##tidae": 21861, "ala": 21862, "hen": 21863, "qui": 21864, "transformations": 21865, "disposed": 21866, "sheath": 21867, "chickens": 21868, "##cade": 21869, "fitzroy": 21870, "sas": 21871, "silesia": 21872, "unacceptable": 21873, "odisha": 21874, "1650": 21875, "sabrina": 21876, "pe": 21877, "spokane": 21878, "ratios": 21879, "athena": 21880, "massage": 21881, "shen": 21882, "dilemma": 21883, "##drum": 21884, "##riz": 21885, "##hul": 21886, "corona": 21887, "doubtful": 21888, "niall": 21889, "##pha": 21890, "##bino": 21891, "fines": 21892, "cite": 21893, "acknowledging": 21894, "bangor": 21895, "ballard": 21896, "bathurst": 21897, "##resh": 21898, "huron": 21899, "mustered": 21900, "alzheimer": 21901, "garments": 21902, "kinase": 21903, "tyre": 21904, "warship": 21905, "##cp": 21906, "flashback": 21907, "pulmonary": 21908, "braun": 21909, "cheat": 21910, "kamal": 21911, "cyclists": 21912, "constructions": 21913, "grenades": 21914, "ndp": 21915, "traveller": 21916, "excuses": 21917, "stomped": 21918, "signalling": 21919, "trimmed": 21920, "futsal": 21921, "mosques": 21922, "relevance": 21923, "##wine": 21924, "wta": 21925, "##23": 21926, "##vah": 21927, "##lter": 21928, "hoc": 21929, "##riding": 21930, "optimistic": 21931, "##´s": 21932, "deco": 21933, "sim": 21934, "interacting": 21935, "rejecting": 21936, "moniker": 21937, "waterways": 21938, "##ieri": 21939, "##oku": 21940, "mayors": 21941, "gdansk": 21942, "outnumbered": 21943, "pearls": 21944, "##ended": 21945, "##hampton": 21946, "fairs": 21947, "totals": 21948, "dominating": 21949, "262": 21950, "notions": 21951, "stairway": 21952, "compiling": 21953, "pursed": 21954, "commodities": 21955, "grease": 21956, "yeast": 21957, "##jong": 21958, "carthage": 21959, "griffiths": 21960, "residual": 21961, "amc": 21962, "contraction": 21963, "laird": 21964, "sapphire": 21965, "##marine": 21966, "##ivated": 21967, "amalgamation": 21968, "dissolve": 21969, "inclination": 21970, "lyle": 21971, "packaged": 21972, "altitudes": 21973, "suez": 21974, "canons": 21975, "graded": 21976, "lurched": 21977, "narrowing": 21978, "boasts": 21979, "guise": 21980, "wed": 21981, "enrico": 21982, "##ovsky": 21983, "rower": 21984, "scarred": 21985, "bree": 21986, "cub": 21987, "iberian": 21988, "protagonists": 21989, "bargaining": 21990, "proposing": 21991, "trainers": 21992, "voyages": 21993, "vans": 21994, "fishes": 21995, "##aea": 21996, "##ivist": 21997, "##verance": 21998, "encryption": 21999, "artworks": 22000, "kazan": 22001, "sabre": 22002, "cleopatra": 22003, "hepburn": 22004, "rotting": 22005, "supremacy": 22006, "mecklenburg": 22007, "##brate": 22008, "burrows": 22009, "hazards": 22010, "outgoing": 22011, "flair": 22012, "organizes": 22013, "##ctions": 22014, "scorpion": 22015, "##usions": 22016, "boo": 22017, "234": 22018, "chevalier": 22019, "dunedin": 22020, "slapping": 22021, "##34": 22022, "ineligible": 22023, "pensions": 22024, "##38": 22025, "##omic": 22026, "manufactures": 22027, "emails": 22028, "bismarck": 22029, "238": 22030, "weakening": 22031, "blackish": 22032, "ding": 22033, "mcgee": 22034, "quo": 22035, "##rling": 22036, "northernmost": 22037, "xx": 22038, "manpower": 22039, "greed": 22040, "sampson": 22041, "clicking": 22042, "##ange": 22043, "##horpe": 22044, "##inations": 22045, "##roving": 22046, "torre": 22047, "##eptive": 22048, "##moral": 22049, "symbolism": 22050, "38th": 22051, "asshole": 22052, "meritorious": 22053, "outfits": 22054, "splashed": 22055, "biographies": 22056, "sprung": 22057, "astros": 22058, "##tale": 22059, "302": 22060, "737": 22061, "filly": 22062, "raoul": 22063, "nw": 22064, "tokugawa": 22065, "linden": 22066, "clubhouse": 22067, "##apa": 22068, "tracts": 22069, "romano": 22070, "##pio": 22071, "putin": 22072, "tags": 22073, "##note": 22074, "chained": 22075, "dickson": 22076, "gunshot": 22077, "moe": 22078, "gunn": 22079, "rashid": 22080, "##tails": 22081, "zipper": 22082, "##bas": 22083, "##nea": 22084, "contrasted": 22085, "##ply": 22086, "##udes": 22087, "plum": 22088, "pharaoh": 22089, "##pile": 22090, "aw": 22091, "comedies": 22092, "ingrid": 22093, "sandwiches": 22094, "subdivisions": 22095, "1100": 22096, "mariana": 22097, "nokia": 22098, "kamen": 22099, "hz": 22100, "delaney": 22101, "veto": 22102, "herring": 22103, "##words": 22104, "possessive": 22105, "outlines": 22106, "##roup": 22107, "siemens": 22108, "stairwell": 22109, "rc": 22110, "gallantry": 22111, "messiah": 22112, "palais": 22113, "yells": 22114, "233": 22115, "zeppelin": 22116, "##dm": 22117, "bolivar": 22118, "##cede": 22119, "smackdown": 22120, "mckinley": 22121, "##mora": 22122, "##yt": 22123, "muted": 22124, "geologic": 22125, "finely": 22126, "unitary": 22127, "avatar": 22128, "hamas": 22129, "maynard": 22130, "rees": 22131, "bog": 22132, "contrasting": 22133, "##rut": 22134, "liv": 22135, "chico": 22136, "disposition": 22137, "pixel": 22138, "##erate": 22139, "becca": 22140, "dmitry": 22141, "yeshiva": 22142, "narratives": 22143, "##lva": 22144, "##ulton": 22145, "mercenary": 22146, "sharpe": 22147, "tempered": 22148, "navigate": 22149, "stealth": 22150, "amassed": 22151, "keynes": 22152, "##lini": 22153, "untouched": 22154, "##rrie": 22155, "havoc": 22156, "lithium": 22157, "##fighting": 22158, "abyss": 22159, "graf": 22160, "southward": 22161, "wolverine": 22162, "balloons": 22163, "implements": 22164, "ngos": 22165, "transitions": 22166, "##icum": 22167, "ambushed": 22168, "concacaf": 22169, "dormant": 22170, "economists": 22171, "##dim": 22172, "costing": 22173, "csi": 22174, "rana": 22175, "universite": 22176, "boulders": 22177, "verity": 22178, "##llon": 22179, "collin": 22180, "mellon": 22181, "misses": 22182, "cypress": 22183, "fluorescent": 22184, "lifeless": 22185, "spence": 22186, "##ulla": 22187, "crewe": 22188, "shepard": 22189, "pak": 22190, "revelations": 22191, "##م": 22192, "jolly": 22193, "gibbons": 22194, "paw": 22195, "##dro": 22196, "##quel": 22197, "freeing": 22198, "##test": 22199, "shack": 22200, "fries": 22201, "palatine": 22202, "##51": 22203, "##hiko": 22204, "accompaniment": 22205, "cruising": 22206, "recycled": 22207, "##aver": 22208, "erwin": 22209, "sorting": 22210, "synthesizers": 22211, "dyke": 22212, "realities": 22213, "sg": 22214, "strides": 22215, "enslaved": 22216, "wetland": 22217, "##ghan": 22218, "competence": 22219, "gunpowder": 22220, "grassy": 22221, "maroon": 22222, "reactors": 22223, "objection": 22224, "##oms": 22225, "carlson": 22226, "gearbox": 22227, "macintosh": 22228, "radios": 22229, "shelton": 22230, "##sho": 22231, "clergyman": 22232, "prakash": 22233, "254": 22234, "mongols": 22235, "trophies": 22236, "oricon": 22237, "228": 22238, "stimuli": 22239, "twenty20": 22240, "cantonese": 22241, "cortes": 22242, "mirrored": 22243, "##saurus": 22244, "bhp": 22245, "cristina": 22246, "melancholy": 22247, "##lating": 22248, "enjoyable": 22249, "nuevo": 22250, "##wny": 22251, "downfall": 22252, "schumacher": 22253, "##ind": 22254, "banging": 22255, "lausanne": 22256, "rumbled": 22257, "paramilitary": 22258, "reflex": 22259, "ax": 22260, "amplitude": 22261, "migratory": 22262, "##gall": 22263, "##ups": 22264, "midi": 22265, "barnard": 22266, "lastly": 22267, "sherry": 22268, "##hp": 22269, "##nall": 22270, "keystone": 22271, "##kra": 22272, "carleton": 22273, "slippery": 22274, "##53": 22275, "coloring": 22276, "foe": 22277, "socket": 22278, "otter": 22279, "##rgos": 22280, "mats": 22281, "##tose": 22282, "consultants": 22283, "bafta": 22284, "bison": 22285, "topping": 22286, "##km": 22287, "490": 22288, "primal": 22289, "abandonment": 22290, "transplant": 22291, "atoll": 22292, "hideous": 22293, "mort": 22294, "pained": 22295, "reproduced": 22296, "tae": 22297, "howling": 22298, "##turn": 22299, "unlawful": 22300, "billionaire": 22301, "hotter": 22302, "poised": 22303, "lansing": 22304, "##chang": 22305, "dinamo": 22306, "retro": 22307, "messing": 22308, "nfc": 22309, "domesday": 22310, "##mina": 22311, "blitz": 22312, "timed": 22313, "##athing": 22314, "##kley": 22315, "ascending": 22316, "gesturing": 22317, "##izations": 22318, "signaled": 22319, "tis": 22320, "chinatown": 22321, "mermaid": 22322, "savanna": 22323, "jameson": 22324, "##aint": 22325, "catalina": 22326, "##pet": 22327, "##hers": 22328, "cochrane": 22329, "cy": 22330, "chatting": 22331, "##kus": 22332, "alerted": 22333, "computation": 22334, "mused": 22335, "noelle": 22336, "majestic": 22337, "mohawk": 22338, "campo": 22339, "octagonal": 22340, "##sant": 22341, "##hend": 22342, "241": 22343, "aspiring": 22344, "##mart": 22345, "comprehend": 22346, "iona": 22347, "paralyzed": 22348, "shimmering": 22349, "swindon": 22350, "rhone": 22351, "##eley": 22352, "reputed": 22353, "configurations": 22354, "pitchfork": 22355, "agitation": 22356, "francais": 22357, "gillian": 22358, "lipstick": 22359, "##ilo": 22360, "outsiders": 22361, "pontifical": 22362, "resisting": 22363, "bitterness": 22364, "sewer": 22365, "rockies": 22366, "##edd": 22367, "##ucher": 22368, "misleading": 22369, "1756": 22370, "exiting": 22371, "galloway": 22372, "##nging": 22373, "risked": 22374, "##heart": 22375, "246": 22376, "commemoration": 22377, "schultz": 22378, "##rka": 22379, "integrating": 22380, "##rsa": 22381, "poses": 22382, "shrieked": 22383, "##weiler": 22384, "guineas": 22385, "gladys": 22386, "jerking": 22387, "owls": 22388, "goldsmith": 22389, "nightly": 22390, "penetrating": 22391, "##unced": 22392, "lia": 22393, "##33": 22394, "ignited": 22395, "betsy": 22396, "##aring": 22397, "##thorpe": 22398, "follower": 22399, "vigorously": 22400, "##rave": 22401, "coded": 22402, "kiran": 22403, "knit": 22404, "zoology": 22405, "tbilisi": 22406, "##28": 22407, "##bered": 22408, "repository": 22409, "govt": 22410, "deciduous": 22411, "dino": 22412, "growling": 22413, "##bba": 22414, "enhancement": 22415, "unleashed": 22416, "chanting": 22417, "pussy": 22418, "biochemistry": 22419, "##eric": 22420, "kettle": 22421, "repression": 22422, "toxicity": 22423, "nrhp": 22424, "##arth": 22425, "##kko": 22426, "##bush": 22427, "ernesto": 22428, "commended": 22429, "outspoken": 22430, "242": 22431, "mca": 22432, "parchment": 22433, "sms": 22434, "kristen": 22435, "##aton": 22436, "bisexual": 22437, "raked": 22438, "glamour": 22439, "navajo": 22440, "a2": 22441, "conditioned": 22442, "showcased": 22443, "##hma": 22444, "spacious": 22445, "youthful": 22446, "##esa": 22447, "usl": 22448, "appliances": 22449, "junta": 22450, "brest": 22451, "layne": 22452, "conglomerate": 22453, "enchanted": 22454, "chao": 22455, "loosened": 22456, "picasso": 22457, "circulating": 22458, "inspect": 22459, "montevideo": 22460, "##centric": 22461, "##kti": 22462, "piazza": 22463, "spurred": 22464, "##aith": 22465, "bari": 22466, "freedoms": 22467, "poultry": 22468, "stamford": 22469, "lieu": 22470, "##ect": 22471, "indigo": 22472, "sarcastic": 22473, "bahia": 22474, "stump": 22475, "attach": 22476, "dvds": 22477, "frankenstein": 22478, "lille": 22479, "approx": 22480, "scriptures": 22481, "pollen": 22482, "##script": 22483, "nmi": 22484, "overseen": 22485, "##ivism": 22486, "tides": 22487, "proponent": 22488, "newmarket": 22489, "inherit": 22490, "milling": 22491, "##erland": 22492, "centralized": 22493, "##rou": 22494, "distributors": 22495, "credentials": 22496, "drawers": 22497, "abbreviation": 22498, "##lco": 22499, "##xon": 22500, "downing": 22501, "uncomfortably": 22502, "ripe": 22503, "##oes": 22504, "erase": 22505, "franchises": 22506, "##ever": 22507, "populace": 22508, "##bery": 22509, "##khar": 22510, "decomposition": 22511, "pleas": 22512, "##tet": 22513, "daryl": 22514, "sabah": 22515, "##stle": 22516, "##wide": 22517, "fearless": 22518, "genie": 22519, "lesions": 22520, "annette": 22521, "##ogist": 22522, "oboe": 22523, "appendix": 22524, "nair": 22525, "dripped": 22526, "petitioned": 22527, "maclean": 22528, "mosquito": 22529, "parrot": 22530, "rpg": 22531, "hampered": 22532, "1648": 22533, "operatic": 22534, "reservoirs": 22535, "##tham": 22536, "irrelevant": 22537, "jolt": 22538, "summarized": 22539, "##fp": 22540, "medallion": 22541, "##taff": 22542, "##−": 22543, "clawed": 22544, "harlow": 22545, "narrower": 22546, "goddard": 22547, "marcia": 22548, "bodied": 22549, "fremont": 22550, "suarez": 22551, "altering": 22552, "tempest": 22553, "mussolini": 22554, "porn": 22555, "##isms": 22556, "sweetly": 22557, "oversees": 22558, "walkers": 22559, "solitude": 22560, "grimly": 22561, "shrines": 22562, "hk": 22563, "ich": 22564, "supervisors": 22565, "hostess": 22566, "dietrich": 22567, "legitimacy": 22568, "brushes": 22569, "expressive": 22570, "##yp": 22571, "dissipated": 22572, "##rse": 22573, "localized": 22574, "systemic": 22575, "##nikov": 22576, "gettysburg": 22577, "##js": 22578, "##uaries": 22579, "dialogues": 22580, "muttering": 22581, "251": 22582, "housekeeper": 22583, "sicilian": 22584, "discouraged": 22585, "##frey": 22586, "beamed": 22587, "kaladin": 22588, "halftime": 22589, "kidnap": 22590, "##amo": 22591, "##llet": 22592, "1754": 22593, "synonymous": 22594, "depleted": 22595, "instituto": 22596, "insulin": 22597, "reprised": 22598, "##opsis": 22599, "clashed": 22600, "##ctric": 22601, "interrupting": 22602, "radcliffe": 22603, "insisting": 22604, "medici": 22605, "1715": 22606, "ejected": 22607, "playfully": 22608, "turbulent": 22609, "##47": 22610, "starvation": 22611, "##rini": 22612, "shipment": 22613, "rebellious": 22614, "petersen": 22615, "verification": 22616, "merits": 22617, "##rified": 22618, "cakes": 22619, "##charged": 22620, "1757": 22621, "milford": 22622, "shortages": 22623, "spying": 22624, "fidelity": 22625, "##aker": 22626, "emitted": 22627, "storylines": 22628, "harvested": 22629, "seismic": 22630, "##iform": 22631, "cheung": 22632, "kilda": 22633, "theoretically": 22634, "barbie": 22635, "lynx": 22636, "##rgy": 22637, "##tius": 22638, "goblin": 22639, "mata": 22640, "poisonous": 22641, "##nburg": 22642, "reactive": 22643, "residues": 22644, "obedience": 22645, "##евич": 22646, "conjecture": 22647, "##rac": 22648, "401": 22649, "hating": 22650, "sixties": 22651, "kicker": 22652, "moaning": 22653, "motown": 22654, "##bha": 22655, "emancipation": 22656, "neoclassical": 22657, "##hering": 22658, "consoles": 22659, "ebert": 22660, "professorship": 22661, "##tures": 22662, "sustaining": 22663, "assaults": 22664, "obeyed": 22665, "affluent": 22666, "incurred": 22667, "tornadoes": 22668, "##eber": 22669, "##zow": 22670, "emphasizing": 22671, "highlanders": 22672, "cheated": 22673, "helmets": 22674, "##ctus": 22675, "internship": 22676, "terence": 22677, "bony": 22678, "executions": 22679, "legislators": 22680, "berries": 22681, "peninsular": 22682, "tinged": 22683, "##aco": 22684, "1689": 22685, "amplifier": 22686, "corvette": 22687, "ribbons": 22688, "lavish": 22689, "pennant": 22690, "##lander": 22691, "worthless": 22692, "##chfield": 22693, "##forms": 22694, "mariano": 22695, "pyrenees": 22696, "expenditures": 22697, "##icides": 22698, "chesterfield": 22699, "mandir": 22700, "tailor": 22701, "39th": 22702, "sergey": 22703, "nestled": 22704, "willed": 22705, "aristocracy": 22706, "devotees": 22707, "goodnight": 22708, "raaf": 22709, "rumored": 22710, "weaponry": 22711, "remy": 22712, "appropriations": 22713, "harcourt": 22714, "burr": 22715, "riaa": 22716, "##lence": 22717, "limitation": 22718, "unnoticed": 22719, "guo": 22720, "soaking": 22721, "swamps": 22722, "##tica": 22723, "collapsing": 22724, "tatiana": 22725, "descriptive": 22726, "brigham": 22727, "psalm": 22728, "##chment": 22729, "maddox": 22730, "##lization": 22731, "patti": 22732, "caliph": 22733, "##aja": 22734, "akron": 22735, "injuring": 22736, "serra": 22737, "##ganj": 22738, "basins": 22739, "##sari": 22740, "astonished": 22741, "launcher": 22742, "##church": 22743, "hilary": 22744, "wilkins": 22745, "sewing": 22746, "##sf": 22747, "stinging": 22748, "##fia": 22749, "##ncia": 22750, "underwood": 22751, "startup": 22752, "##ition": 22753, "compilations": 22754, "vibrations": 22755, "embankment": 22756, "jurist": 22757, "##nity": 22758, "bard": 22759, "juventus": 22760, "groundwater": 22761, "kern": 22762, "palaces": 22763, "helium": 22764, "boca": 22765, "cramped": 22766, "marissa": 22767, "soto": 22768, "##worm": 22769, "jae": 22770, "princely": 22771, "##ggy": 22772, "faso": 22773, "bazaar": 22774, "warmly": 22775, "##voking": 22776, "229": 22777, "pairing": 22778, "##lite": 22779, "##grate": 22780, "##nets": 22781, "wien": 22782, "freaked": 22783, "ulysses": 22784, "rebirth": 22785, "##alia": 22786, "##rent": 22787, "mummy": 22788, "guzman": 22789, "jimenez": 22790, "stilled": 22791, "##nitz": 22792, "trajectory": 22793, "tha": 22794, "woken": 22795, "archival": 22796, "professions": 22797, "##pts": 22798, "##pta": 22799, "hilly": 22800, "shadowy": 22801, "shrink": 22802, "##bolt": 22803, "norwood": 22804, "glued": 22805, "migrate": 22806, "stereotypes": 22807, "devoid": 22808, "##pheus": 22809, "625": 22810, "evacuate": 22811, "horrors": 22812, "infancy": 22813, "gotham": 22814, "knowles": 22815, "optic": 22816, "downloaded": 22817, "sachs": 22818, "kingsley": 22819, "parramatta": 22820, "darryl": 22821, "mor": 22822, "##onale": 22823, "shady": 22824, "commence": 22825, "confesses": 22826, "kan": 22827, "##meter": 22828, "##placed": 22829, "marlborough": 22830, "roundabout": 22831, "regents": 22832, "frigates": 22833, "io": 22834, "##imating": 22835, "gothenburg": 22836, "revoked": 22837, "carvings": 22838, "clockwise": 22839, "convertible": 22840, "intruder": 22841, "##sche": 22842, "banged": 22843, "##ogo": 22844, "vicky": 22845, "bourgeois": 22846, "##mony": 22847, "dupont": 22848, "footing": 22849, "##gum": 22850, "pd": 22851, "##real": 22852, "buckle": 22853, "yun": 22854, "penthouse": 22855, "sane": 22856, "720": 22857, "serviced": 22858, "stakeholders": 22859, "neumann": 22860, "bb": 22861, "##eers": 22862, "comb": 22863, "##gam": 22864, "catchment": 22865, "pinning": 22866, "rallies": 22867, "typing": 22868, "##elles": 22869, "forefront": 22870, "freiburg": 22871, "sweetie": 22872, "giacomo": 22873, "widowed": 22874, "goodwill": 22875, "worshipped": 22876, "aspirations": 22877, "midday": 22878, "##vat": 22879, "fishery": 22880, "##trick": 22881, "bournemouth": 22882, "turk": 22883, "243": 22884, "hearth": 22885, "ethanol": 22886, "guadalajara": 22887, "murmurs": 22888, "sl": 22889, "##uge": 22890, "afforded": 22891, "scripted": 22892, "##hta": 22893, "wah": 22894, "##jn": 22895, "coroner": 22896, "translucent": 22897, "252": 22898, "memorials": 22899, "puck": 22900, "progresses": 22901, "clumsy": 22902, "##race": 22903, "315": 22904, "candace": 22905, "recounted": 22906, "##27": 22907, "##slin": 22908, "##uve": 22909, "filtering": 22910, "##mac": 22911, "howl": 22912, "strata": 22913, "heron": 22914, "leveled": 22915, "##ays": 22916, "dubious": 22917, "##oja": 22918, "##т": 22919, "##wheel": 22920, "citations": 22921, "exhibiting": 22922, "##laya": 22923, "##mics": 22924, "##pods": 22925, "turkic": 22926, "##lberg": 22927, "injunction": 22928, "##ennial": 22929, "##mit": 22930, "antibodies": 22931, "##44": 22932, "organise": 22933, "##rigues": 22934, "cardiovascular": 22935, "cushion": 22936, "inverness": 22937, "##zquez": 22938, "dia": 22939, "cocoa": 22940, "sibling": 22941, "##tman": 22942, "##roid": 22943, "expanse": 22944, "feasible": 22945, "tunisian": 22946, "algiers": 22947, "##relli": 22948, "rus": 22949, "bloomberg": 22950, "dso": 22951, "westphalia": 22952, "bro": 22953, "tacoma": 22954, "281": 22955, "downloads": 22956, "##ours": 22957, "konrad": 22958, "duran": 22959, "##hdi": 22960, "continuum": 22961, "jett": 22962, "compares": 22963, "legislator": 22964, "secession": 22965, "##nable": 22966, "##gues": 22967, "##zuka": 22968, "translating": 22969, "reacher": 22970, "##gley": 22971, "##ła": 22972, "aleppo": 22973, "##agi": 22974, "tc": 22975, "orchards": 22976, "trapping": 22977, "linguist": 22978, "versatile": 22979, "drumming": 22980, "postage": 22981, "calhoun": 22982, "superiors": 22983, "##mx": 22984, "barefoot": 22985, "leary": 22986, "##cis": 22987, "ignacio": 22988, "alfa": 22989, "kaplan": 22990, "##rogen": 22991, "bratislava": 22992, "mori": 22993, "##vot": 22994, "disturb": 22995, "haas": 22996, "313": 22997, "cartridges": 22998, "gilmore": 22999, "radiated": 23000, "salford": 23001, "tunic": 23002, "hades": 23003, "##ulsive": 23004, "archeological": 23005, "delilah": 23006, "magistrates": 23007, "auditioned": 23008, "brewster": 23009, "charters": 23010, "empowerment": 23011, "blogs": 23012, "cappella": 23013, "dynasties": 23014, "iroquois": 23015, "whipping": 23016, "##krishna": 23017, "raceway": 23018, "truths": 23019, "myra": 23020, "weaken": 23021, "judah": 23022, "mcgregor": 23023, "##horse": 23024, "mic": 23025, "refueling": 23026, "37th": 23027, "burnley": 23028, "bosses": 23029, "markus": 23030, "premio": 23031, "query": 23032, "##gga": 23033, "dunbar": 23034, "##economic": 23035, "darkest": 23036, "lyndon": 23037, "sealing": 23038, "commendation": 23039, "reappeared": 23040, "##mun": 23041, "addicted": 23042, "ezio": 23043, "slaughtered": 23044, "satisfactory": 23045, "shuffle": 23046, "##eves": 23047, "##thic": 23048, "##uj": 23049, "fortification": 23050, "warrington": 23051, "##otto": 23052, "resurrected": 23053, "fargo": 23054, "mane": 23055, "##utable": 23056, "##lei": 23057, "##space": 23058, "foreword": 23059, "ox": 23060, "##aris": 23061, "##vern": 23062, "abrams": 23063, "hua": 23064, "##mento": 23065, "sakura": 23066, "##alo": 23067, "uv": 23068, "sentimental": 23069, "##skaya": 23070, "midfield": 23071, "##eses": 23072, "sturdy": 23073, "scrolls": 23074, "macleod": 23075, "##kyu": 23076, "entropy": 23077, "##lance": 23078, "mitochondrial": 23079, "cicero": 23080, "excelled": 23081, "thinner": 23082, "convoys": 23083, "perceive": 23084, "##oslav": 23085, "##urable": 23086, "systematically": 23087, "grind": 23088, "burkina": 23089, "287": 23090, "##tagram": 23091, "ops": 23092, "##aman": 23093, "guantanamo": 23094, "##cloth": 23095, "##tite": 23096, "forcefully": 23097, "wavy": 23098, "##jou": 23099, "pointless": 23100, "##linger": 23101, "##tze": 23102, "layton": 23103, "portico": 23104, "superficial": 23105, "clerical": 23106, "outlaws": 23107, "##hism": 23108, "burials": 23109, "muir": 23110, "##inn": 23111, "creditors": 23112, "hauling": 23113, "rattle": 23114, "##leg": 23115, "calais": 23116, "monde": 23117, "archers": 23118, "reclaimed": 23119, "dwell": 23120, "wexford": 23121, "hellenic": 23122, "falsely": 23123, "remorse": 23124, "##tek": 23125, "dough": 23126, "furnishings": 23127, "##uttered": 23128, "gabon": 23129, "neurological": 23130, "novice": 23131, "##igraphy": 23132, "contemplated": 23133, "pulpit": 23134, "nightstand": 23135, "saratoga": 23136, "##istan": 23137, "documenting": 23138, "pulsing": 23139, "taluk": 23140, "##firmed": 23141, "busted": 23142, "marital": 23143, "##rien": 23144, "disagreements": 23145, "wasps": 23146, "##yes": 23147, "hodge": 23148, "mcdonnell": 23149, "mimic": 23150, "fran": 23151, "pendant": 23152, "dhabi": 23153, "musa": 23154, "##nington": 23155, "congratulations": 23156, "argent": 23157, "darrell": 23158, "concussion": 23159, "losers": 23160, "regrets": 23161, "thessaloniki": 23162, "reversal": 23163, "donaldson": 23164, "hardwood": 23165, "thence": 23166, "achilles": 23167, "ritter": 23168, "##eran": 23169, "demonic": 23170, "jurgen": 23171, "prophets": 23172, "goethe": 23173, "eki": 23174, "classmate": 23175, "buff": 23176, "##cking": 23177, "yank": 23178, "irrational": 23179, "##inging": 23180, "perished": 23181, "seductive": 23182, "qur": 23183, "sourced": 23184, "##crat": 23185, "##typic": 23186, "mustard": 23187, "ravine": 23188, "barre": 23189, "horizontally": 23190, "characterization": 23191, "phylogenetic": 23192, "boise": 23193, "##dit": 23194, "##runner": 23195, "##tower": 23196, "brutally": 23197, "intercourse": 23198, "seduce": 23199, "##bbing": 23200, "fay": 23201, "ferris": 23202, "ogden": 23203, "amar": 23204, "nik": 23205, "unarmed": 23206, "##inator": 23207, "evaluating": 23208, "kyrgyzstan": 23209, "sweetness": 23210, "##lford": 23211, "##oki": 23212, "mccormick": 23213, "meiji": 23214, "notoriety": 23215, "stimulate": 23216, "disrupt": 23217, "figuring": 23218, "instructional": 23219, "mcgrath": 23220, "##zoo": 23221, "groundbreaking": 23222, "##lto": 23223, "flinch": 23224, "khorasan": 23225, "agrarian": 23226, "bengals": 23227, "mixer": 23228, "radiating": 23229, "##sov": 23230, "ingram": 23231, "pitchers": 23232, "nad": 23233, "tariff": 23234, "##cript": 23235, "tata": 23236, "##codes": 23237, "##emi": 23238, "##ungen": 23239, "appellate": 23240, "lehigh": 23241, "##bled": 23242, "##giri": 23243, "brawl": 23244, "duct": 23245, "texans": 23246, "##ciation": 23247, "##ropolis": 23248, "skipper": 23249, "speculative": 23250, "vomit": 23251, "doctrines": 23252, "stresses": 23253, "253": 23254, "davy": 23255, "graders": 23256, "whitehead": 23257, "jozef": 23258, "timely": 23259, "cumulative": 23260, "haryana": 23261, "paints": 23262, "appropriately": 23263, "boon": 23264, "cactus": 23265, "##ales": 23266, "##pid": 23267, "dow": 23268, "legions": 23269, "##pit": 23270, "perceptions": 23271, "1730": 23272, "picturesque": 23273, "##yse": 23274, "periphery": 23275, "rune": 23276, "wr": 23277, "##aha": 23278, "celtics": 23279, "sentencing": 23280, "whoa": 23281, "##erin": 23282, "confirms": 23283, "variance": 23284, "425": 23285, "moines": 23286, "mathews": 23287, "spade": 23288, "rave": 23289, "m1": 23290, "fronted": 23291, "fx": 23292, "blending": 23293, "alleging": 23294, "reared": 23295, "##gl": 23296, "237": 23297, "##paper": 23298, "grassroots": 23299, "eroded": 23300, "##free": 23301, "##physical": 23302, "directs": 23303, "ordeal": 23304, "##sław": 23305, "accelerate": 23306, "hacker": 23307, "rooftop": 23308, "##inia": 23309, "lev": 23310, "buys": 23311, "cebu": 23312, "devote": 23313, "##lce": 23314, "specialising": 23315, "##ulsion": 23316, "choreographed": 23317, "repetition": 23318, "warehouses": 23319, "##ryl": 23320, "paisley": 23321, "tuscany": 23322, "analogy": 23323, "sorcerer": 23324, "hash": 23325, "huts": 23326, "shards": 23327, "descends": 23328, "exclude": 23329, "nix": 23330, "chaplin": 23331, "gaga": 23332, "ito": 23333, "vane": 23334, "##drich": 23335, "causeway": 23336, "misconduct": 23337, "limo": 23338, "orchestrated": 23339, "glands": 23340, "jana": 23341, "##kot": 23342, "u2": 23343, "##mple": 23344, "##sons": 23345, "branching": 23346, "contrasts": 23347, "scoop": 23348, "longed": 23349, "##virus": 23350, "chattanooga": 23351, "##75": 23352, "syrup": 23353, "cornerstone": 23354, "##tized": 23355, "##mind": 23356, "##iaceae": 23357, "careless": 23358, "precedence": 23359, "frescoes": 23360, "##uet": 23361, "chilled": 23362, "consult": 23363, "modelled": 23364, "snatch": 23365, "peat": 23366, "##thermal": 23367, "caucasian": 23368, "humane": 23369, "relaxation": 23370, "spins": 23371, "temperance": 23372, "##lbert": 23373, "occupations": 23374, "lambda": 23375, "hybrids": 23376, "moons": 23377, "mp3": 23378, "##oese": 23379, "247": 23380, "rolf": 23381, "societal": 23382, "yerevan": 23383, "ness": 23384, "##ssler": 23385, "befriended": 23386, "mechanized": 23387, "nominate": 23388, "trough": 23389, "boasted": 23390, "cues": 23391, "seater": 23392, "##hom": 23393, "bends": 23394, "##tangle": 23395, "conductors": 23396, "emptiness": 23397, "##lmer": 23398, "eurasian": 23399, "adriatic": 23400, "tian": 23401, "##cie": 23402, "anxiously": 23403, "lark": 23404, "propellers": 23405, "chichester": 23406, "jock": 23407, "ev": 23408, "2a": 23409, "##holding": 23410, "credible": 23411, "recounts": 23412, "tori": 23413, "loyalist": 23414, "abduction": 23415, "##hoot": 23416, "##redo": 23417, "nepali": 23418, "##mite": 23419, "ventral": 23420, "tempting": 23421, "##ango": 23422, "##crats": 23423, "steered": 23424, "##wice": 23425, "javelin": 23426, "dipping": 23427, "laborers": 23428, "prentice": 23429, "looming": 23430, "titanium": 23431, "##ː": 23432, "badges": 23433, "emir": 23434, "tensor": 23435, "##ntation": 23436, "egyptians": 23437, "rash": 23438, "denies": 23439, "hawthorne": 23440, "lombard": 23441, "showers": 23442, "wehrmacht": 23443, "dietary": 23444, "trojan": 23445, "##reus": 23446, "welles": 23447, "executing": 23448, "horseshoe": 23449, "lifeboat": 23450, "##lak": 23451, "elsa": 23452, "infirmary": 23453, "nearing": 23454, "roberta": 23455, "boyer": 23456, "mutter": 23457, "trillion": 23458, "joanne": 23459, "##fine": 23460, "##oked": 23461, "sinks": 23462, "vortex": 23463, "uruguayan": 23464, "clasp": 23465, "sirius": 23466, "##block": 23467, "accelerator": 23468, "prohibit": 23469, "sunken": 23470, "byu": 23471, "chronological": 23472, "diplomats": 23473, "ochreous": 23474, "510": 23475, "symmetrical": 23476, "1644": 23477, "maia": 23478, "##tology": 23479, "salts": 23480, "reigns": 23481, "atrocities": 23482, "##ия": 23483, "hess": 23484, "bared": 23485, "issn": 23486, "##vyn": 23487, "cater": 23488, "saturated": 23489, "##cycle": 23490, "##isse": 23491, "sable": 23492, "voyager": 23493, "dyer": 23494, "yusuf": 23495, "##inge": 23496, "fountains": 23497, "wolff": 23498, "##39": 23499, "##nni": 23500, "engraving": 23501, "rollins": 23502, "atheist": 23503, "ominous": 23504, "##ault": 23505, "herr": 23506, "chariot": 23507, "martina": 23508, "strung": 23509, "##fell": 23510, "##farlane": 23511, "horrific": 23512, "sahib": 23513, "gazes": 23514, "saetan": 23515, "erased": 23516, "ptolemy": 23517, "##olic": 23518, "flushing": 23519, "lauderdale": 23520, "analytic": 23521, "##ices": 23522, "530": 23523, "navarro": 23524, "beak": 23525, "gorilla": 23526, "herrera": 23527, "broom": 23528, "guadalupe": 23529, "raiding": 23530, "sykes": 23531, "311": 23532, "bsc": 23533, "deliveries": 23534, "1720": 23535, "invasions": 23536, "carmichael": 23537, "tajikistan": 23538, "thematic": 23539, "ecumenical": 23540, "sentiments": 23541, "onstage": 23542, "##rians": 23543, "##brand": 23544, "##sume": 23545, "catastrophic": 23546, "flanks": 23547, "molten": 23548, "##arns": 23549, "waller": 23550, "aimee": 23551, "terminating": 23552, "##icing": 23553, "alternately": 23554, "##oche": 23555, "nehru": 23556, "printers": 23557, "outraged": 23558, "##eving": 23559, "empires": 23560, "template": 23561, "banners": 23562, "repetitive": 23563, "za": 23564, "##oise": 23565, "vegetarian": 23566, "##tell": 23567, "guiana": 23568, "opt": 23569, "cavendish": 23570, "lucknow": 23571, "synthesized": 23572, "##hani": 23573, "##mada": 23574, "finalized": 23575, "##ctable": 23576, "fictitious": 23577, "mayoral": 23578, "unreliable": 23579, "##enham": 23580, "embracing": 23581, "peppers": 23582, "rbis": 23583, "##chio": 23584, "##neo": 23585, "inhibition": 23586, "slashed": 23587, "togo": 23588, "orderly": 23589, "embroidered": 23590, "safari": 23591, "salty": 23592, "236": 23593, "barron": 23594, "benito": 23595, "totaled": 23596, "##dak": 23597, "pubs": 23598, "simulated": 23599, "caden": 23600, "devin": 23601, "tolkien": 23602, "momma": 23603, "welding": 23604, "sesame": 23605, "##ept": 23606, "gottingen": 23607, "hardness": 23608, "630": 23609, "shaman": 23610, "temeraire": 23611, "620": 23612, "adequately": 23613, "pediatric": 23614, "##kit": 23615, "ck": 23616, "assertion": 23617, "radicals": 23618, "composure": 23619, "cadence": 23620, "seafood": 23621, "beaufort": 23622, "lazarus": 23623, "mani": 23624, "warily": 23625, "cunning": 23626, "kurdistan": 23627, "249": 23628, "cantata": 23629, "##kir": 23630, "ares": 23631, "##41": 23632, "##clusive": 23633, "nape": 23634, "townland": 23635, "geared": 23636, "insulted": 23637, "flutter": 23638, "boating": 23639, "violate": 23640, "draper": 23641, "dumping": 23642, "malmo": 23643, "##hh": 23644, "##romatic": 23645, "firearm": 23646, "alta": 23647, "bono": 23648, "obscured": 23649, "##clave": 23650, "exceeds": 23651, "panorama": 23652, "unbelievable": 23653, "##train": 23654, "preschool": 23655, "##essed": 23656, "disconnected": 23657, "installing": 23658, "rescuing": 23659, "secretaries": 23660, "accessibility": 23661, "##castle": 23662, "##drive": 23663, "##ifice": 23664, "##film": 23665, "bouts": 23666, "slug": 23667, "waterway": 23668, "mindanao": 23669, "##buro": 23670, "##ratic": 23671, "halves": 23672, "##ل": 23673, "calming": 23674, "liter": 23675, "maternity": 23676, "adorable": 23677, "bragg": 23678, "electrification": 23679, "mcc": 23680, "##dote": 23681, "roxy": 23682, "schizophrenia": 23683, "##body": 23684, "munoz": 23685, "kaye": 23686, "whaling": 23687, "239": 23688, "mil": 23689, "tingling": 23690, "tolerant": 23691, "##ago": 23692, "unconventional": 23693, "volcanoes": 23694, "##finder": 23695, "deportivo": 23696, "##llie": 23697, "robson": 23698, "kaufman": 23699, "neuroscience": 23700, "wai": 23701, "deportation": 23702, "masovian": 23703, "scraping": 23704, "converse": 23705, "##bh": 23706, "hacking": 23707, "bulge": 23708, "##oun": 23709, "administratively": 23710, "yao": 23711, "580": 23712, "amp": 23713, "mammoth": 23714, "booster": 23715, "claremont": 23716, "hooper": 23717, "nomenclature": 23718, "pursuits": 23719, "mclaughlin": 23720, "melinda": 23721, "##sul": 23722, "catfish": 23723, "barclay": 23724, "substrates": 23725, "taxa": 23726, "zee": 23727, "originals": 23728, "kimberly": 23729, "packets": 23730, "padma": 23731, "##ality": 23732, "borrowing": 23733, "ostensibly": 23734, "solvent": 23735, "##bri": 23736, "##genesis": 23737, "##mist": 23738, "lukas": 23739, "shreveport": 23740, "veracruz": 23741, "##ь": 23742, "##lou": 23743, "##wives": 23744, "cheney": 23745, "tt": 23746, "anatolia": 23747, "hobbs": 23748, "##zyn": 23749, "cyclic": 23750, "radiant": 23751, "alistair": 23752, "greenish": 23753, "siena": 23754, "dat": 23755, "independents": 23756, "##bation": 23757, "conform": 23758, "pieter": 23759, "hyper": 23760, "applicant": 23761, "bradshaw": 23762, "spores": 23763, "telangana": 23764, "vinci": 23765, "inexpensive": 23766, "nuclei": 23767, "322": 23768, "jang": 23769, "nme": 23770, "soho": 23771, "spd": 23772, "##ign": 23773, "cradled": 23774, "receptionist": 23775, "pow": 23776, "##43": 23777, "##rika": 23778, "fascism": 23779, "##ifer": 23780, "experimenting": 23781, "##ading": 23782, "##iec": 23783, "##region": 23784, "345": 23785, "jocelyn": 23786, "maris": 23787, "stair": 23788, "nocturnal": 23789, "toro": 23790, "constabulary": 23791, "elgin": 23792, "##kker": 23793, "msc": 23794, "##giving": 23795, "##schen": 23796, "##rase": 23797, "doherty": 23798, "doping": 23799, "sarcastically": 23800, "batter": 23801, "maneuvers": 23802, "##cano": 23803, "##apple": 23804, "##gai": 23805, "##git": 23806, "intrinsic": 23807, "##nst": 23808, "##stor": 23809, "1753": 23810, "showtime": 23811, "cafes": 23812, "gasps": 23813, "lviv": 23814, "ushered": 23815, "##thed": 23816, "fours": 23817, "restart": 23818, "astonishment": 23819, "transmitting": 23820, "flyer": 23821, "shrugs": 23822, "##sau": 23823, "intriguing": 23824, "cones": 23825, "dictated": 23826, "mushrooms": 23827, "medial": 23828, "##kovsky": 23829, "##elman": 23830, "escorting": 23831, "gaped": 23832, "##26": 23833, "godfather": 23834, "##door": 23835, "##sell": 23836, "djs": 23837, "recaptured": 23838, "timetable": 23839, "vila": 23840, "1710": 23841, "3a": 23842, "aerodrome": 23843, "mortals": 23844, "scientology": 23845, "##orne": 23846, "angelina": 23847, "mag": 23848, "convection": 23849, "unpaid": 23850, "insertion": 23851, "intermittent": 23852, "lego": 23853, "##nated": 23854, "endeavor": 23855, "kota": 23856, "pereira": 23857, "##lz": 23858, "304": 23859, "bwv": 23860, "glamorgan": 23861, "insults": 23862, "agatha": 23863, "fey": 23864, "##cend": 23865, "fleetwood": 23866, "mahogany": 23867, "protruding": 23868, "steamship": 23869, "zeta": 23870, "##arty": 23871, "mcguire": 23872, "suspense": 23873, "##sphere": 23874, "advising": 23875, "urges": 23876, "##wala": 23877, "hurriedly": 23878, "meteor": 23879, "gilded": 23880, "inline": 23881, "arroyo": 23882, "stalker": 23883, "##oge": 23884, "excitedly": 23885, "revered": 23886, "##cure": 23887, "earle": 23888, "introductory": 23889, "##break": 23890, "##ilde": 23891, "mutants": 23892, "puff": 23893, "pulses": 23894, "reinforcement": 23895, "##haling": 23896, "curses": 23897, "lizards": 23898, "stalk": 23899, "correlated": 23900, "##fixed": 23901, "fallout": 23902, "macquarie": 23903, "##unas": 23904, "bearded": 23905, "denton": 23906, "heaving": 23907, "802": 23908, "##ocation": 23909, "winery": 23910, "assign": 23911, "dortmund": 23912, "##lkirk": 23913, "everest": 23914, "invariant": 23915, "charismatic": 23916, "susie": 23917, "##elling": 23918, "bled": 23919, "lesley": 23920, "telegram": 23921, "sumner": 23922, "bk": 23923, "##ogen": 23924, "##к": 23925, "wilcox": 23926, "needy": 23927, "colbert": 23928, "duval": 23929, "##iferous": 23930, "##mbled": 23931, "allotted": 23932, "attends": 23933, "imperative": 23934, "##hita": 23935, "replacements": 23936, "hawker": 23937, "##inda": 23938, "insurgency": 23939, "##zee": 23940, "##eke": 23941, "casts": 23942, "##yla": 23943, "680": 23944, "ives": 23945, "transitioned": 23946, "##pack": 23947, "##powering": 23948, "authoritative": 23949, "baylor": 23950, "flex": 23951, "cringed": 23952, "plaintiffs": 23953, "woodrow": 23954, "##skie": 23955, "drastic": 23956, "ape": 23957, "aroma": 23958, "unfolded": 23959, "commotion": 23960, "nt": 23961, "preoccupied": 23962, "theta": 23963, "routines": 23964, "lasers": 23965, "privatization": 23966, "wand": 23967, "domino": 23968, "ek": 23969, "clenching": 23970, "nsa": 23971, "strategically": 23972, "showered": 23973, "bile": 23974, "handkerchief": 23975, "pere": 23976, "storing": 23977, "christophe": 23978, "insulting": 23979, "316": 23980, "nakamura": 23981, "romani": 23982, "asiatic": 23983, "magdalena": 23984, "palma": 23985, "cruises": 23986, "stripping": 23987, "405": 23988, "konstantin": 23989, "soaring": 23990, "##berman": 23991, "colloquially": 23992, "forerunner": 23993, "havilland": 23994, "incarcerated": 23995, "parasites": 23996, "sincerity": 23997, "##utus": 23998, "disks": 23999, "plank": 24000, "saigon": 24001, "##ining": 24002, "corbin": 24003, "homo": 24004, "ornaments": 24005, "powerhouse": 24006, "##tlement": 24007, "chong": 24008, "fastened": 24009, "feasibility": 24010, "idf": 24011, "morphological": 24012, "usable": 24013, "##nish": 24014, "##zuki": 24015, "aqueduct": 24016, "jaguars": 24017, "keepers": 24018, "##flies": 24019, "aleksandr": 24020, "faust": 24021, "assigns": 24022, "ewing": 24023, "bacterium": 24024, "hurled": 24025, "tricky": 24026, "hungarians": 24027, "integers": 24028, "wallis": 24029, "321": 24030, "yamaha": 24031, "##isha": 24032, "hushed": 24033, "oblivion": 24034, "aviator": 24035, "evangelist": 24036, "friars": 24037, "##eller": 24038, "monograph": 24039, "ode": 24040, "##nary": 24041, "airplanes": 24042, "labourers": 24043, "charms": 24044, "##nee": 24045, "1661": 24046, "hagen": 24047, "tnt": 24048, "rudder": 24049, "fiesta": 24050, "transcript": 24051, "dorothea": 24052, "ska": 24053, "inhibitor": 24054, "maccabi": 24055, "retorted": 24056, "raining": 24057, "encompassed": 24058, "clauses": 24059, "menacing": 24060, "1642": 24061, "lineman": 24062, "##gist": 24063, "vamps": 24064, "##ape": 24065, "##dick": 24066, "gloom": 24067, "##rera": 24068, "dealings": 24069, "easing": 24070, "seekers": 24071, "##nut": 24072, "##pment": 24073, "helens": 24074, "unmanned": 24075, "##anu": 24076, "##isson": 24077, "basics": 24078, "##amy": 24079, "##ckman": 24080, "adjustments": 24081, "1688": 24082, "brutality": 24083, "horne": 24084, "##zell": 24085, "sui": 24086, "##55": 24087, "##mable": 24088, "aggregator": 24089, "##thal": 24090, "rhino": 24091, "##drick": 24092, "##vira": 24093, "counters": 24094, "zoom": 24095, "##01": 24096, "##rting": 24097, "mn": 24098, "montenegrin": 24099, "packard": 24100, "##unciation": 24101, "##♭": 24102, "##kki": 24103, "reclaim": 24104, "scholastic": 24105, "thugs": 24106, "pulsed": 24107, "##icia": 24108, "syriac": 24109, "quan": 24110, "saddam": 24111, "banda": 24112, "kobe": 24113, "blaming": 24114, "buddies": 24115, "dissent": 24116, "##lusion": 24117, "##usia": 24118, "corbett": 24119, "jaya": 24120, "delle": 24121, "erratic": 24122, "lexie": 24123, "##hesis": 24124, "435": 24125, "amiga": 24126, "hermes": 24127, "##pressing": 24128, "##leen": 24129, "chapels": 24130, "gospels": 24131, "jamal": 24132, "##uating": 24133, "compute": 24134, "revolving": 24135, "warp": 24136, "##sso": 24137, "##thes": 24138, "armory": 24139, "##eras": 24140, "##gol": 24141, "antrim": 24142, "loki": 24143, "##kow": 24144, "##asian": 24145, "##good": 24146, "##zano": 24147, "braid": 24148, "handwriting": 24149, "subdistrict": 24150, "funky": 24151, "pantheon": 24152, "##iculate": 24153, "concurrency": 24154, "estimation": 24155, "improper": 24156, "juliana": 24157, "##his": 24158, "newcomers": 24159, "johnstone": 24160, "staten": 24161, "communicated": 24162, "##oco": 24163, "##alle": 24164, "sausage": 24165, "stormy": 24166, "##stered": 24167, "##tters": 24168, "superfamily": 24169, "##grade": 24170, "acidic": 24171, "collateral": 24172, "tabloid": 24173, "##oped": 24174, "##rza": 24175, "bladder": 24176, "austen": 24177, "##ellant": 24178, "mcgraw": 24179, "##hay": 24180, "hannibal": 24181, "mein": 24182, "aquino": 24183, "lucifer": 24184, "wo": 24185, "badger": 24186, "boar": 24187, "cher": 24188, "christensen": 24189, "greenberg": 24190, "interruption": 24191, "##kken": 24192, "jem": 24193, "244": 24194, "mocked": 24195, "bottoms": 24196, "cambridgeshire": 24197, "##lide": 24198, "sprawling": 24199, "##bbly": 24200, "eastwood": 24201, "ghent": 24202, "synth": 24203, "##buck": 24204, "advisers": 24205, "##bah": 24206, "nominally": 24207, "hapoel": 24208, "qu": 24209, "daggers": 24210, "estranged": 24211, "fabricated": 24212, "towels": 24213, "vinnie": 24214, "wcw": 24215, "misunderstanding": 24216, "anglia": 24217, "nothin": 24218, "unmistakable": 24219, "##dust": 24220, "##lova": 24221, "chilly": 24222, "marquette": 24223, "truss": 24224, "##edge": 24225, "##erine": 24226, "reece": 24227, "##lty": 24228, "##chemist": 24229, "##connected": 24230, "272": 24231, "308": 24232, "41st": 24233, "bash": 24234, "raion": 24235, "waterfalls": 24236, "##ump": 24237, "##main": 24238, "labyrinth": 24239, "queue": 24240, "theorist": 24241, "##istle": 24242, "bharatiya": 24243, "flexed": 24244, "soundtracks": 24245, "rooney": 24246, "leftist": 24247, "patrolling": 24248, "wharton": 24249, "plainly": 24250, "alleviate": 24251, "eastman": 24252, "schuster": 24253, "topographic": 24254, "engages": 24255, "immensely": 24256, "unbearable": 24257, "fairchild": 24258, "1620": 24259, "dona": 24260, "lurking": 24261, "parisian": 24262, "oliveira": 24263, "ia": 24264, "indictment": 24265, "hahn": 24266, "bangladeshi": 24267, "##aster": 24268, "vivo": 24269, "##uming": 24270, "##ential": 24271, "antonia": 24272, "expects": 24273, "indoors": 24274, "kildare": 24275, "harlan": 24276, "##logue": 24277, "##ogenic": 24278, "##sities": 24279, "forgiven": 24280, "##wat": 24281, "childish": 24282, "tavi": 24283, "##mide": 24284, "##orra": 24285, "plausible": 24286, "grimm": 24287, "successively": 24288, "scooted": 24289, "##bola": 24290, "##dget": 24291, "##rith": 24292, "spartans": 24293, "emery": 24294, "flatly": 24295, "azure": 24296, "epilogue": 24297, "##wark": 24298, "flourish": 24299, "##iny": 24300, "##tracted": 24301, "##overs": 24302, "##oshi": 24303, "bestseller": 24304, "distressed": 24305, "receipt": 24306, "spitting": 24307, "hermit": 24308, "topological": 24309, "##cot": 24310, "drilled": 24311, "subunit": 24312, "francs": 24313, "##layer": 24314, "eel": 24315, "##fk": 24316, "##itas": 24317, "octopus": 24318, "footprint": 24319, "petitions": 24320, "ufo": 24321, "##say": 24322, "##foil": 24323, "interfering": 24324, "leaking": 24325, "palo": 24326, "##metry": 24327, "thistle": 24328, "valiant": 24329, "##pic": 24330, "narayan": 24331, "mcpherson": 24332, "##fast": 24333, "gonzales": 24334, "##ym": 24335, "##enne": 24336, "dustin": 24337, "novgorod": 24338, "solos": 24339, "##zman": 24340, "doin": 24341, "##raph": 24342, "##patient": 24343, "##meyer": 24344, "soluble": 24345, "ashland": 24346, "cuffs": 24347, "carole": 24348, "pendleton": 24349, "whistling": 24350, "vassal": 24351, "##river": 24352, "deviation": 24353, "revisited": 24354, "constituents": 24355, "rallied": 24356, "rotate": 24357, "loomed": 24358, "##eil": 24359, "##nting": 24360, "amateurs": 24361, "augsburg": 24362, "auschwitz": 24363, "crowns": 24364, "skeletons": 24365, "##cona": 24366, "bonnet": 24367, "257": 24368, "dummy": 24369, "globalization": 24370, "simeon": 24371, "sleeper": 24372, "mandal": 24373, "differentiated": 24374, "##crow": 24375, "##mare": 24376, "milne": 24377, "bundled": 24378, "exasperated": 24379, "talmud": 24380, "owes": 24381, "segregated": 24382, "##feng": 24383, "##uary": 24384, "dentist": 24385, "piracy": 24386, "props": 24387, "##rang": 24388, "devlin": 24389, "##torium": 24390, "malicious": 24391, "paws": 24392, "##laid": 24393, "dependency": 24394, "##ergy": 24395, "##fers": 24396, "##enna": 24397, "258": 24398, "pistons": 24399, "rourke": 24400, "jed": 24401, "grammatical": 24402, "tres": 24403, "maha": 24404, "wig": 24405, "512": 24406, "ghostly": 24407, "jayne": 24408, "##achal": 24409, "##creen": 24410, "##ilis": 24411, "##lins": 24412, "##rence": 24413, "designate": 24414, "##with": 24415, "arrogance": 24416, "cambodian": 24417, "clones": 24418, "showdown": 24419, "throttle": 24420, "twain": 24421, "##ception": 24422, "lobes": 24423, "metz": 24424, "nagoya": 24425, "335": 24426, "braking": 24427, "##furt": 24428, "385": 24429, "roaming": 24430, "##minster": 24431, "amin": 24432, "crippled": 24433, "##37": 24434, "##llary": 24435, "indifferent": 24436, "hoffmann": 24437, "idols": 24438, "intimidating": 24439, "1751": 24440, "261": 24441, "influenza": 24442, "memo": 24443, "onions": 24444, "1748": 24445, "bandage": 24446, "consciously": 24447, "##landa": 24448, "##rage": 24449, "clandestine": 24450, "observes": 24451, "swiped": 24452, "tangle": 24453, "##ener": 24454, "##jected": 24455, "##trum": 24456, "##bill": 24457, "##lta": 24458, "hugs": 24459, "congresses": 24460, "josiah": 24461, "spirited": 24462, "##dek": 24463, "humanist": 24464, "managerial": 24465, "filmmaking": 24466, "inmate": 24467, "rhymes": 24468, "debuting": 24469, "grimsby": 24470, "ur": 24471, "##laze": 24472, "duplicate": 24473, "vigor": 24474, "##tf": 24475, "republished": 24476, "bolshevik": 24477, "refurbishment": 24478, "antibiotics": 24479, "martini": 24480, "methane": 24481, "newscasts": 24482, "royale": 24483, "horizons": 24484, "levant": 24485, "iain": 24486, "visas": 24487, "##ischen": 24488, "paler": 24489, "##around": 24490, "manifestation": 24491, "snuck": 24492, "alf": 24493, "chop": 24494, "futile": 24495, "pedestal": 24496, "rehab": 24497, "##kat": 24498, "bmg": 24499, "kerman": 24500, "res": 24501, "fairbanks": 24502, "jarrett": 24503, "abstraction": 24504, "saharan": 24505, "##zek": 24506, "1746": 24507, "procedural": 24508, "clearer": 24509, "kincaid": 24510, "sash": 24511, "luciano": 24512, "##ffey": 24513, "crunch": 24514, "helmut": 24515, "##vara": 24516, "revolutionaries": 24517, "##tute": 24518, "creamy": 24519, "leach": 24520, "##mmon": 24521, "1747": 24522, "permitting": 24523, "nes": 24524, "plight": 24525, "wendell": 24526, "##lese": 24527, "contra": 24528, "ts": 24529, "clancy": 24530, "ipa": 24531, "mach": 24532, "staples": 24533, "autopsy": 24534, "disturbances": 24535, "nueva": 24536, "karin": 24537, "pontiac": 24538, "##uding": 24539, "proxy": 24540, "venerable": 24541, "haunt": 24542, "leto": 24543, "bergman": 24544, "expands": 24545, "##helm": 24546, "wal": 24547, "##pipe": 24548, "canning": 24549, "celine": 24550, "cords": 24551, "obesity": 24552, "##enary": 24553, "intrusion": 24554, "planner": 24555, "##phate": 24556, "reasoned": 24557, "sequencing": 24558, "307": 24559, "harrow": 24560, "##chon": 24561, "##dora": 24562, "marred": 24563, "mcintyre": 24564, "repay": 24565, "tarzan": 24566, "darting": 24567, "248": 24568, "harrisburg": 24569, "margarita": 24570, "repulsed": 24571, "##hur": 24572, "##lding": 24573, "belinda": 24574, "hamburger": 24575, "novo": 24576, "compliant": 24577, "runways": 24578, "bingham": 24579, "registrar": 24580, "skyscraper": 24581, "ic": 24582, "cuthbert": 24583, "improvisation": 24584, "livelihood": 24585, "##corp": 24586, "##elial": 24587, "admiring": 24588, "##dened": 24589, "sporadic": 24590, "believer": 24591, "casablanca": 24592, "popcorn": 24593, "##29": 24594, "asha": 24595, "shovel": 24596, "##bek": 24597, "##dice": 24598, "coiled": 24599, "tangible": 24600, "##dez": 24601, "casper": 24602, "elsie": 24603, "resin": 24604, "tenderness": 24605, "rectory": 24606, "##ivision": 24607, "avail": 24608, "sonar": 24609, "##mori": 24610, "boutique": 24611, "##dier": 24612, "guerre": 24613, "bathed": 24614, "upbringing": 24615, "vaulted": 24616, "sandals": 24617, "blessings": 24618, "##naut": 24619, "##utnant": 24620, "1680": 24621, "306": 24622, "foxes": 24623, "pia": 24624, "corrosion": 24625, "hesitantly": 24626, "confederates": 24627, "crystalline": 24628, "footprints": 24629, "shapiro": 24630, "tirana": 24631, "valentin": 24632, "drones": 24633, "45th": 24634, "microscope": 24635, "shipments": 24636, "texted": 24637, "inquisition": 24638, "wry": 24639, "guernsey": 24640, "unauthorized": 24641, "resigning": 24642, "760": 24643, "ripple": 24644, "schubert": 24645, "stu": 24646, "reassure": 24647, "felony": 24648, "##ardo": 24649, "brittle": 24650, "koreans": 24651, "##havan": 24652, "##ives": 24653, "dun": 24654, "implicit": 24655, "tyres": 24656, "##aldi": 24657, "##lth": 24658, "magnolia": 24659, "##ehan": 24660, "##puri": 24661, "##poulos": 24662, "aggressively": 24663, "fei": 24664, "gr": 24665, "familiarity": 24666, "##poo": 24667, "indicative": 24668, "##trust": 24669, "fundamentally": 24670, "jimmie": 24671, "overrun": 24672, "395": 24673, "anchors": 24674, "moans": 24675, "##opus": 24676, "britannia": 24677, "armagh": 24678, "##ggle": 24679, "purposely": 24680, "seizing": 24681, "##vao": 24682, "bewildered": 24683, "mundane": 24684, "avoidance": 24685, "cosmopolitan": 24686, "geometridae": 24687, "quartermaster": 24688, "caf": 24689, "415": 24690, "chatter": 24691, "engulfed": 24692, "gleam": 24693, "purge": 24694, "##icate": 24695, "juliette": 24696, "jurisprudence": 24697, "guerra": 24698, "revisions": 24699, "##bn": 24700, "casimir": 24701, "brew": 24702, "##jm": 24703, "1749": 24704, "clapton": 24705, "cloudy": 24706, "conde": 24707, "hermitage": 24708, "278": 24709, "simulations": 24710, "torches": 24711, "vincenzo": 24712, "matteo": 24713, "##rill": 24714, "hidalgo": 24715, "booming": 24716, "westbound": 24717, "accomplishment": 24718, "tentacles": 24719, "unaffected": 24720, "##sius": 24721, "annabelle": 24722, "flopped": 24723, "sloping": 24724, "##litz": 24725, "dreamer": 24726, "interceptor": 24727, "vu": 24728, "##loh": 24729, "consecration": 24730, "copying": 24731, "messaging": 24732, "breaker": 24733, "climates": 24734, "hospitalized": 24735, "1752": 24736, "torino": 24737, "afternoons": 24738, "winfield": 24739, "witnessing": 24740, "##teacher": 24741, "breakers": 24742, "choirs": 24743, "sawmill": 24744, "coldly": 24745, "##ege": 24746, "sipping": 24747, "haste": 24748, "uninhabited": 24749, "conical": 24750, "bibliography": 24751, "pamphlets": 24752, "severn": 24753, "edict": 24754, "##oca": 24755, "deux": 24756, "illnesses": 24757, "grips": 24758, "##pl": 24759, "rehearsals": 24760, "sis": 24761, "thinkers": 24762, "tame": 24763, "##keepers": 24764, "1690": 24765, "acacia": 24766, "reformer": 24767, "##osed": 24768, "##rys": 24769, "shuffling": 24770, "##iring": 24771, "##shima": 24772, "eastbound": 24773, "ionic": 24774, "rhea": 24775, "flees": 24776, "littered": 24777, "##oum": 24778, "rocker": 24779, "vomiting": 24780, "groaning": 24781, "champ": 24782, "overwhelmingly": 24783, "civilizations": 24784, "paces": 24785, "sloop": 24786, "adoptive": 24787, "##tish": 24788, "skaters": 24789, "##vres": 24790, "aiding": 24791, "mango": 24792, "##joy": 24793, "nikola": 24794, "shriek": 24795, "##ignon": 24796, "pharmaceuticals": 24797, "##mg": 24798, "tuna": 24799, "calvert": 24800, "gustavo": 24801, "stocked": 24802, "yearbook": 24803, "##urai": 24804, "##mana": 24805, "computed": 24806, "subsp": 24807, "riff": 24808, "hanoi": 24809, "kelvin": 24810, "hamid": 24811, "moors": 24812, "pastures": 24813, "summons": 24814, "jihad": 24815, "nectar": 24816, "##ctors": 24817, "bayou": 24818, "untitled": 24819, "pleasing": 24820, "vastly": 24821, "republics": 24822, "intellect": 24823, "##η": 24824, "##ulio": 24825, "##tou": 24826, "crumbling": 24827, "stylistic": 24828, "sb": 24829, "##ی": 24830, "consolation": 24831, "frequented": 24832, "h₂o": 24833, "walden": 24834, "widows": 24835, "##iens": 24836, "404": 24837, "##ignment": 24838, "chunks": 24839, "improves": 24840, "288": 24841, "grit": 24842, "recited": 24843, "##dev": 24844, "snarl": 24845, "sociological": 24846, "##arte": 24847, "##gul": 24848, "inquired": 24849, "##held": 24850, "bruise": 24851, "clube": 24852, "consultancy": 24853, "homogeneous": 24854, "hornets": 24855, "multiplication": 24856, "pasta": 24857, "prick": 24858, "savior": 24859, "##grin": 24860, "##kou": 24861, "##phile": 24862, "yoon": 24863, "##gara": 24864, "grimes": 24865, "vanishing": 24866, "cheering": 24867, "reacting": 24868, "bn": 24869, "distillery": 24870, "##quisite": 24871, "##vity": 24872, "coe": 24873, "dockyard": 24874, "massif": 24875, "##jord": 24876, "escorts": 24877, "voss": 24878, "##valent": 24879, "byte": 24880, "chopped": 24881, "hawke": 24882, "illusions": 24883, "workings": 24884, "floats": 24885, "##koto": 24886, "##vac": 24887, "kv": 24888, "annapolis": 24889, "madden": 24890, "##onus": 24891, "alvaro": 24892, "noctuidae": 24893, "##cum": 24894, "##scopic": 24895, "avenge": 24896, "steamboat": 24897, "forte": 24898, "illustrates": 24899, "erika": 24900, "##trip": 24901, "570": 24902, "dew": 24903, "nationalities": 24904, "bran": 24905, "manifested": 24906, "thirsty": 24907, "diversified": 24908, "muscled": 24909, "reborn": 24910, "##standing": 24911, "arson": 24912, "##lessness": 24913, "##dran": 24914, "##logram": 24915, "##boys": 24916, "##kushima": 24917, "##vious": 24918, "willoughby": 24919, "##phobia": 24920, "286": 24921, "alsace": 24922, "dashboard": 24923, "yuki": 24924, "##chai": 24925, "granville": 24926, "myspace": 24927, "publicized": 24928, "tricked": 24929, "##gang": 24930, "adjective": 24931, "##ater": 24932, "relic": 24933, "reorganisation": 24934, "enthusiastically": 24935, "indications": 24936, "saxe": 24937, "##lassified": 24938, "consolidate": 24939, "iec": 24940, "padua": 24941, "helplessly": 24942, "ramps": 24943, "renaming": 24944, "regulars": 24945, "pedestrians": 24946, "accents": 24947, "convicts": 24948, "inaccurate": 24949, "lowers": 24950, "mana": 24951, "##pati": 24952, "barrie": 24953, "bjp": 24954, "outta": 24955, "someplace": 24956, "berwick": 24957, "flanking": 24958, "invoked": 24959, "marrow": 24960, "sparsely": 24961, "excerpts": 24962, "clothed": 24963, "rei": 24964, "##ginal": 24965, "wept": 24966, "##straße": 24967, "##vish": 24968, "alexa": 24969, "excel": 24970, "##ptive": 24971, "membranes": 24972, "aquitaine": 24973, "creeks": 24974, "cutler": 24975, "sheppard": 24976, "implementations": 24977, "ns": 24978, "##dur": 24979, "fragrance": 24980, "budge": 24981, "concordia": 24982, "magnesium": 24983, "marcelo": 24984, "##antes": 24985, "gladly": 24986, "vibrating": 24987, "##rral": 24988, "##ggles": 24989, "montrose": 24990, "##omba": 24991, "lew": 24992, "seamus": 24993, "1630": 24994, "cocky": 24995, "##ament": 24996, "##uen": 24997, "bjorn": 24998, "##rrick": 24999, "fielder": 25000, "fluttering": 25001, "##lase": 25002, "methyl": 25003, "kimberley": 25004, "mcdowell": 25005, "reductions": 25006, "barbed": 25007, "##jic": 25008, "##tonic": 25009, "aeronautical": 25010, "condensed": 25011, "distracting": 25012, "##promising": 25013, "huffed": 25014, "##cala": 25015, "##sle": 25016, "claudius": 25017, "invincible": 25018, "missy": 25019, "pious": 25020, "balthazar": 25021, "ci": 25022, "##lang": 25023, "butte": 25024, "combo": 25025, "orson": 25026, "##dication": 25027, "myriad": 25028, "1707": 25029, "silenced": 25030, "##fed": 25031, "##rh": 25032, "coco": 25033, "netball": 25034, "yourselves": 25035, "##oza": 25036, "clarify": 25037, "heller": 25038, "peg": 25039, "durban": 25040, "etudes": 25041, "offender": 25042, "roast": 25043, "blackmail": 25044, "curvature": 25045, "##woods": 25046, "vile": 25047, "309": 25048, "illicit": 25049, "suriname": 25050, "##linson": 25051, "overture": 25052, "1685": 25053, "bubbling": 25054, "gymnast": 25055, "tucking": 25056, "##mming": 25057, "##ouin": 25058, "maldives": 25059, "##bala": 25060, "gurney": 25061, "##dda": 25062, "##eased": 25063, "##oides": 25064, "backside": 25065, "pinto": 25066, "jars": 25067, "racehorse": 25068, "tending": 25069, "##rdial": 25070, "baronetcy": 25071, "wiener": 25072, "duly": 25073, "##rke": 25074, "barbarian": 25075, "cupping": 25076, "flawed": 25077, "##thesis": 25078, "bertha": 25079, "pleistocene": 25080, "puddle": 25081, "swearing": 25082, "##nob": 25083, "##tically": 25084, "fleeting": 25085, "prostate": 25086, "amulet": 25087, "educating": 25088, "##mined": 25089, "##iti": 25090, "##tler": 25091, "75th": 25092, "jens": 25093, "respondents": 25094, "analytics": 25095, "cavaliers": 25096, "papacy": 25097, "raju": 25098, "##iente": 25099, "##ulum": 25100, "##tip": 25101, "funnel": 25102, "271": 25103, "disneyland": 25104, "##lley": 25105, "sociologist": 25106, "##iam": 25107, "2500": 25108, "faulkner": 25109, "louvre": 25110, "menon": 25111, "##dson": 25112, "276": 25113, "##ower": 25114, "afterlife": 25115, "mannheim": 25116, "peptide": 25117, "referees": 25118, "comedians": 25119, "meaningless": 25120, "##anger": 25121, "##laise": 25122, "fabrics": 25123, "hurley": 25124, "renal": 25125, "sleeps": 25126, "##bour": 25127, "##icle": 25128, "breakout": 25129, "kristin": 25130, "roadside": 25131, "animator": 25132, "clover": 25133, "disdain": 25134, "unsafe": 25135, "redesign": 25136, "##urity": 25137, "firth": 25138, "barnsley": 25139, "portage": 25140, "reset": 25141, "narrows": 25142, "268": 25143, "commandos": 25144, "expansive": 25145, "speechless": 25146, "tubular": 25147, "##lux": 25148, "essendon": 25149, "eyelashes": 25150, "smashwords": 25151, "##yad": 25152, "##bang": 25153, "##claim": 25154, "craved": 25155, "sprinted": 25156, "chet": 25157, "somme": 25158, "astor": 25159, "wrocław": 25160, "orton": 25161, "266": 25162, "bane": 25163, "##erving": 25164, "##uing": 25165, "mischief": 25166, "##amps": 25167, "##sund": 25168, "scaling": 25169, "terre": 25170, "##xious": 25171, "impairment": 25172, "offenses": 25173, "undermine": 25174, "moi": 25175, "soy": 25176, "contiguous": 25177, "arcadia": 25178, "inuit": 25179, "seam": 25180, "##tops": 25181, "macbeth": 25182, "rebelled": 25183, "##icative": 25184, "##iot": 25185, "590": 25186, "elaborated": 25187, "frs": 25188, "uniformed": 25189, "##dberg": 25190, "259": 25191, "powerless": 25192, "priscilla": 25193, "stimulated": 25194, "980": 25195, "qc": 25196, "arboretum": 25197, "frustrating": 25198, "trieste": 25199, "bullock": 25200, "##nified": 25201, "enriched": 25202, "glistening": 25203, "intern": 25204, "##adia": 25205, "locus": 25206, "nouvelle": 25207, "ollie": 25208, "ike": 25209, "lash": 25210, "starboard": 25211, "ee": 25212, "tapestry": 25213, "headlined": 25214, "hove": 25215, "rigged": 25216, "##vite": 25217, "pollock": 25218, "##yme": 25219, "thrive": 25220, "clustered": 25221, "cas": 25222, "roi": 25223, "gleamed": 25224, "olympiad": 25225, "##lino": 25226, "pressured": 25227, "regimes": 25228, "##hosis": 25229, "##lick": 25230, "ripley": 25231, "##ophone": 25232, "kickoff": 25233, "gallon": 25234, "rockwell": 25235, "##arable": 25236, "crusader": 25237, "glue": 25238, "revolutions": 25239, "scrambling": 25240, "1714": 25241, "grover": 25242, "##jure": 25243, "englishman": 25244, "aztec": 25245, "263": 25246, "contemplating": 25247, "coven": 25248, "ipad": 25249, "preach": 25250, "triumphant": 25251, "tufts": 25252, "##esian": 25253, "rotational": 25254, "##phus": 25255, "328": 25256, "falkland": 25257, "##brates": 25258, "strewn": 25259, "clarissa": 25260, "rejoin": 25261, "environmentally": 25262, "glint": 25263, "banded": 25264, "drenched": 25265, "moat": 25266, "albanians": 25267, "johor": 25268, "rr": 25269, "maestro": 25270, "malley": 25271, "nouveau": 25272, "shaded": 25273, "taxonomy": 25274, "v6": 25275, "adhere": 25276, "bunk": 25277, "airfields": 25278, "##ritan": 25279, "1741": 25280, "encompass": 25281, "remington": 25282, "tran": 25283, "##erative": 25284, "amelie": 25285, "mazda": 25286, "friar": 25287, "morals": 25288, "passions": 25289, "##zai": 25290, "breadth": 25291, "vis": 25292, "##hae": 25293, "argus": 25294, "burnham": 25295, "caressing": 25296, "insider": 25297, "rudd": 25298, "##imov": 25299, "##mini": 25300, "##rso": 25301, "italianate": 25302, "murderous": 25303, "textual": 25304, "wainwright": 25305, "armada": 25306, "bam": 25307, "weave": 25308, "timer": 25309, "##taken": 25310, "##nh": 25311, "fra": 25312, "##crest": 25313, "ardent": 25314, "salazar": 25315, "taps": 25316, "tunis": 25317, "##ntino": 25318, "allegro": 25319, "gland": 25320, "philanthropic": 25321, "##chester": 25322, "implication": 25323, "##optera": 25324, "esq": 25325, "judas": 25326, "noticeably": 25327, "wynn": 25328, "##dara": 25329, "inched": 25330, "indexed": 25331, "crises": 25332, "villiers": 25333, "bandit": 25334, "royalties": 25335, "patterned": 25336, "cupboard": 25337, "interspersed": 25338, "accessory": 25339, "isla": 25340, "kendrick": 25341, "entourage": 25342, "stitches": 25343, "##esthesia": 25344, "headwaters": 25345, "##ior": 25346, "interlude": 25347, "distraught": 25348, "draught": 25349, "1727": 25350, "##basket": 25351, "biased": 25352, "sy": 25353, "transient": 25354, "triad": 25355, "subgenus": 25356, "adapting": 25357, "kidd": 25358, "shortstop": 25359, "##umatic": 25360, "dimly": 25361, "spiked": 25362, "mcleod": 25363, "reprint": 25364, "nellie": 25365, "pretoria": 25366, "windmill": 25367, "##cek": 25368, "singled": 25369, "##mps": 25370, "273": 25371, "reunite": 25372, "##orous": 25373, "747": 25374, "bankers": 25375, "outlying": 25376, "##omp": 25377, "##ports": 25378, "##tream": 25379, "apologies": 25380, "cosmetics": 25381, "patsy": 25382, "##deh": 25383, "##ocks": 25384, "##yson": 25385, "bender": 25386, "nantes": 25387, "serene": 25388, "##nad": 25389, "lucha": 25390, "mmm": 25391, "323": 25392, "##cius": 25393, "##gli": 25394, "cmll": 25395, "coinage": 25396, "nestor": 25397, "juarez": 25398, "##rook": 25399, "smeared": 25400, "sprayed": 25401, "twitching": 25402, "sterile": 25403, "irina": 25404, "embodied": 25405, "juveniles": 25406, "enveloped": 25407, "miscellaneous": 25408, "cancers": 25409, "dq": 25410, "gulped": 25411, "luisa": 25412, "crested": 25413, "swat": 25414, "donegal": 25415, "ref": 25416, "##anov": 25417, "##acker": 25418, "hearst": 25419, "mercantile": 25420, "##lika": 25421, "doorbell": 25422, "ua": 25423, "vicki": 25424, "##alla": 25425, "##som": 25426, "bilbao": 25427, "psychologists": 25428, "stryker": 25429, "sw": 25430, "horsemen": 25431, "turkmenistan": 25432, "wits": 25433, "##national": 25434, "anson": 25435, "mathew": 25436, "screenings": 25437, "##umb": 25438, "rihanna": 25439, "##agne": 25440, "##nessy": 25441, "aisles": 25442, "##iani": 25443, "##osphere": 25444, "hines": 25445, "kenton": 25446, "saskatoon": 25447, "tasha": 25448, "truncated": 25449, "##champ": 25450, "##itan": 25451, "mildred": 25452, "advises": 25453, "fredrik": 25454, "interpreting": 25455, "inhibitors": 25456, "##athi": 25457, "spectroscopy": 25458, "##hab": 25459, "##kong": 25460, "karim": 25461, "panda": 25462, "##oia": 25463, "##nail": 25464, "##vc": 25465, "conqueror": 25466, "kgb": 25467, "leukemia": 25468, "##dity": 25469, "arrivals": 25470, "cheered": 25471, "pisa": 25472, "phosphorus": 25473, "shielded": 25474, "##riated": 25475, "mammal": 25476, "unitarian": 25477, "urgently": 25478, "chopin": 25479, "sanitary": 25480, "##mission": 25481, "spicy": 25482, "drugged": 25483, "hinges": 25484, "##tort": 25485, "tipping": 25486, "trier": 25487, "impoverished": 25488, "westchester": 25489, "##caster": 25490, "267": 25491, "epoch": 25492, "nonstop": 25493, "##gman": 25494, "##khov": 25495, "aromatic": 25496, "centrally": 25497, "cerro": 25498, "##tively": 25499, "##vio": 25500, "billions": 25501, "modulation": 25502, "sedimentary": 25503, "283": 25504, "facilitating": 25505, "outrageous": 25506, "goldstein": 25507, "##eak": 25508, "##kt": 25509, "ld": 25510, "maitland": 25511, "penultimate": 25512, "pollard": 25513, "##dance": 25514, "fleets": 25515, "spaceship": 25516, "vertebrae": 25517, "##nig": 25518, "alcoholism": 25519, "als": 25520, "recital": 25521, "##bham": 25522, "##ference": 25523, "##omics": 25524, "m2": 25525, "##bm": 25526, "trois": 25527, "##tropical": 25528, "##в": 25529, "commemorates": 25530, "##meric": 25531, "marge": 25532, "##raction": 25533, "1643": 25534, "670": 25535, "cosmetic": 25536, "ravaged": 25537, "##ige": 25538, "catastrophe": 25539, "eng": 25540, "##shida": 25541, "albrecht": 25542, "arterial": 25543, "bellamy": 25544, "decor": 25545, "harmon": 25546, "##rde": 25547, "bulbs": 25548, "synchronized": 25549, "vito": 25550, "easiest": 25551, "shetland": 25552, "shielding": 25553, "wnba": 25554, "##glers": 25555, "##ssar": 25556, "##riam": 25557, "brianna": 25558, "cumbria": 25559, "##aceous": 25560, "##rard": 25561, "cores": 25562, "thayer": 25563, "##nsk": 25564, "brood": 25565, "hilltop": 25566, "luminous": 25567, "carts": 25568, "keynote": 25569, "larkin": 25570, "logos": 25571, "##cta": 25572, "##ا": 25573, "##mund": 25574, "##quay": 25575, "lilith": 25576, "tinted": 25577, "277": 25578, "wrestle": 25579, "mobilization": 25580, "##uses": 25581, "sequential": 25582, "siam": 25583, "bloomfield": 25584, "takahashi": 25585, "274": 25586, "##ieving": 25587, "presenters": 25588, "ringo": 25589, "blazed": 25590, "witty": 25591, "##oven": 25592, "##ignant": 25593, "devastation": 25594, "haydn": 25595, "harmed": 25596, "newt": 25597, "therese": 25598, "##peed": 25599, "gershwin": 25600, "molina": 25601, "rabbis": 25602, "sudanese": 25603, "001": 25604, "innate": 25605, "restarted": 25606, "##sack": 25607, "##fus": 25608, "slices": 25609, "wb": 25610, "##shah": 25611, "enroll": 25612, "hypothetical": 25613, "hysterical": 25614, "1743": 25615, "fabio": 25616, "indefinite": 25617, "warped": 25618, "##hg": 25619, "exchanging": 25620, "525": 25621, "unsuitable": 25622, "##sboro": 25623, "gallo": 25624, "1603": 25625, "bret": 25626, "cobalt": 25627, "homemade": 25628, "##hunter": 25629, "mx": 25630, "operatives": 25631, "##dhar": 25632, "terraces": 25633, "durable": 25634, "latch": 25635, "pens": 25636, "whorls": 25637, "##ctuated": 25638, "##eaux": 25639, "billing": 25640, "ligament": 25641, "succumbed": 25642, "##gly": 25643, "regulators": 25644, "spawn": 25645, "##brick": 25646, "##stead": 25647, "filmfare": 25648, "rochelle": 25649, "##nzo": 25650, "1725": 25651, "circumstance": 25652, "saber": 25653, "supplements": 25654, "##nsky": 25655, "##tson": 25656, "crowe": 25657, "wellesley": 25658, "carrot": 25659, "##9th": 25660, "##movable": 25661, "primate": 25662, "drury": 25663, "sincerely": 25664, "topical": 25665, "##mad": 25666, "##rao": 25667, "callahan": 25668, "kyiv": 25669, "smarter": 25670, "tits": 25671, "undo": 25672, "##yeh": 25673, "announcements": 25674, "anthologies": 25675, "barrio": 25676, "nebula": 25677, "##islaus": 25678, "##shaft": 25679, "##tyn": 25680, "bodyguards": 25681, "2021": 25682, "assassinate": 25683, "barns": 25684, "emmett": 25685, "scully": 25686, "##mah": 25687, "##yd": 25688, "##eland": 25689, "##tino": 25690, "##itarian": 25691, "demoted": 25692, "gorman": 25693, "lashed": 25694, "prized": 25695, "adventist": 25696, "writ": 25697, "##gui": 25698, "alla": 25699, "invertebrates": 25700, "##ausen": 25701, "1641": 25702, "amman": 25703, "1742": 25704, "align": 25705, "healy": 25706, "redistribution": 25707, "##gf": 25708, "##rize": 25709, "insulation": 25710, "##drop": 25711, "adherents": 25712, "hezbollah": 25713, "vitro": 25714, "ferns": 25715, "yanking": 25716, "269": 25717, "php": 25718, "registering": 25719, "uppsala": 25720, "cheerleading": 25721, "confines": 25722, "mischievous": 25723, "tully": 25724, "##ross": 25725, "49th": 25726, "docked": 25727, "roam": 25728, "stipulated": 25729, "pumpkin": 25730, "##bry": 25731, "prompt": 25732, "##ezer": 25733, "blindly": 25734, "shuddering": 25735, "craftsmen": 25736, "frail": 25737, "scented": 25738, "katharine": 25739, "scramble": 25740, "shaggy": 25741, "sponge": 25742, "helix": 25743, "zaragoza": 25744, "279": 25745, "##52": 25746, "43rd": 25747, "backlash": 25748, "fontaine": 25749, "seizures": 25750, "posse": 25751, "cowan": 25752, "nonfiction": 25753, "telenovela": 25754, "wwii": 25755, "hammered": 25756, "undone": 25757, "##gpur": 25758, "encircled": 25759, "irs": 25760, "##ivation": 25761, "artefacts": 25762, "oneself": 25763, "searing": 25764, "smallpox": 25765, "##belle": 25766, "##osaurus": 25767, "shandong": 25768, "breached": 25769, "upland": 25770, "blushing": 25771, "rankin": 25772, "infinitely": 25773, "psyche": 25774, "tolerated": 25775, "docking": 25776, "evicted": 25777, "##col": 25778, "unmarked": 25779, "##lving": 25780, "gnome": 25781, "lettering": 25782, "litres": 25783, "musique": 25784, "##oint": 25785, "benevolent": 25786, "##jal": 25787, "blackened": 25788, "##anna": 25789, "mccall": 25790, "racers": 25791, "tingle": 25792, "##ocene": 25793, "##orestation": 25794, "introductions": 25795, "radically": 25796, "292": 25797, "##hiff": 25798, "##باد": 25799, "1610": 25800, "1739": 25801, "munchen": 25802, "plead": 25803, "##nka": 25804, "condo": 25805, "scissors": 25806, "##sight": 25807, "##tens": 25808, "apprehension": 25809, "##cey": 25810, "##yin": 25811, "hallmark": 25812, "watering": 25813, "formulas": 25814, "sequels": 25815, "##llas": 25816, "aggravated": 25817, "bae": 25818, "commencing": 25819, "##building": 25820, "enfield": 25821, "prohibits": 25822, "marne": 25823, "vedic": 25824, "civilized": 25825, "euclidean": 25826, "jagger": 25827, "beforehand": 25828, "blasts": 25829, "dumont": 25830, "##arney": 25831, "##nem": 25832, "740": 25833, "conversions": 25834, "hierarchical": 25835, "rios": 25836, "simulator": 25837, "##dya": 25838, "##lellan": 25839, "hedges": 25840, "oleg": 25841, "thrusts": 25842, "shadowed": 25843, "darby": 25844, "maximize": 25845, "1744": 25846, "gregorian": 25847, "##nded": 25848, "##routed": 25849, "sham": 25850, "unspecified": 25851, "##hog": 25852, "emory": 25853, "factual": 25854, "##smo": 25855, "##tp": 25856, "fooled": 25857, "##rger": 25858, "ortega": 25859, "wellness": 25860, "marlon": 25861, "##oton": 25862, "##urance": 25863, "casket": 25864, "keating": 25865, "ley": 25866, "enclave": 25867, "##ayan": 25868, "char": 25869, "influencing": 25870, "jia": 25871, "##chenko": 25872, "412": 25873, "ammonia": 25874, "erebidae": 25875, "incompatible": 25876, "violins": 25877, "cornered": 25878, "##arat": 25879, "grooves": 25880, "astronauts": 25881, "columbian": 25882, "rampant": 25883, "fabrication": 25884, "kyushu": 25885, "mahmud": 25886, "vanish": 25887, "##dern": 25888, "mesopotamia": 25889, "##lete": 25890, "ict": 25891, "##rgen": 25892, "caspian": 25893, "kenji": 25894, "pitted": 25895, "##vered": 25896, "999": 25897, "grimace": 25898, "roanoke": 25899, "tchaikovsky": 25900, "twinned": 25901, "##analysis": 25902, "##awan": 25903, "xinjiang": 25904, "arias": 25905, "clemson": 25906, "kazakh": 25907, "sizable": 25908, "1662": 25909, "##khand": 25910, "##vard": 25911, "plunge": 25912, "tatum": 25913, "vittorio": 25914, "##nden": 25915, "cholera": 25916, "##dana": 25917, "##oper": 25918, "bracing": 25919, "indifference": 25920, "projectile": 25921, "superliga": 25922, "##chee": 25923, "realises": 25924, "upgrading": 25925, "299": 25926, "porte": 25927, "retribution": 25928, "##vies": 25929, "nk": 25930, "stil": 25931, "##resses": 25932, "ama": 25933, "bureaucracy": 25934, "blackberry": 25935, "bosch": 25936, "testosterone": 25937, "collapses": 25938, "greer": 25939, "##pathic": 25940, "ioc": 25941, "fifties": 25942, "malls": 25943, "##erved": 25944, "bao": 25945, "baskets": 25946, "adolescents": 25947, "siegfried": 25948, "##osity": 25949, "##tosis": 25950, "mantra": 25951, "detecting": 25952, "existent": 25953, "fledgling": 25954, "##cchi": 25955, "dissatisfied": 25956, "gan": 25957, "telecommunication": 25958, "mingled": 25959, "sobbed": 25960, "6000": 25961, "controversies": 25962, "outdated": 25963, "taxis": 25964, "##raus": 25965, "fright": 25966, "slams": 25967, "##lham": 25968, "##fect": 25969, "##tten": 25970, "detectors": 25971, "fetal": 25972, "tanned": 25973, "##uw": 25974, "fray": 25975, "goth": 25976, "olympian": 25977, "skipping": 25978, "mandates": 25979, "scratches": 25980, "sheng": 25981, "unspoken": 25982, "hyundai": 25983, "tracey": 25984, "hotspur": 25985, "restrictive": 25986, "##buch": 25987, "americana": 25988, "mundo": 25989, "##bari": 25990, "burroughs": 25991, "diva": 25992, "vulcan": 25993, "##6th": 25994, "distinctions": 25995, "thumping": 25996, "##ngen": 25997, "mikey": 25998, "sheds": 25999, "fide": 26000, "rescues": 26001, "springsteen": 26002, "vested": 26003, "valuation": 26004, "##ece": 26005, "##ely": 26006, "pinnacle": 26007, "rake": 26008, "sylvie": 26009, "##edo": 26010, "almond": 26011, "quivering": 26012, "##irus": 26013, "alteration": 26014, "faltered": 26015, "##wad": 26016, "51st": 26017, "hydra": 26018, "ticked": 26019, "##kato": 26020, "recommends": 26021, "##dicated": 26022, "antigua": 26023, "arjun": 26024, "stagecoach": 26025, "wilfred": 26026, "trickle": 26027, "pronouns": 26028, "##pon": 26029, "aryan": 26030, "nighttime": 26031, "##anian": 26032, "gall": 26033, "pea": 26034, "stitch": 26035, "##hei": 26036, "leung": 26037, "milos": 26038, "##dini": 26039, "eritrea": 26040, "nexus": 26041, "starved": 26042, "snowfall": 26043, "kant": 26044, "parasitic": 26045, "cot": 26046, "discus": 26047, "hana": 26048, "strikers": 26049, "appleton": 26050, "kitchens": 26051, "##erina": 26052, "##partisan": 26053, "##itha": 26054, "##vius": 26055, "disclose": 26056, "metis": 26057, "##channel": 26058, "1701": 26059, "tesla": 26060, "##vera": 26061, "fitch": 26062, "1735": 26063, "blooded": 26064, "##tila": 26065, "decimal": 26066, "##tang": 26067, "##bai": 26068, "cyclones": 26069, "eun": 26070, "bottled": 26071, "peas": 26072, "pensacola": 26073, "basha": 26074, "bolivian": 26075, "crabs": 26076, "boil": 26077, "lanterns": 26078, "partridge": 26079, "roofed": 26080, "1645": 26081, "necks": 26082, "##phila": 26083, "opined": 26084, "patting": 26085, "##kla": 26086, "##lland": 26087, "chuckles": 26088, "volta": 26089, "whereupon": 26090, "##nche": 26091, "devout": 26092, "euroleague": 26093, "suicidal": 26094, "##dee": 26095, "inherently": 26096, "involuntary": 26097, "knitting": 26098, "nasser": 26099, "##hide": 26100, "puppets": 26101, "colourful": 26102, "courageous": 26103, "southend": 26104, "stills": 26105, "miraculous": 26106, "hodgson": 26107, "richer": 26108, "rochdale": 26109, "ethernet": 26110, "greta": 26111, "uniting": 26112, "prism": 26113, "umm": 26114, "##haya": 26115, "##itical": 26116, "##utation": 26117, "deterioration": 26118, "pointe": 26119, "prowess": 26120, "##ropriation": 26121, "lids": 26122, "scranton": 26123, "billings": 26124, "subcontinent": 26125, "##koff": 26126, "##scope": 26127, "brute": 26128, "kellogg": 26129, "psalms": 26130, "degraded": 26131, "##vez": 26132, "stanisław": 26133, "##ructured": 26134, "ferreira": 26135, "pun": 26136, "astonishing": 26137, "gunnar": 26138, "##yat": 26139, "arya": 26140, "prc": 26141, "gottfried": 26142, "##tight": 26143, "excursion": 26144, "##ographer": 26145, "dina": 26146, "##quil": 26147, "##nare": 26148, "huffington": 26149, "illustrious": 26150, "wilbur": 26151, "gundam": 26152, "verandah": 26153, "##zard": 26154, "naacp": 26155, "##odle": 26156, "constructive": 26157, "fjord": 26158, "kade": 26159, "##naud": 26160, "generosity": 26161, "thrilling": 26162, "baseline": 26163, "cayman": 26164, "frankish": 26165, "plastics": 26166, "accommodations": 26167, "zoological": 26168, "##fting": 26169, "cedric": 26170, "qb": 26171, "motorized": 26172, "##dome": 26173, "##otted": 26174, "squealed": 26175, "tackled": 26176, "canucks": 26177, "budgets": 26178, "situ": 26179, "asthma": 26180, "dail": 26181, "gabled": 26182, "grasslands": 26183, "whimpered": 26184, "writhing": 26185, "judgments": 26186, "##65": 26187, "minnie": 26188, "pv": 26189, "##carbon": 26190, "bananas": 26191, "grille": 26192, "domes": 26193, "monique": 26194, "odin": 26195, "maguire": 26196, "markham": 26197, "tierney": 26198, "##estra": 26199, "##chua": 26200, "libel": 26201, "poke": 26202, "speedy": 26203, "atrium": 26204, "laval": 26205, "notwithstanding": 26206, "##edly": 26207, "fai": 26208, "kala": 26209, "##sur": 26210, "robb": 26211, "##sma": 26212, "listings": 26213, "luz": 26214, "supplementary": 26215, "tianjin": 26216, "##acing": 26217, "enzo": 26218, "jd": 26219, "ric": 26220, "scanner": 26221, "croats": 26222, "transcribed": 26223, "##49": 26224, "arden": 26225, "cv": 26226, "##hair": 26227, "##raphy": 26228, "##lver": 26229, "##uy": 26230, "357": 26231, "seventies": 26232, "staggering": 26233, "alam": 26234, "horticultural": 26235, "hs": 26236, "regression": 26237, "timbers": 26238, "blasting": 26239, "##ounded": 26240, "montagu": 26241, "manipulating": 26242, "##cit": 26243, "catalytic": 26244, "1550": 26245, "troopers": 26246, "##meo": 26247, "condemnation": 26248, "fitzpatrick": 26249, "##oire": 26250, "##roved": 26251, "inexperienced": 26252, "1670": 26253, "castes": 26254, "##lative": 26255, "outing": 26256, "314": 26257, "dubois": 26258, "flicking": 26259, "quarrel": 26260, "ste": 26261, "learners": 26262, "1625": 26263, "iq": 26264, "whistled": 26265, "##class": 26266, "282": 26267, "classify": 26268, "tariffs": 26269, "temperament": 26270, "355": 26271, "folly": 26272, "liszt": 26273, "##yles": 26274, "immersed": 26275, "jordanian": 26276, "ceasefire": 26277, "apparel": 26278, "extras": 26279, "maru": 26280, "fished": 26281, "##bio": 26282, "harta": 26283, "stockport": 26284, "assortment": 26285, "craftsman": 26286, "paralysis": 26287, "transmitters": 26288, "##cola": 26289, "blindness": 26290, "##wk": 26291, "fatally": 26292, "proficiency": 26293, "solemnly": 26294, "##orno": 26295, "repairing": 26296, "amore": 26297, "groceries": 26298, "ultraviolet": 26299, "##chase": 26300, "schoolhouse": 26301, "##tua": 26302, "resurgence": 26303, "nailed": 26304, "##otype": 26305, "##×": 26306, "ruse": 26307, "saliva": 26308, "diagrams": 26309, "##tructing": 26310, "albans": 26311, "rann": 26312, "thirties": 26313, "1b": 26314, "antennas": 26315, "hilarious": 26316, "cougars": 26317, "paddington": 26318, "stats": 26319, "##eger": 26320, "breakaway": 26321, "ipod": 26322, "reza": 26323, "authorship": 26324, "prohibiting": 26325, "scoffed": 26326, "##etz": 26327, "##ttle": 26328, "conscription": 26329, "defected": 26330, "trondheim": 26331, "##fires": 26332, "ivanov": 26333, "keenan": 26334, "##adan": 26335, "##ciful": 26336, "##fb": 26337, "##slow": 26338, "locating": 26339, "##ials": 26340, "##tford": 26341, "cadiz": 26342, "basalt": 26343, "blankly": 26344, "interned": 26345, "rags": 26346, "rattling": 26347, "##tick": 26348, "carpathian": 26349, "reassured": 26350, "sync": 26351, "bum": 26352, "guildford": 26353, "iss": 26354, "staunch": 26355, "##onga": 26356, "astronomers": 26357, "sera": 26358, "sofie": 26359, "emergencies": 26360, "susquehanna": 26361, "##heard": 26362, "duc": 26363, "mastery": 26364, "vh1": 26365, "williamsburg": 26366, "bayer": 26367, "buckled": 26368, "craving": 26369, "##khan": 26370, "##rdes": 26371, "bloomington": 26372, "##write": 26373, "alton": 26374, "barbecue": 26375, "##bians": 26376, "justine": 26377, "##hri": 26378, "##ndt": 26379, "delightful": 26380, "smartphone": 26381, "newtown": 26382, "photon": 26383, "retrieval": 26384, "peugeot": 26385, "hissing": 26386, "##monium": 26387, "##orough": 26388, "flavors": 26389, "lighted": 26390, "relaunched": 26391, "tainted": 26392, "##games": 26393, "##lysis": 26394, "anarchy": 26395, "microscopic": 26396, "hopping": 26397, "adept": 26398, "evade": 26399, "evie": 26400, "##beau": 26401, "inhibit": 26402, "sinn": 26403, "adjustable": 26404, "hurst": 26405, "intuition": 26406, "wilton": 26407, "cisco": 26408, "44th": 26409, "lawful": 26410, "lowlands": 26411, "stockings": 26412, "thierry": 26413, "##dalen": 26414, "##hila": 26415, "##nai": 26416, "fates": 26417, "prank": 26418, "tb": 26419, "maison": 26420, "lobbied": 26421, "provocative": 26422, "1724": 26423, "4a": 26424, "utopia": 26425, "##qual": 26426, "carbonate": 26427, "gujarati": 26428, "purcell": 26429, "##rford": 26430, "curtiss": 26431, "##mei": 26432, "overgrown": 26433, "arenas": 26434, "mediation": 26435, "swallows": 26436, "##rnik": 26437, "respectful": 26438, "turnbull": 26439, "##hedron": 26440, "##hope": 26441, "alyssa": 26442, "ozone": 26443, "##ʻi": 26444, "ami": 26445, "gestapo": 26446, "johansson": 26447, "snooker": 26448, "canteen": 26449, "cuff": 26450, "declines": 26451, "empathy": 26452, "stigma": 26453, "##ags": 26454, "##iner": 26455, "##raine": 26456, "taxpayers": 26457, "gui": 26458, "volga": 26459, "##wright": 26460, "##copic": 26461, "lifespan": 26462, "overcame": 26463, "tattooed": 26464, "enactment": 26465, "giggles": 26466, "##ador": 26467, "##camp": 26468, "barrington": 26469, "bribe": 26470, "obligatory": 26471, "orbiting": 26472, "peng": 26473, "##enas": 26474, "elusive": 26475, "sucker": 26476, "##vating": 26477, "cong": 26478, "hardship": 26479, "empowered": 26480, "anticipating": 26481, "estrada": 26482, "cryptic": 26483, "greasy": 26484, "detainees": 26485, "planck": 26486, "sudbury": 26487, "plaid": 26488, "dod": 26489, "marriott": 26490, "kayla": 26491, "##ears": 26492, "##vb": 26493, "##zd": 26494, "mortally": 26495, "##hein": 26496, "cognition": 26497, "radha": 26498, "319": 26499, "liechtenstein": 26500, "meade": 26501, "richly": 26502, "argyle": 26503, "harpsichord": 26504, "liberalism": 26505, "trumpets": 26506, "lauded": 26507, "tyrant": 26508, "salsa": 26509, "tiled": 26510, "lear": 26511, "promoters": 26512, "reused": 26513, "slicing": 26514, "trident": 26515, "##chuk": 26516, "##gami": 26517, "##lka": 26518, "cantor": 26519, "checkpoint": 26520, "##points": 26521, "gaul": 26522, "leger": 26523, "mammalian": 26524, "##tov": 26525, "##aar": 26526, "##schaft": 26527, "doha": 26528, "frenchman": 26529, "nirvana": 26530, "##vino": 26531, "delgado": 26532, "headlining": 26533, "##eron": 26534, "##iography": 26535, "jug": 26536, "tko": 26537, "1649": 26538, "naga": 26539, "intersections": 26540, "##jia": 26541, "benfica": 26542, "nawab": 26543, "##suka": 26544, "ashford": 26545, "gulp": 26546, "##deck": 26547, "##vill": 26548, "##rug": 26549, "brentford": 26550, "frazier": 26551, "pleasures": 26552, "dunne": 26553, "potsdam": 26554, "shenzhen": 26555, "dentistry": 26556, "##tec": 26557, "flanagan": 26558, "##dorff": 26559, "##hear": 26560, "chorale": 26561, "dinah": 26562, "prem": 26563, "quezon": 26564, "##rogated": 26565, "relinquished": 26566, "sutra": 26567, "terri": 26568, "##pani": 26569, "flaps": 26570, "##rissa": 26571, "poly": 26572, "##rnet": 26573, "homme": 26574, "aback": 26575, "##eki": 26576, "linger": 26577, "womb": 26578, "##kson": 26579, "##lewood": 26580, "doorstep": 26581, "orthodoxy": 26582, "threaded": 26583, "westfield": 26584, "##rval": 26585, "dioceses": 26586, "fridays": 26587, "subsided": 26588, "##gata": 26589, "loyalists": 26590, "##biotic": 26591, "##ettes": 26592, "letterman": 26593, "lunatic": 26594, "prelate": 26595, "tenderly": 26596, "invariably": 26597, "souza": 26598, "thug": 26599, "winslow": 26600, "##otide": 26601, "furlongs": 26602, "gogh": 26603, "jeopardy": 26604, "##runa": 26605, "pegasus": 26606, "##umble": 26607, "humiliated": 26608, "standalone": 26609, "tagged": 26610, "##roller": 26611, "freshmen": 26612, "klan": 26613, "##bright": 26614, "attaining": 26615, "initiating": 26616, "transatlantic": 26617, "logged": 26618, "viz": 26619, "##uance": 26620, "1723": 26621, "combatants": 26622, "intervening": 26623, "stephane": 26624, "chieftain": 26625, "despised": 26626, "grazed": 26627, "317": 26628, "cdc": 26629, "galveston": 26630, "godzilla": 26631, "macro": 26632, "simulate": 26633, "##planes": 26634, "parades": 26635, "##esses": 26636, "960": 26637, "##ductive": 26638, "##unes": 26639, "equator": 26640, "overdose": 26641, "##cans": 26642, "##hosh": 26643, "##lifting": 26644, "joshi": 26645, "epstein": 26646, "sonora": 26647, "treacherous": 26648, "aquatics": 26649, "manchu": 26650, "responsive": 26651, "##sation": 26652, "supervisory": 26653, "##christ": 26654, "##llins": 26655, "##ibar": 26656, "##balance": 26657, "##uso": 26658, "kimball": 26659, "karlsruhe": 26660, "mab": 26661, "##emy": 26662, "ignores": 26663, "phonetic": 26664, "reuters": 26665, "spaghetti": 26666, "820": 26667, "almighty": 26668, "danzig": 26669, "rumbling": 26670, "tombstone": 26671, "designations": 26672, "lured": 26673, "outset": 26674, "##felt": 26675, "supermarkets": 26676, "##wt": 26677, "grupo": 26678, "kei": 26679, "kraft": 26680, "susanna": 26681, "##blood": 26682, "comprehension": 26683, "genealogy": 26684, "##aghan": 26685, "##verted": 26686, "redding": 26687, "##ythe": 26688, "1722": 26689, "bowing": 26690, "##pore": 26691, "##roi": 26692, "lest": 26693, "sharpened": 26694, "fulbright": 26695, "valkyrie": 26696, "sikhs": 26697, "##unds": 26698, "swans": 26699, "bouquet": 26700, "merritt": 26701, "##tage": 26702, "##venting": 26703, "commuted": 26704, "redhead": 26705, "clerks": 26706, "leasing": 26707, "cesare": 26708, "dea": 26709, "hazy": 26710, "##vances": 26711, "fledged": 26712, "greenfield": 26713, "servicemen": 26714, "##gical": 26715, "armando": 26716, "blackout": 26717, "dt": 26718, "sagged": 26719, "downloadable": 26720, "intra": 26721, "potion": 26722, "pods": 26723, "##4th": 26724, "##mism": 26725, "xp": 26726, "attendants": 26727, "gambia": 26728, "stale": 26729, "##ntine": 26730, "plump": 26731, "asteroids": 26732, "rediscovered": 26733, "buds": 26734, "flea": 26735, "hive": 26736, "##neas": 26737, "1737": 26738, "classifications": 26739, "debuts": 26740, "##eles": 26741, "olympus": 26742, "scala": 26743, "##eurs": 26744, "##gno": 26745, "##mute": 26746, "hummed": 26747, "sigismund": 26748, "visuals": 26749, "wiggled": 26750, "await": 26751, "pilasters": 26752, "clench": 26753, "sulfate": 26754, "##ances": 26755, "bellevue": 26756, "enigma": 26757, "trainee": 26758, "snort": 26759, "##sw": 26760, "clouded": 26761, "denim": 26762, "##rank": 26763, "##rder": 26764, "churning": 26765, "hartman": 26766, "lodges": 26767, "riches": 26768, "sima": 26769, "##missible": 26770, "accountable": 26771, "socrates": 26772, "regulates": 26773, "mueller": 26774, "##cr": 26775, "1702": 26776, "avoids": 26777, "solids": 26778, "himalayas": 26779, "nutrient": 26780, "pup": 26781, "##jevic": 26782, "squat": 26783, "fades": 26784, "nec": 26785, "##lates": 26786, "##pina": 26787, "##rona": 26788, "##ου": 26789, "privateer": 26790, "tequila": 26791, "##gative": 26792, "##mpton": 26793, "apt": 26794, "hornet": 26795, "immortals": 26796, "##dou": 26797, "asturias": 26798, "cleansing": 26799, "dario": 26800, "##rries": 26801, "##anta": 26802, "etymology": 26803, "servicing": 26804, "zhejiang": 26805, "##venor": 26806, "##nx": 26807, "horned": 26808, "erasmus": 26809, "rayon": 26810, "relocating": 26811, "£10": 26812, "##bags": 26813, "escalated": 26814, "promenade": 26815, "stubble": 26816, "2010s": 26817, "artisans": 26818, "axial": 26819, "liquids": 26820, "mora": 26821, "sho": 26822, "yoo": 26823, "##tsky": 26824, "bundles": 26825, "oldies": 26826, "##nally": 26827, "notification": 26828, "bastion": 26829, "##ths": 26830, "sparkle": 26831, "##lved": 26832, "1728": 26833, "leash": 26834, "pathogen": 26835, "highs": 26836, "##hmi": 26837, "immature": 26838, "880": 26839, "gonzaga": 26840, "ignatius": 26841, "mansions": 26842, "monterrey": 26843, "sweets": 26844, "bryson": 26845, "##loe": 26846, "polled": 26847, "regatta": 26848, "brightest": 26849, "pei": 26850, "rosy": 26851, "squid": 26852, "hatfield": 26853, "payroll": 26854, "addict": 26855, "meath": 26856, "cornerback": 26857, "heaviest": 26858, "lodging": 26859, "##mage": 26860, "capcom": 26861, "rippled": 26862, "##sily": 26863, "barnet": 26864, "mayhem": 26865, "ymca": 26866, "snuggled": 26867, "rousseau": 26868, "##cute": 26869, "blanchard": 26870, "284": 26871, "fragmented": 26872, "leighton": 26873, "chromosomes": 26874, "risking": 26875, "##md": 26876, "##strel": 26877, "##utter": 26878, "corinne": 26879, "coyotes": 26880, "cynical": 26881, "hiroshi": 26882, "yeomanry": 26883, "##ractive": 26884, "ebook": 26885, "grading": 26886, "mandela": 26887, "plume": 26888, "agustin": 26889, "magdalene": 26890, "##rkin": 26891, "bea": 26892, "femme": 26893, "trafford": 26894, "##coll": 26895, "##lun": 26896, "##tance": 26897, "52nd": 26898, "fourier": 26899, "upton": 26900, "##mental": 26901, "camilla": 26902, "gust": 26903, "iihf": 26904, "islamabad": 26905, "longevity": 26906, "##kala": 26907, "feldman": 26908, "netting": 26909, "##rization": 26910, "endeavour": 26911, "foraging": 26912, "mfa": 26913, "orr": 26914, "##open": 26915, "greyish": 26916, "contradiction": 26917, "graz": 26918, "##ruff": 26919, "handicapped": 26920, "marlene": 26921, "tweed": 26922, "oaxaca": 26923, "spp": 26924, "campos": 26925, "miocene": 26926, "pri": 26927, "configured": 26928, "cooks": 26929, "pluto": 26930, "cozy": 26931, "pornographic": 26932, "##entes": 26933, "70th": 26934, "fairness": 26935, "glided": 26936, "jonny": 26937, "lynne": 26938, "rounding": 26939, "sired": 26940, "##emon": 26941, "##nist": 26942, "remade": 26943, "uncover": 26944, "##mack": 26945, "complied": 26946, "lei": 26947, "newsweek": 26948, "##jured": 26949, "##parts": 26950, "##enting": 26951, "##pg": 26952, "293": 26953, "finer": 26954, "guerrillas": 26955, "athenian": 26956, "deng": 26957, "disused": 26958, "stepmother": 26959, "accuse": 26960, "gingerly": 26961, "seduction": 26962, "521": 26963, "confronting": 26964, "##walker": 26965, "##going": 26966, "gora": 26967, "nostalgia": 26968, "sabres": 26969, "virginity": 26970, "wrenched": 26971, "##minated": 26972, "syndication": 26973, "wielding": 26974, "eyre": 26975, "##56": 26976, "##gnon": 26977, "##igny": 26978, "behaved": 26979, "taxpayer": 26980, "sweeps": 26981, "##growth": 26982, "childless": 26983, "gallant": 26984, "##ywood": 26985, "amplified": 26986, "geraldine": 26987, "scrape": 26988, "##ffi": 26989, "babylonian": 26990, "fresco": 26991, "##rdan": 26992, "##kney": 26993, "##position": 26994, "1718": 26995, "restricting": 26996, "tack": 26997, "fukuoka": 26998, "osborn": 26999, "selector": 27000, "partnering": 27001, "##dlow": 27002, "318": 27003, "gnu": 27004, "kia": 27005, "tak": 27006, "whitley": 27007, "gables": 27008, "##54": 27009, "##mania": 27010, "mri": 27011, "softness": 27012, "immersion": 27013, "##bots": 27014, "##evsky": 27015, "1713": 27016, "chilling": 27017, "insignificant": 27018, "pcs": 27019, "##uis": 27020, "elites": 27021, "lina": 27022, "purported": 27023, "supplemental": 27024, "teaming": 27025, "##americana": 27026, "##dding": 27027, "##inton": 27028, "proficient": 27029, "rouen": 27030, "##nage": 27031, "##rret": 27032, "niccolo": 27033, "selects": 27034, "##bread": 27035, "fluffy": 27036, "1621": 27037, "gruff": 27038, "knotted": 27039, "mukherjee": 27040, "polgara": 27041, "thrash": 27042, "nicholls": 27043, "secluded": 27044, "smoothing": 27045, "thru": 27046, "corsica": 27047, "loaf": 27048, "whitaker": 27049, "inquiries": 27050, "##rrier": 27051, "##kam": 27052, "indochina": 27053, "289": 27054, "marlins": 27055, "myles": 27056, "peking": 27057, "##tea": 27058, "extracts": 27059, "pastry": 27060, "superhuman": 27061, "connacht": 27062, "vogel": 27063, "##ditional": 27064, "##het": 27065, "##udged": 27066, "##lash": 27067, "gloss": 27068, "quarries": 27069, "refit": 27070, "teaser": 27071, "##alic": 27072, "##gaon": 27073, "20s": 27074, "materialized": 27075, "sling": 27076, "camped": 27077, "pickering": 27078, "tung": 27079, "tracker": 27080, "pursuant": 27081, "##cide": 27082, "cranes": 27083, "soc": 27084, "##cini": 27085, "##typical": 27086, "##viere": 27087, "anhalt": 27088, "overboard": 27089, "workout": 27090, "chores": 27091, "fares": 27092, "orphaned": 27093, "stains": 27094, "##logie": 27095, "fenton": 27096, "surpassing": 27097, "joyah": 27098, "triggers": 27099, "##itte": 27100, "grandmaster": 27101, "##lass": 27102, "##lists": 27103, "clapping": 27104, "fraudulent": 27105, "ledger": 27106, "nagasaki": 27107, "##cor": 27108, "##nosis": 27109, "##tsa": 27110, "eucalyptus": 27111, "tun": 27112, "##icio": 27113, "##rney": 27114, "##tara": 27115, "dax": 27116, "heroism": 27117, "ina": 27118, "wrexham": 27119, "onboard": 27120, "unsigned": 27121, "##dates": 27122, "moshe": 27123, "galley": 27124, "winnie": 27125, "droplets": 27126, "exiles": 27127, "praises": 27128, "watered": 27129, "noodles": 27130, "##aia": 27131, "fein": 27132, "adi": 27133, "leland": 27134, "multicultural": 27135, "stink": 27136, "bingo": 27137, "comets": 27138, "erskine": 27139, "modernized": 27140, "canned": 27141, "constraint": 27142, "domestically": 27143, "chemotherapy": 27144, "featherweight": 27145, "stifled": 27146, "##mum": 27147, "darkly": 27148, "irresistible": 27149, "refreshing": 27150, "hasty": 27151, "isolate": 27152, "##oys": 27153, "kitchener": 27154, "planners": 27155, "##wehr": 27156, "cages": 27157, "yarn": 27158, "implant": 27159, "toulon": 27160, "elects": 27161, "childbirth": 27162, "yue": 27163, "##lind": 27164, "##lone": 27165, "cn": 27166, "rightful": 27167, "sportsman": 27168, "junctions": 27169, "remodeled": 27170, "specifies": 27171, "##rgh": 27172, "291": 27173, "##oons": 27174, "complimented": 27175, "##urgent": 27176, "lister": 27177, "ot": 27178, "##logic": 27179, "bequeathed": 27180, "cheekbones": 27181, "fontana": 27182, "gabby": 27183, "##dial": 27184, "amadeus": 27185, "corrugated": 27186, "maverick": 27187, "resented": 27188, "triangles": 27189, "##hered": 27190, "##usly": 27191, "nazareth": 27192, "tyrol": 27193, "1675": 27194, "assent": 27195, "poorer": 27196, "sectional": 27197, "aegean": 27198, "##cous": 27199, "296": 27200, "nylon": 27201, "ghanaian": 27202, "##egorical": 27203, "##weig": 27204, "cushions": 27205, "forbid": 27206, "fusiliers": 27207, "obstruction": 27208, "somerville": 27209, "##scia": 27210, "dime": 27211, "earrings": 27212, "elliptical": 27213, "leyte": 27214, "oder": 27215, "polymers": 27216, "timmy": 27217, "atm": 27218, "midtown": 27219, "piloted": 27220, "settles": 27221, "continual": 27222, "externally": 27223, "mayfield": 27224, "##uh": 27225, "enrichment": 27226, "henson": 27227, "keane": 27228, "persians": 27229, "1733": 27230, "benji": 27231, "braden": 27232, "pep": 27233, "324": 27234, "##efe": 27235, "contenders": 27236, "pepsi": 27237, "valet": 27238, "##isches": 27239, "298": 27240, "##asse": 27241, "##earing": 27242, "goofy": 27243, "stroll": 27244, "##amen": 27245, "authoritarian": 27246, "occurrences": 27247, "adversary": 27248, "ahmedabad": 27249, "tangent": 27250, "toppled": 27251, "dorchester": 27252, "1672": 27253, "modernism": 27254, "marxism": 27255, "islamist": 27256, "charlemagne": 27257, "exponential": 27258, "racks": 27259, "unicode": 27260, "brunette": 27261, "mbc": 27262, "pic": 27263, "skirmish": 27264, "##bund": 27265, "##lad": 27266, "##powered": 27267, "##yst": 27268, "hoisted": 27269, "messina": 27270, "shatter": 27271, "##ctum": 27272, "jedi": 27273, "vantage": 27274, "##music": 27275, "##neil": 27276, "clemens": 27277, "mahmoud": 27278, "corrupted": 27279, "authentication": 27280, "lowry": 27281, "nils": 27282, "##washed": 27283, "omnibus": 27284, "wounding": 27285, "jillian": 27286, "##itors": 27287, "##opped": 27288, "serialized": 27289, "narcotics": 27290, "handheld": 27291, "##arm": 27292, "##plicity": 27293, "intersecting": 27294, "stimulating": 27295, "##onis": 27296, "crate": 27297, "fellowships": 27298, "hemingway": 27299, "casinos": 27300, "climatic": 27301, "fordham": 27302, "copeland": 27303, "drip": 27304, "beatty": 27305, "leaflets": 27306, "robber": 27307, "brothel": 27308, "madeira": 27309, "##hedral": 27310, "sphinx": 27311, "ultrasound": 27312, "##vana": 27313, "valor": 27314, "forbade": 27315, "leonid": 27316, "villas": 27317, "##aldo": 27318, "duane": 27319, "marquez": 27320, "##cytes": 27321, "disadvantaged": 27322, "forearms": 27323, "kawasaki": 27324, "reacts": 27325, "consular": 27326, "lax": 27327, "uncles": 27328, "uphold": 27329, "##hopper": 27330, "concepcion": 27331, "dorsey": 27332, "lass": 27333, "##izan": 27334, "arching": 27335, "passageway": 27336, "1708": 27337, "researches": 27338, "tia": 27339, "internationals": 27340, "##graphs": 27341, "##opers": 27342, "distinguishes": 27343, "javanese": 27344, "divert": 27345, "##uven": 27346, "plotted": 27347, "##listic": 27348, "##rwin": 27349, "##erik": 27350, "##tify": 27351, "affirmative": 27352, "signifies": 27353, "validation": 27354, "##bson": 27355, "kari": 27356, "felicity": 27357, "georgina": 27358, "zulu": 27359, "##eros": 27360, "##rained": 27361, "##rath": 27362, "overcoming": 27363, "##dot": 27364, "argyll": 27365, "##rbin": 27366, "1734": 27367, "chiba": 27368, "ratification": 27369, "windy": 27370, "earls": 27371, "parapet": 27372, "##marks": 27373, "hunan": 27374, "pristine": 27375, "astrid": 27376, "punta": 27377, "##gart": 27378, "brodie": 27379, "##kota": 27380, "##oder": 27381, "malaga": 27382, "minerva": 27383, "rouse": 27384, "##phonic": 27385, "bellowed": 27386, "pagoda": 27387, "portals": 27388, "reclamation": 27389, "##gur": 27390, "##odies": 27391, "##⁄₄": 27392, "parentheses": 27393, "quoting": 27394, "allergic": 27395, "palette": 27396, "showcases": 27397, "benefactor": 27398, "heartland": 27399, "nonlinear": 27400, "##tness": 27401, "bladed": 27402, "cheerfully": 27403, "scans": 27404, "##ety": 27405, "##hone": 27406, "1666": 27407, "girlfriends": 27408, "pedersen": 27409, "hiram": 27410, "sous": 27411, "##liche": 27412, "##nator": 27413, "1683": 27414, "##nery": 27415, "##orio": 27416, "##umen": 27417, "bobo": 27418, "primaries": 27419, "smiley": 27420, "##cb": 27421, "unearthed": 27422, "uniformly": 27423, "fis": 27424, "metadata": 27425, "1635": 27426, "ind": 27427, "##oted": 27428, "recoil": 27429, "##titles": 27430, "##tura": 27431, "##ια": 27432, "406": 27433, "hilbert": 27434, "jamestown": 27435, "mcmillan": 27436, "tulane": 27437, "seychelles": 27438, "##frid": 27439, "antics": 27440, "coli": 27441, "fated": 27442, "stucco": 27443, "##grants": 27444, "1654": 27445, "bulky": 27446, "accolades": 27447, "arrays": 27448, "caledonian": 27449, "carnage": 27450, "optimism": 27451, "puebla": 27452, "##tative": 27453, "##cave": 27454, "enforcing": 27455, "rotherham": 27456, "seo": 27457, "dunlop": 27458, "aeronautics": 27459, "chimed": 27460, "incline": 27461, "zoning": 27462, "archduke": 27463, "hellenistic": 27464, "##oses": 27465, "##sions": 27466, "candi": 27467, "thong": 27468, "##ople": 27469, "magnate": 27470, "rustic": 27471, "##rsk": 27472, "projective": 27473, "slant": 27474, "##offs": 27475, "danes": 27476, "hollis": 27477, "vocalists": 27478, "##ammed": 27479, "congenital": 27480, "contend": 27481, "gesellschaft": 27482, "##ocating": 27483, "##pressive": 27484, "douglass": 27485, "quieter": 27486, "##cm": 27487, "##kshi": 27488, "howled": 27489, "salim": 27490, "spontaneously": 27491, "townsville": 27492, "buena": 27493, "southport": 27494, "##bold": 27495, "kato": 27496, "1638": 27497, "faerie": 27498, "stiffly": 27499, "##vus": 27500, "##rled": 27501, "297": 27502, "flawless": 27503, "realising": 27504, "taboo": 27505, "##7th": 27506, "bytes": 27507, "straightening": 27508, "356": 27509, "jena": 27510, "##hid": 27511, "##rmin": 27512, "cartwright": 27513, "berber": 27514, "bertram": 27515, "soloists": 27516, "411": 27517, "noses": 27518, "417": 27519, "coping": 27520, "fission": 27521, "hardin": 27522, "inca": 27523, "##cen": 27524, "1717": 27525, "mobilized": 27526, "vhf": 27527, "##raf": 27528, "biscuits": 27529, "curate": 27530, "##85": 27531, "##anial": 27532, "331": 27533, "gaunt": 27534, "neighbourhoods": 27535, "1540": 27536, "##abas": 27537, "blanca": 27538, "bypassed": 27539, "sockets": 27540, "behold": 27541, "coincidentally": 27542, "##bane": 27543, "nara": 27544, "shave": 27545, "splinter": 27546, "terrific": 27547, "##arion": 27548, "##erian": 27549, "commonplace": 27550, "juris": 27551, "redwood": 27552, "waistband": 27553, "boxed": 27554, "caitlin": 27555, "fingerprints": 27556, "jennie": 27557, "naturalized": 27558, "##ired": 27559, "balfour": 27560, "craters": 27561, "jody": 27562, "bungalow": 27563, "hugely": 27564, "quilt": 27565, "glitter": 27566, "pigeons": 27567, "undertaker": 27568, "bulging": 27569, "constrained": 27570, "goo": 27571, "##sil": 27572, "##akh": 27573, "assimilation": 27574, "reworked": 27575, "##person": 27576, "persuasion": 27577, "##pants": 27578, "felicia": 27579, "##cliff": 27580, "##ulent": 27581, "1732": 27582, "explodes": 27583, "##dun": 27584, "##inium": 27585, "##zic": 27586, "lyman": 27587, "vulture": 27588, "hog": 27589, "overlook": 27590, "begs": 27591, "northwards": 27592, "ow": 27593, "spoil": 27594, "##urer": 27595, "fatima": 27596, "favorably": 27597, "accumulate": 27598, "sargent": 27599, "sorority": 27600, "corresponded": 27601, "dispersal": 27602, "kochi": 27603, "toned": 27604, "##imi": 27605, "##lita": 27606, "internacional": 27607, "newfound": 27608, "##agger": 27609, "##lynn": 27610, "##rigue": 27611, "booths": 27612, "peanuts": 27613, "##eborg": 27614, "medicare": 27615, "muriel": 27616, "nur": 27617, "##uram": 27618, "crates": 27619, "millennia": 27620, "pajamas": 27621, "worsened": 27622, "##breakers": 27623, "jimi": 27624, "vanuatu": 27625, "yawned": 27626, "##udeau": 27627, "carousel": 27628, "##hony": 27629, "hurdle": 27630, "##ccus": 27631, "##mounted": 27632, "##pod": 27633, "rv": 27634, "##eche": 27635, "airship": 27636, "ambiguity": 27637, "compulsion": 27638, "recapture": 27639, "##claiming": 27640, "arthritis": 27641, "##osomal": 27642, "1667": 27643, "asserting": 27644, "ngc": 27645, "sniffing": 27646, "dade": 27647, "discontent": 27648, "glendale": 27649, "ported": 27650, "##amina": 27651, "defamation": 27652, "rammed": 27653, "##scent": 27654, "fling": 27655, "livingstone": 27656, "##fleet": 27657, "875": 27658, "##ppy": 27659, "apocalyptic": 27660, "comrade": 27661, "lcd": 27662, "##lowe": 27663, "cessna": 27664, "eine": 27665, "persecuted": 27666, "subsistence": 27667, "demi": 27668, "hoop": 27669, "reliefs": 27670, "710": 27671, "coptic": 27672, "progressing": 27673, "stemmed": 27674, "perpetrators": 27675, "1665": 27676, "priestess": 27677, "##nio": 27678, "dobson": 27679, "ebony": 27680, "rooster": 27681, "itf": 27682, "tortricidae": 27683, "##bbon": 27684, "##jian": 27685, "cleanup": 27686, "##jean": 27687, "##øy": 27688, "1721": 27689, "eighties": 27690, "taxonomic": 27691, "holiness": 27692, "##hearted": 27693, "##spar": 27694, "antilles": 27695, "showcasing": 27696, "stabilized": 27697, "##nb": 27698, "gia": 27699, "mascara": 27700, "michelangelo": 27701, "dawned": 27702, "##uria": 27703, "##vinsky": 27704, "extinguished": 27705, "fitz": 27706, "grotesque": 27707, "£100": 27708, "##fera": 27709, "##loid": 27710, "##mous": 27711, "barges": 27712, "neue": 27713, "throbbed": 27714, "cipher": 27715, "johnnie": 27716, "##a1": 27717, "##mpt": 27718, "outburst": 27719, "##swick": 27720, "spearheaded": 27721, "administrations": 27722, "c1": 27723, "heartbreak": 27724, "pixels": 27725, "pleasantly": 27726, "##enay": 27727, "lombardy": 27728, "plush": 27729, "##nsed": 27730, "bobbie": 27731, "##hly": 27732, "reapers": 27733, "tremor": 27734, "xiang": 27735, "minogue": 27736, "substantive": 27737, "hitch": 27738, "barak": 27739, "##wyl": 27740, "kwan": 27741, "##encia": 27742, "910": 27743, "obscene": 27744, "elegance": 27745, "indus": 27746, "surfer": 27747, "bribery": 27748, "conserve": 27749, "##hyllum": 27750, "##masters": 27751, "horatio": 27752, "##fat": 27753, "apes": 27754, "rebound": 27755, "psychotic": 27756, "##pour": 27757, "iteration": 27758, "##mium": 27759, "##vani": 27760, "botanic": 27761, "horribly": 27762, "antiques": 27763, "dispose": 27764, "paxton": 27765, "##hli": 27766, "##wg": 27767, "timeless": 27768, "1704": 27769, "disregard": 27770, "engraver": 27771, "hounds": 27772, "##bau": 27773, "##version": 27774, "looted": 27775, "uno": 27776, "facilitates": 27777, "groans": 27778, "masjid": 27779, "rutland": 27780, "antibody": 27781, "disqualification": 27782, "decatur": 27783, "footballers": 27784, "quake": 27785, "slacks": 27786, "48th": 27787, "rein": 27788, "scribe": 27789, "stabilize": 27790, "commits": 27791, "exemplary": 27792, "tho": 27793, "##hort": 27794, "##chison": 27795, "pantry": 27796, "traversed": 27797, "##hiti": 27798, "disrepair": 27799, "identifiable": 27800, "vibrated": 27801, "baccalaureate": 27802, "##nnis": 27803, "csa": 27804, "interviewing": 27805, "##iensis": 27806, "##raße": 27807, "greaves": 27808, "wealthiest": 27809, "343": 27810, "classed": 27811, "jogged": 27812, "£5": 27813, "##58": 27814, "##atal": 27815, "illuminating": 27816, "knicks": 27817, "respecting": 27818, "##uno": 27819, "scrubbed": 27820, "##iji": 27821, "##dles": 27822, "kruger": 27823, "moods": 27824, "growls": 27825, "raider": 27826, "silvia": 27827, "chefs": 27828, "kam": 27829, "vr": 27830, "cree": 27831, "percival": 27832, "##terol": 27833, "gunter": 27834, "counterattack": 27835, "defiant": 27836, "henan": 27837, "ze": 27838, "##rasia": 27839, "##riety": 27840, "equivalence": 27841, "submissions": 27842, "##fra": 27843, "##thor": 27844, "bautista": 27845, "mechanically": 27846, "##heater": 27847, "cornice": 27848, "herbal": 27849, "templar": 27850, "##mering": 27851, "outputs": 27852, "ruining": 27853, "ligand": 27854, "renumbered": 27855, "extravagant": 27856, "mika": 27857, "blockbuster": 27858, "eta": 27859, "insurrection": 27860, "##ilia": 27861, "darkening": 27862, "ferocious": 27863, "pianos": 27864, "strife": 27865, "kinship": 27866, "##aer": 27867, "melee": 27868, "##anor": 27869, "##iste": 27870, "##may": 27871, "##oue": 27872, "decidedly": 27873, "weep": 27874, "##jad": 27875, "##missive": 27876, "##ppel": 27877, "354": 27878, "puget": 27879, "unease": 27880, "##gnant": 27881, "1629": 27882, "hammering": 27883, "kassel": 27884, "ob": 27885, "wessex": 27886, "##lga": 27887, "bromwich": 27888, "egan": 27889, "paranoia": 27890, "utilization": 27891, "##atable": 27892, "##idad": 27893, "contradictory": 27894, "provoke": 27895, "##ols": 27896, "##ouring": 27897, "##tangled": 27898, "knesset": 27899, "##very": 27900, "##lette": 27901, "plumbing": 27902, "##sden": 27903, "##¹": 27904, "greensboro": 27905, "occult": 27906, "sniff": 27907, "338": 27908, "zev": 27909, "beaming": 27910, "gamer": 27911, "haggard": 27912, "mahal": 27913, "##olt": 27914, "##pins": 27915, "mendes": 27916, "utmost": 27917, "briefing": 27918, "gunnery": 27919, "##gut": 27920, "##pher": 27921, "##zh": 27922, "##rok": 27923, "1679": 27924, "khalifa": 27925, "sonya": 27926, "##boot": 27927, "principals": 27928, "urbana": 27929, "wiring": 27930, "##liffe": 27931, "##minating": 27932, "##rrado": 27933, "dahl": 27934, "nyu": 27935, "skepticism": 27936, "np": 27937, "townspeople": 27938, "ithaca": 27939, "lobster": 27940, "somethin": 27941, "##fur": 27942, "##arina": 27943, "##−1": 27944, "freighter": 27945, "zimmerman": 27946, "biceps": 27947, "contractual": 27948, "##herton": 27949, "amend": 27950, "hurrying": 27951, "subconscious": 27952, "##anal": 27953, "336": 27954, "meng": 27955, "clermont": 27956, "spawning": 27957, "##eia": 27958, "##lub": 27959, "dignitaries": 27960, "impetus": 27961, "snacks": 27962, "spotting": 27963, "twigs": 27964, "##bilis": 27965, "##cz": 27966, "##ouk": 27967, "libertadores": 27968, "nic": 27969, "skylar": 27970, "##aina": 27971, "##firm": 27972, "gustave": 27973, "asean": 27974, "##anum": 27975, "dieter": 27976, "legislatures": 27977, "flirt": 27978, "bromley": 27979, "trolls": 27980, "umar": 27981, "##bbies": 27982, "##tyle": 27983, "blah": 27984, "parc": 27985, "bridgeport": 27986, "crank": 27987, "negligence": 27988, "##nction": 27989, "46th": 27990, "constantin": 27991, "molded": 27992, "bandages": 27993, "seriousness": 27994, "00pm": 27995, "siegel": 27996, "carpets": 27997, "compartments": 27998, "upbeat": 27999, "statehood": 28000, "##dner": 28001, "##edging": 28002, "marko": 28003, "730": 28004, "platt": 28005, "##hane": 28006, "paving": 28007, "##iy": 28008, "1738": 28009, "abbess": 28010, "impatience": 28011, "limousine": 28012, "nbl": 28013, "##talk": 28014, "441": 28015, "lucille": 28016, "mojo": 28017, "nightfall": 28018, "robbers": 28019, "##nais": 28020, "karel": 28021, "brisk": 28022, "calves": 28023, "replicate": 28024, "ascribed": 28025, "telescopes": 28026, "##olf": 28027, "intimidated": 28028, "##reen": 28029, "ballast": 28030, "specialization": 28031, "##sit": 28032, "aerodynamic": 28033, "caliphate": 28034, "rainer": 28035, "visionary": 28036, "##arded": 28037, "epsilon": 28038, "##aday": 28039, "##onte": 28040, "aggregation": 28041, "auditory": 28042, "boosted": 28043, "reunification": 28044, "kathmandu": 28045, "loco": 28046, "robyn": 28047, "402": 28048, "acknowledges": 28049, "appointing": 28050, "humanoid": 28051, "newell": 28052, "redeveloped": 28053, "restraints": 28054, "##tained": 28055, "barbarians": 28056, "chopper": 28057, "1609": 28058, "italiana": 28059, "##lez": 28060, "##lho": 28061, "investigates": 28062, "wrestlemania": 28063, "##anies": 28064, "##bib": 28065, "690": 28066, "##falls": 28067, "creaked": 28068, "dragoons": 28069, "gravely": 28070, "minions": 28071, "stupidity": 28072, "volley": 28073, "##harat": 28074, "##week": 28075, "musik": 28076, "##eries": 28077, "##uously": 28078, "fungal": 28079, "massimo": 28080, "semantics": 28081, "malvern": 28082, "##ahl": 28083, "##pee": 28084, "discourage": 28085, "embryo": 28086, "imperialism": 28087, "1910s": 28088, "profoundly": 28089, "##ddled": 28090, "jiangsu": 28091, "sparkled": 28092, "stat": 28093, "##holz": 28094, "sweatshirt": 28095, "tobin": 28096, "##iction": 28097, "sneered": 28098, "##cheon": 28099, "##oit": 28100, "brit": 28101, "causal": 28102, "smyth": 28103, "##neuve": 28104, "diffuse": 28105, "perrin": 28106, "silvio": 28107, "##ipes": 28108, "##recht": 28109, "detonated": 28110, "iqbal": 28111, "selma": 28112, "##nism": 28113, "##zumi": 28114, "roasted": 28115, "##riders": 28116, "tay": 28117, "##ados": 28118, "##mament": 28119, "##mut": 28120, "##rud": 28121, "840": 28122, "completes": 28123, "nipples": 28124, "cfa": 28125, "flavour": 28126, "hirsch": 28127, "##laus": 28128, "calderon": 28129, "sneakers": 28130, "moravian": 28131, "##ksha": 28132, "1622": 28133, "rq": 28134, "294": 28135, "##imeters": 28136, "bodo": 28137, "##isance": 28138, "##pre": 28139, "##ronia": 28140, "anatomical": 28141, "excerpt": 28142, "##lke": 28143, "dh": 28144, "kunst": 28145, "##tablished": 28146, "##scoe": 28147, "biomass": 28148, "panted": 28149, "unharmed": 28150, "gael": 28151, "housemates": 28152, "montpellier": 28153, "##59": 28154, "coa": 28155, "rodents": 28156, "tonic": 28157, "hickory": 28158, "singleton": 28159, "##taro": 28160, "451": 28161, "1719": 28162, "aldo": 28163, "breaststroke": 28164, "dempsey": 28165, "och": 28166, "rocco": 28167, "##cuit": 28168, "merton": 28169, "dissemination": 28170, "midsummer": 28171, "serials": 28172, "##idi": 28173, "haji": 28174, "polynomials": 28175, "##rdon": 28176, "gs": 28177, "enoch": 28178, "prematurely": 28179, "shutter": 28180, "taunton": 28181, "£3": 28182, "##grating": 28183, "##inates": 28184, "archangel": 28185, "harassed": 28186, "##asco": 28187, "326": 28188, "archway": 28189, "dazzling": 28190, "##ecin": 28191, "1736": 28192, "sumo": 28193, "wat": 28194, "##kovich": 28195, "1086": 28196, "honneur": 28197, "##ently": 28198, "##nostic": 28199, "##ttal": 28200, "##idon": 28201, "1605": 28202, "403": 28203, "1716": 28204, "blogger": 28205, "rents": 28206, "##gnan": 28207, "hires": 28208, "##ikh": 28209, "##dant": 28210, "howie": 28211, "##rons": 28212, "handler": 28213, "retracted": 28214, "shocks": 28215, "1632": 28216, "arun": 28217, "duluth": 28218, "kepler": 28219, "trumpeter": 28220, "##lary": 28221, "peeking": 28222, "seasoned": 28223, "trooper": 28224, "##mara": 28225, "laszlo": 28226, "##iciencies": 28227, "##rti": 28228, "heterosexual": 28229, "##inatory": 28230, "##ssion": 28231, "indira": 28232, "jogging": 28233, "##inga": 28234, "##lism": 28235, "beit": 28236, "dissatisfaction": 28237, "malice": 28238, "##ately": 28239, "nedra": 28240, "peeling": 28241, "##rgeon": 28242, "47th": 28243, "stadiums": 28244, "475": 28245, "vertigo": 28246, "##ains": 28247, "iced": 28248, "restroom": 28249, "##plify": 28250, "##tub": 28251, "illustrating": 28252, "pear": 28253, "##chner": 28254, "##sibility": 28255, "inorganic": 28256, "rappers": 28257, "receipts": 28258, "watery": 28259, "##kura": 28260, "lucinda": 28261, "##oulos": 28262, "reintroduced": 28263, "##8th": 28264, "##tched": 28265, "gracefully": 28266, "saxons": 28267, "nutritional": 28268, "wastewater": 28269, "rained": 28270, "favourites": 28271, "bedrock": 28272, "fisted": 28273, "hallways": 28274, "likeness": 28275, "upscale": 28276, "##lateral": 28277, "1580": 28278, "blinds": 28279, "prequel": 28280, "##pps": 28281, "##tama": 28282, "deter": 28283, "humiliating": 28284, "restraining": 28285, "tn": 28286, "vents": 28287, "1659": 28288, "laundering": 28289, "recess": 28290, "rosary": 28291, "tractors": 28292, "coulter": 28293, "federer": 28294, "##ifiers": 28295, "##plin": 28296, "persistence": 28297, "##quitable": 28298, "geschichte": 28299, "pendulum": 28300, "quakers": 28301, "##beam": 28302, "bassett": 28303, "pictorial": 28304, "buffet": 28305, "koln": 28306, "##sitor": 28307, "drills": 28308, "reciprocal": 28309, "shooters": 28310, "##57": 28311, "##cton": 28312, "##tees": 28313, "converge": 28314, "pip": 28315, "dmitri": 28316, "donnelly": 28317, "yamamoto": 28318, "aqua": 28319, "azores": 28320, "demographics": 28321, "hypnotic": 28322, "spitfire": 28323, "suspend": 28324, "wryly": 28325, "roderick": 28326, "##rran": 28327, "sebastien": 28328, "##asurable": 28329, "mavericks": 28330, "##fles": 28331, "##200": 28332, "himalayan": 28333, "prodigy": 28334, "##iance": 28335, "transvaal": 28336, "demonstrators": 28337, "handcuffs": 28338, "dodged": 28339, "mcnamara": 28340, "sublime": 28341, "1726": 28342, "crazed": 28343, "##efined": 28344, "##till": 28345, "ivo": 28346, "pondered": 28347, "reconciled": 28348, "shrill": 28349, "sava": 28350, "##duk": 28351, "bal": 28352, "cad": 28353, "heresy": 28354, "jaipur": 28355, "goran": 28356, "##nished": 28357, "341": 28358, "lux": 28359, "shelly": 28360, "whitehall": 28361, "##hre": 28362, "israelis": 28363, "peacekeeping": 28364, "##wled": 28365, "1703": 28366, "demetrius": 28367, "ousted": 28368, "##arians": 28369, "##zos": 28370, "beale": 28371, "anwar": 28372, "backstroke": 28373, "raged": 28374, "shrinking": 28375, "cremated": 28376, "##yck": 28377, "benign": 28378, "towing": 28379, "wadi": 28380, "darmstadt": 28381, "landfill": 28382, "parana": 28383, "soothe": 28384, "colleen": 28385, "sidewalks": 28386, "mayfair": 28387, "tumble": 28388, "hepatitis": 28389, "ferrer": 28390, "superstructure": 28391, "##gingly": 28392, "##urse": 28393, "##wee": 28394, "anthropological": 28395, "translators": 28396, "##mies": 28397, "closeness": 28398, "hooves": 28399, "##pw": 28400, "mondays": 28401, "##roll": 28402, "##vita": 28403, "landscaping": 28404, "##urized": 28405, "purification": 28406, "sock": 28407, "thorns": 28408, "thwarted": 28409, "jalan": 28410, "tiberius": 28411, "##taka": 28412, "saline": 28413, "##rito": 28414, "confidently": 28415, "khyber": 28416, "sculptors": 28417, "##ij": 28418, "brahms": 28419, "hammersmith": 28420, "inspectors": 28421, "battista": 28422, "fivb": 28423, "fragmentation": 28424, "hackney": 28425, "##uls": 28426, "arresting": 28427, "exercising": 28428, "antoinette": 28429, "bedfordshire": 28430, "##zily": 28431, "dyed": 28432, "##hema": 28433, "1656": 28434, "racetrack": 28435, "variability": 28436, "##tique": 28437, "1655": 28438, "austrians": 28439, "deteriorating": 28440, "madman": 28441, "theorists": 28442, "aix": 28443, "lehman": 28444, "weathered": 28445, "1731": 28446, "decreed": 28447, "eruptions": 28448, "1729": 28449, "flaw": 28450, "quinlan": 28451, "sorbonne": 28452, "flutes": 28453, "nunez": 28454, "1711": 28455, "adored": 28456, "downwards": 28457, "fable": 28458, "rasped": 28459, "1712": 28460, "moritz": 28461, "mouthful": 28462, "renegade": 28463, "shivers": 28464, "stunts": 28465, "dysfunction": 28466, "restrain": 28467, "translit": 28468, "327": 28469, "pancakes": 28470, "##avio": 28471, "##cision": 28472, "##tray": 28473, "351": 28474, "vial": 28475, "##lden": 28476, "bain": 28477, "##maid": 28478, "##oxide": 28479, "chihuahua": 28480, "malacca": 28481, "vimes": 28482, "##rba": 28483, "##rnier": 28484, "1664": 28485, "donnie": 28486, "plaques": 28487, "##ually": 28488, "337": 28489, "bangs": 28490, "floppy": 28491, "huntsville": 28492, "loretta": 28493, "nikolay": 28494, "##otte": 28495, "eater": 28496, "handgun": 28497, "ubiquitous": 28498, "##hett": 28499, "eras": 28500, "zodiac": 28501, "1634": 28502, "##omorphic": 28503, "1820s": 28504, "##zog": 28505, "cochran": 28506, "##bula": 28507, "##lithic": 28508, "warring": 28509, "##rada": 28510, "dalai": 28511, "excused": 28512, "blazers": 28513, "mcconnell": 28514, "reeling": 28515, "bot": 28516, "este": 28517, "##abi": 28518, "geese": 28519, "hoax": 28520, "taxon": 28521, "##bla": 28522, "guitarists": 28523, "##icon": 28524, "condemning": 28525, "hunts": 28526, "inversion": 28527, "moffat": 28528, "taekwondo": 28529, "##lvis": 28530, "1624": 28531, "stammered": 28532, "##rest": 28533, "##rzy": 28534, "sousa": 28535, "fundraiser": 28536, "marylebone": 28537, "navigable": 28538, "uptown": 28539, "cabbage": 28540, "daniela": 28541, "salman": 28542, "shitty": 28543, "whimper": 28544, "##kian": 28545, "##utive": 28546, "programmers": 28547, "protections": 28548, "rm": 28549, "##rmi": 28550, "##rued": 28551, "forceful": 28552, "##enes": 28553, "fuss": 28554, "##tao": 28555, "##wash": 28556, "brat": 28557, "oppressive": 28558, "reykjavik": 28559, "spartak": 28560, "ticking": 28561, "##inkles": 28562, "##kiewicz": 28563, "adolph": 28564, "horst": 28565, "maui": 28566, "protege": 28567, "straighten": 28568, "cpc": 28569, "landau": 28570, "concourse": 28571, "clements": 28572, "resultant": 28573, "##ando": 28574, "imaginative": 28575, "joo": 28576, "reactivated": 28577, "##rem": 28578, "##ffled": 28579, "##uising": 28580, "consultative": 28581, "##guide": 28582, "flop": 28583, "kaitlyn": 28584, "mergers": 28585, "parenting": 28586, "somber": 28587, "##vron": 28588, "supervise": 28589, "vidhan": 28590, "##imum": 28591, "courtship": 28592, "exemplified": 28593, "harmonies": 28594, "medallist": 28595, "refining": 28596, "##rrow": 28597, "##ка": 28598, "amara": 28599, "##hum": 28600, "780": 28601, "goalscorer": 28602, "sited": 28603, "overshadowed": 28604, "rohan": 28605, "displeasure": 28606, "secretive": 28607, "multiplied": 28608, "osman": 28609, "##orth": 28610, "engravings": 28611, "padre": 28612, "##kali": 28613, "##veda": 28614, "miniatures": 28615, "mis": 28616, "##yala": 28617, "clap": 28618, "pali": 28619, "rook": 28620, "##cana": 28621, "1692": 28622, "57th": 28623, "antennae": 28624, "astro": 28625, "oskar": 28626, "1628": 28627, "bulldog": 28628, "crotch": 28629, "hackett": 28630, "yucatan": 28631, "##sure": 28632, "amplifiers": 28633, "brno": 28634, "ferrara": 28635, "migrating": 28636, "##gree": 28637, "thanking": 28638, "turing": 28639, "##eza": 28640, "mccann": 28641, "ting": 28642, "andersson": 28643, "onslaught": 28644, "gaines": 28645, "ganga": 28646, "incense": 28647, "standardization": 28648, "##mation": 28649, "sentai": 28650, "scuba": 28651, "stuffing": 28652, "turquoise": 28653, "waivers": 28654, "alloys": 28655, "##vitt": 28656, "regaining": 28657, "vaults": 28658, "##clops": 28659, "##gizing": 28660, "digger": 28661, "furry": 28662, "memorabilia": 28663, "probing": 28664, "##iad": 28665, "payton": 28666, "rec": 28667, "deutschland": 28668, "filippo": 28669, "opaque": 28670, "seamen": 28671, "zenith": 28672, "afrikaans": 28673, "##filtration": 28674, "disciplined": 28675, "inspirational": 28676, "##merie": 28677, "banco": 28678, "confuse": 28679, "grafton": 28680, "tod": 28681, "##dgets": 28682, "championed": 28683, "simi": 28684, "anomaly": 28685, "biplane": 28686, "##ceptive": 28687, "electrode": 28688, "##para": 28689, "1697": 28690, "cleavage": 28691, "crossbow": 28692, "swirl": 28693, "informant": 28694, "##lars": 28695, "##osta": 28696, "afi": 28697, "bonfire": 28698, "spec": 28699, "##oux": 28700, "lakeside": 28701, "slump": 28702, "##culus": 28703, "##lais": 28704, "##qvist": 28705, "##rrigan": 28706, "1016": 28707, "facades": 28708, "borg": 28709, "inwardly": 28710, "cervical": 28711, "xl": 28712, "pointedly": 28713, "050": 28714, "stabilization": 28715, "##odon": 28716, "chests": 28717, "1699": 28718, "hacked": 28719, "ctv": 28720, "orthogonal": 28721, "suzy": 28722, "##lastic": 28723, "gaulle": 28724, "jacobite": 28725, "rearview": 28726, "##cam": 28727, "##erted": 28728, "ashby": 28729, "##drik": 28730, "##igate": 28731, "##mise": 28732, "##zbek": 28733, "affectionately": 28734, "canine": 28735, "disperse": 28736, "latham": 28737, "##istles": 28738, "##ivar": 28739, "spielberg": 28740, "##orin": 28741, "##idium": 28742, "ezekiel": 28743, "cid": 28744, "##sg": 28745, "durga": 28746, "middletown": 28747, "##cina": 28748, "customized": 28749, "frontiers": 28750, "harden": 28751, "##etano": 28752, "##zzy": 28753, "1604": 28754, "bolsheviks": 28755, "##66": 28756, "coloration": 28757, "yoko": 28758, "##bedo": 28759, "briefs": 28760, "slabs": 28761, "debra": 28762, "liquidation": 28763, "plumage": 28764, "##oin": 28765, "blossoms": 28766, "dementia": 28767, "subsidy": 28768, "1611": 28769, "proctor": 28770, "relational": 28771, "jerseys": 28772, "parochial": 28773, "ter": 28774, "##ici": 28775, "esa": 28776, "peshawar": 28777, "cavalier": 28778, "loren": 28779, "cpi": 28780, "idiots": 28781, "shamrock": 28782, "1646": 28783, "dutton": 28784, "malabar": 28785, "mustache": 28786, "##endez": 28787, "##ocytes": 28788, "referencing": 28789, "terminates": 28790, "marche": 28791, "yarmouth": 28792, "##sop": 28793, "acton": 28794, "mated": 28795, "seton": 28796, "subtly": 28797, "baptised": 28798, "beige": 28799, "extremes": 28800, "jolted": 28801, "kristina": 28802, "telecast": 28803, "##actic": 28804, "safeguard": 28805, "waldo": 28806, "##baldi": 28807, "##bular": 28808, "endeavors": 28809, "sloppy": 28810, "subterranean": 28811, "##ensburg": 28812, "##itung": 28813, "delicately": 28814, "pigment": 28815, "tq": 28816, "##scu": 28817, "1626": 28818, "##ound": 28819, "collisions": 28820, "coveted": 28821, "herds": 28822, "##personal": 28823, "##meister": 28824, "##nberger": 28825, "chopra": 28826, "##ricting": 28827, "abnormalities": 28828, "defective": 28829, "galician": 28830, "lucie": 28831, "##dilly": 28832, "alligator": 28833, "likened": 28834, "##genase": 28835, "burundi": 28836, "clears": 28837, "complexion": 28838, "derelict": 28839, "deafening": 28840, "diablo": 28841, "fingered": 28842, "champaign": 28843, "dogg": 28844, "enlist": 28845, "isotope": 28846, "labeling": 28847, "mrna": 28848, "##erre": 28849, "brilliance": 28850, "marvelous": 28851, "##ayo": 28852, "1652": 28853, "crawley": 28854, "ether": 28855, "footed": 28856, "dwellers": 28857, "deserts": 28858, "hamish": 28859, "rubs": 28860, "warlock": 28861, "skimmed": 28862, "##lizer": 28863, "870": 28864, "buick": 28865, "embark": 28866, "heraldic": 28867, "irregularities": 28868, "##ajan": 28869, "kiara": 28870, "##kulam": 28871, "##ieg": 28872, "antigen": 28873, "kowalski": 28874, "##lge": 28875, "oakley": 28876, "visitation": 28877, "##mbit": 28878, "vt": 28879, "##suit": 28880, "1570": 28881, "murderers": 28882, "##miento": 28883, "##rites": 28884, "chimneys": 28885, "##sling": 28886, "condemn": 28887, "custer": 28888, "exchequer": 28889, "havre": 28890, "##ghi": 28891, "fluctuations": 28892, "##rations": 28893, "dfb": 28894, "hendricks": 28895, "vaccines": 28896, "##tarian": 28897, "nietzsche": 28898, "biking": 28899, "juicy": 28900, "##duced": 28901, "brooding": 28902, "scrolling": 28903, "selangor": 28904, "##ragan": 28905, "352": 28906, "annum": 28907, "boomed": 28908, "seminole": 28909, "sugarcane": 28910, "##dna": 28911, "departmental": 28912, "dismissing": 28913, "innsbruck": 28914, "arteries": 28915, "ashok": 28916, "batavia": 28917, "daze": 28918, "kun": 28919, "overtook": 28920, "##rga": 28921, "##tlan": 28922, "beheaded": 28923, "gaddafi": 28924, "holm": 28925, "electronically": 28926, "faulty": 28927, "galilee": 28928, "fractures": 28929, "kobayashi": 28930, "##lized": 28931, "gunmen": 28932, "magma": 28933, "aramaic": 28934, "mala": 28935, "eastenders": 28936, "inference": 28937, "messengers": 28938, "bf": 28939, "##qu": 28940, "407": 28941, "bathrooms": 28942, "##vere": 28943, "1658": 28944, "flashbacks": 28945, "ideally": 28946, "misunderstood": 28947, "##jali": 28948, "##weather": 28949, "mendez": 28950, "##grounds": 28951, "505": 28952, "uncanny": 28953, "##iii": 28954, "1709": 28955, "friendships": 28956, "##nbc": 28957, "sacrament": 28958, "accommodated": 28959, "reiterated": 28960, "logistical": 28961, "pebbles": 28962, "thumped": 28963, "##escence": 28964, "administering": 28965, "decrees": 28966, "drafts": 28967, "##flight": 28968, "##cased": 28969, "##tula": 28970, "futuristic": 28971, "picket": 28972, "intimidation": 28973, "winthrop": 28974, "##fahan": 28975, "interfered": 28976, "339": 28977, "afar": 28978, "francoise": 28979, "morally": 28980, "uta": 28981, "cochin": 28982, "croft": 28983, "dwarfs": 28984, "##bruck": 28985, "##dents": 28986, "##nami": 28987, "biker": 28988, "##hner": 28989, "##meral": 28990, "nano": 28991, "##isen": 28992, "##ometric": 28993, "##pres": 28994, "##ан": 28995, "brightened": 28996, "meek": 28997, "parcels": 28998, "securely": 28999, "gunners": 29000, "##jhl": 29001, "##zko": 29002, "agile": 29003, "hysteria": 29004, "##lten": 29005, "##rcus": 29006, "bukit": 29007, "champs": 29008, "chevy": 29009, "cuckoo": 29010, "leith": 29011, "sadler": 29012, "theologians": 29013, "welded": 29014, "##section": 29015, "1663": 29016, "jj": 29017, "plurality": 29018, "xander": 29019, "##rooms": 29020, "##formed": 29021, "shredded": 29022, "temps": 29023, "intimately": 29024, "pau": 29025, "tormented": 29026, "##lok": 29027, "##stellar": 29028, "1618": 29029, "charred": 29030, "ems": 29031, "essen": 29032, "##mmel": 29033, "alarms": 29034, "spraying": 29035, "ascot": 29036, "blooms": 29037, "twinkle": 29038, "##abia": 29039, "##apes": 29040, "internment": 29041, "obsidian": 29042, "##chaft": 29043, "snoop": 29044, "##dav": 29045, "##ooping": 29046, "malibu": 29047, "##tension": 29048, "quiver": 29049, "##itia": 29050, "hays": 29051, "mcintosh": 29052, "travers": 29053, "walsall": 29054, "##ffie": 29055, "1623": 29056, "beverley": 29057, "schwarz": 29058, "plunging": 29059, "structurally": 29060, "m3": 29061, "rosenthal": 29062, "vikram": 29063, "##tsk": 29064, "770": 29065, "ghz": 29066, "##onda": 29067, "##tiv": 29068, "chalmers": 29069, "groningen": 29070, "pew": 29071, "reckon": 29072, "unicef": 29073, "##rvis": 29074, "55th": 29075, "##gni": 29076, "1651": 29077, "sulawesi": 29078, "avila": 29079, "cai": 29080, "metaphysical": 29081, "screwing": 29082, "turbulence": 29083, "##mberg": 29084, "augusto": 29085, "samba": 29086, "56th": 29087, "baffled": 29088, "momentary": 29089, "toxin": 29090, "##urian": 29091, "##wani": 29092, "aachen": 29093, "condoms": 29094, "dali": 29095, "steppe": 29096, "##3d": 29097, "##app": 29098, "##oed": 29099, "##year": 29100, "adolescence": 29101, "dauphin": 29102, "electrically": 29103, "inaccessible": 29104, "microscopy": 29105, "nikita": 29106, "##ega": 29107, "atv": 29108, "##cel": 29109, "##enter": 29110, "##oles": 29111, "##oteric": 29112, "##ы": 29113, "accountants": 29114, "punishments": 29115, "wrongly": 29116, "bribes": 29117, "adventurous": 29118, "clinch": 29119, "flinders": 29120, "southland": 29121, "##hem": 29122, "##kata": 29123, "gough": 29124, "##ciency": 29125, "lads": 29126, "soared": 29127, "##ה": 29128, "undergoes": 29129, "deformation": 29130, "outlawed": 29131, "rubbish": 29132, "##arus": 29133, "##mussen": 29134, "##nidae": 29135, "##rzburg": 29136, "arcs": 29137, "##ingdon": 29138, "##tituted": 29139, "1695": 29140, "wheelbase": 29141, "wheeling": 29142, "bombardier": 29143, "campground": 29144, "zebra": 29145, "##lices": 29146, "##oj": 29147, "##bain": 29148, "lullaby": 29149, "##ecure": 29150, "donetsk": 29151, "wylie": 29152, "grenada": 29153, "##arding": 29154, "##ης": 29155, "squinting": 29156, "eireann": 29157, "opposes": 29158, "##andra": 29159, "maximal": 29160, "runes": 29161, "##broken": 29162, "##cuting": 29163, "##iface": 29164, "##ror": 29165, "##rosis": 29166, "additive": 29167, "britney": 29168, "adultery": 29169, "triggering": 29170, "##drome": 29171, "detrimental": 29172, "aarhus": 29173, "containment": 29174, "jc": 29175, "swapped": 29176, "vichy": 29177, "##ioms": 29178, "madly": 29179, "##oric": 29180, "##rag": 29181, "brant": 29182, "##ckey": 29183, "##trix": 29184, "1560": 29185, "1612": 29186, "broughton": 29187, "rustling": 29188, "##stems": 29189, "##uder": 29190, "asbestos": 29191, "mentoring": 29192, "##nivorous": 29193, "finley": 29194, "leaps": 29195, "##isan": 29196, "apical": 29197, "pry": 29198, "slits": 29199, "substitutes": 29200, "##dict": 29201, "intuitive": 29202, "fantasia": 29203, "insistent": 29204, "unreasonable": 29205, "##igen": 29206, "##vna": 29207, "domed": 29208, "hannover": 29209, "margot": 29210, "ponder": 29211, "##zziness": 29212, "impromptu": 29213, "jian": 29214, "lc": 29215, "rampage": 29216, "stemming": 29217, "##eft": 29218, "andrey": 29219, "gerais": 29220, "whichever": 29221, "amnesia": 29222, "appropriated": 29223, "anzac": 29224, "clicks": 29225, "modifying": 29226, "ultimatum": 29227, "cambrian": 29228, "maids": 29229, "verve": 29230, "yellowstone": 29231, "##mbs": 29232, "conservatoire": 29233, "##scribe": 29234, "adherence": 29235, "dinners": 29236, "spectra": 29237, "imperfect": 29238, "mysteriously": 29239, "sidekick": 29240, "tatar": 29241, "tuba": 29242, "##aks": 29243, "##ifolia": 29244, "distrust": 29245, "##athan": 29246, "##zle": 29247, "c2": 29248, "ronin": 29249, "zac": 29250, "##pse": 29251, "celaena": 29252, "instrumentalist": 29253, "scents": 29254, "skopje": 29255, "##mbling": 29256, "comical": 29257, "compensated": 29258, "vidal": 29259, "condor": 29260, "intersect": 29261, "jingle": 29262, "wavelengths": 29263, "##urrent": 29264, "mcqueen": 29265, "##izzly": 29266, "carp": 29267, "weasel": 29268, "422": 29269, "kanye": 29270, "militias": 29271, "postdoctoral": 29272, "eugen": 29273, "gunslinger": 29274, "##ɛ": 29275, "faux": 29276, "hospice": 29277, "##for": 29278, "appalled": 29279, "derivation": 29280, "dwarves": 29281, "##elis": 29282, "dilapidated": 29283, "##folk": 29284, "astoria": 29285, "philology": 29286, "##lwyn": 29287, "##otho": 29288, "##saka": 29289, "inducing": 29290, "philanthropy": 29291, "##bf": 29292, "##itative": 29293, "geek": 29294, "markedly": 29295, "sql": 29296, "##yce": 29297, "bessie": 29298, "indices": 29299, "rn": 29300, "##flict": 29301, "495": 29302, "frowns": 29303, "resolving": 29304, "weightlifting": 29305, "tugs": 29306, "cleric": 29307, "contentious": 29308, "1653": 29309, "mania": 29310, "rms": 29311, "##miya": 29312, "##reate": 29313, "##ruck": 29314, "##tucket": 29315, "bien": 29316, "eels": 29317, "marek": 29318, "##ayton": 29319, "##cence": 29320, "discreet": 29321, "unofficially": 29322, "##ife": 29323, "leaks": 29324, "##bber": 29325, "1705": 29326, "332": 29327, "dung": 29328, "compressor": 29329, "hillsborough": 29330, "pandit": 29331, "shillings": 29332, "distal": 29333, "##skin": 29334, "381": 29335, "##tat": 29336, "##you": 29337, "nosed": 29338, "##nir": 29339, "mangrove": 29340, "undeveloped": 29341, "##idia": 29342, "textures": 29343, "##inho": 29344, "##500": 29345, "##rise": 29346, "ae": 29347, "irritating": 29348, "nay": 29349, "amazingly": 29350, "bancroft": 29351, "apologetic": 29352, "compassionate": 29353, "kata": 29354, "symphonies": 29355, "##lovic": 29356, "airspace": 29357, "##lch": 29358, "930": 29359, "gifford": 29360, "precautions": 29361, "fulfillment": 29362, "sevilla": 29363, "vulgar": 29364, "martinique": 29365, "##urities": 29366, "looting": 29367, "piccolo": 29368, "tidy": 29369, "##dermott": 29370, "quadrant": 29371, "armchair": 29372, "incomes": 29373, "mathematicians": 29374, "stampede": 29375, "nilsson": 29376, "##inking": 29377, "##scan": 29378, "foo": 29379, "quarterfinal": 29380, "##ostal": 29381, "shang": 29382, "shouldered": 29383, "squirrels": 29384, "##owe": 29385, "344": 29386, "vinegar": 29387, "##bner": 29388, "##rchy": 29389, "##systems": 29390, "delaying": 29391, "##trics": 29392, "ars": 29393, "dwyer": 29394, "rhapsody": 29395, "sponsoring": 29396, "##gration": 29397, "bipolar": 29398, "cinder": 29399, "starters": 29400, "##olio": 29401, "##urst": 29402, "421": 29403, "signage": 29404, "##nty": 29405, "aground": 29406, "figurative": 29407, "mons": 29408, "acquaintances": 29409, "duets": 29410, "erroneously": 29411, "soyuz": 29412, "elliptic": 29413, "recreated": 29414, "##cultural": 29415, "##quette": 29416, "##ssed": 29417, "##tma": 29418, "##zcz": 29419, "moderator": 29420, "scares": 29421, "##itaire": 29422, "##stones": 29423, "##udence": 29424, "juniper": 29425, "sighting": 29426, "##just": 29427, "##nsen": 29428, "britten": 29429, "calabria": 29430, "ry": 29431, "bop": 29432, "cramer": 29433, "forsyth": 29434, "stillness": 29435, "##л": 29436, "airmen": 29437, "gathers": 29438, "unfit": 29439, "##umber": 29440, "##upt": 29441, "taunting": 29442, "##rip": 29443, "seeker": 29444, "streamlined": 29445, "##bution": 29446, "holster": 29447, "schumann": 29448, "tread": 29449, "vox": 29450, "##gano": 29451, "##onzo": 29452, "strive": 29453, "dil": 29454, "reforming": 29455, "covent": 29456, "newbury": 29457, "predicting": 29458, "##orro": 29459, "decorate": 29460, "tre": 29461, "##puted": 29462, "andover": 29463, "ie": 29464, "asahi": 29465, "dept": 29466, "dunkirk": 29467, "gills": 29468, "##tori": 29469, "buren": 29470, "huskies": 29471, "##stis": 29472, "##stov": 29473, "abstracts": 29474, "bets": 29475, "loosen": 29476, "##opa": 29477, "1682": 29478, "yearning": 29479, "##glio": 29480, "##sir": 29481, "berman": 29482, "effortlessly": 29483, "enamel": 29484, "napoli": 29485, "persist": 29486, "##peration": 29487, "##uez": 29488, "attache": 29489, "elisa": 29490, "b1": 29491, "invitations": 29492, "##kic": 29493, "accelerating": 29494, "reindeer": 29495, "boardwalk": 29496, "clutches": 29497, "nelly": 29498, "polka": 29499, "starbucks": 29500, "##kei": 29501, "adamant": 29502, "huey": 29503, "lough": 29504, "unbroken": 29505, "adventurer": 29506, "embroidery": 29507, "inspecting": 29508, "stanza": 29509, "##ducted": 29510, "naia": 29511, "taluka": 29512, "##pone": 29513, "##roids": 29514, "chases": 29515, "deprivation": 29516, "florian": 29517, "##jing": 29518, "##ppet": 29519, "earthly": 29520, "##lib": 29521, "##ssee": 29522, "colossal": 29523, "foreigner": 29524, "vet": 29525, "freaks": 29526, "patrice": 29527, "rosewood": 29528, "triassic": 29529, "upstate": 29530, "##pkins": 29531, "dominates": 29532, "ata": 29533, "chants": 29534, "ks": 29535, "vo": 29536, "##400": 29537, "##bley": 29538, "##raya": 29539, "##rmed": 29540, "555": 29541, "agra": 29542, "infiltrate": 29543, "##ailing": 29544, "##ilation": 29545, "##tzer": 29546, "##uppe": 29547, "##werk": 29548, "binoculars": 29549, "enthusiast": 29550, "fujian": 29551, "squeak": 29552, "##avs": 29553, "abolitionist": 29554, "almeida": 29555, "boredom": 29556, "hampstead": 29557, "marsden": 29558, "rations": 29559, "##ands": 29560, "inflated": 29561, "334": 29562, "bonuses": 29563, "rosalie": 29564, "patna": 29565, "##rco": 29566, "329": 29567, "detachments": 29568, "penitentiary": 29569, "54th": 29570, "flourishing": 29571, "woolf": 29572, "##dion": 29573, "##etched": 29574, "papyrus": 29575, "##lster": 29576, "##nsor": 29577, "##toy": 29578, "bobbed": 29579, "dismounted": 29580, "endelle": 29581, "inhuman": 29582, "motorola": 29583, "tbs": 29584, "wince": 29585, "wreath": 29586, "##ticus": 29587, "hideout": 29588, "inspections": 29589, "sanjay": 29590, "disgrace": 29591, "infused": 29592, "pudding": 29593, "stalks": 29594, "##urbed": 29595, "arsenic": 29596, "leases": 29597, "##hyl": 29598, "##rrard": 29599, "collarbone": 29600, "##waite": 29601, "##wil": 29602, "dowry": 29603, "##bant": 29604, "##edance": 29605, "genealogical": 29606, "nitrate": 29607, "salamanca": 29608, "scandals": 29609, "thyroid": 29610, "necessitated": 29611, "##!": 29612, "##\"": 29613, "###": 29614, "##$": 29615, "##%": 29616, "##&": 29617, "##'": 29618, "##(": 29619, "##)": 29620, "##*": 29621, "##+": 29622, "##,": 29623, "##-": 29624, "##.": 29625, "##/": 29626, "##:": 29627, "##;": 29628, "##<": 29629, "##=": 29630, "##>": 29631, "##?": 29632, "##@": 29633, "##[": 29634, "##\\": 29635, "##]": 29636, "##^": 29637, "##_": 29638, "##`": 29639, "##{": 29640, "##|": 29641, "##}": 29642, "##~": 29643, "##¡": 29644, "##¢": 29645, "##£": 29646, "##¤": 29647, "##¥": 29648, "##¦": 29649, "##§": 29650, "##¨": 29651, "##©": 29652, "##ª": 29653, "##«": 29654, "##¬": 29655, "##®": 29656, "##±": 29657, "##´": 29658, "##µ": 29659, "##¶": 29660, "##·": 29661, "##º": 29662, "##»": 29663, "##¼": 29664, "##¾": 29665, "##¿": 29666, "##æ": 29667, "##ð": 29668, "##÷": 29669, "##þ": 29670, "##đ": 29671, "##ħ": 29672, "##ŋ": 29673, "##œ": 29674, "##ƒ": 29675, "##ɐ": 29676, "##ɑ": 29677, "##ɒ": 29678, "##ɔ": 29679, "##ɕ": 29680, "##ə": 29681, "##ɡ": 29682, "##ɣ": 29683, "##ɨ": 29684, "##ɪ": 29685, "##ɫ": 29686, "##ɬ": 29687, "##ɯ": 29688, "##ɲ": 29689, "##ɴ": 29690, "##ɹ": 29691, "##ɾ": 29692, "##ʀ": 29693, "##ʁ": 29694, "##ʂ": 29695, "##ʃ": 29696, "##ʉ": 29697, "##ʊ": 29698, "##ʋ": 29699, "##ʌ": 29700, "##ʎ": 29701, "##ʐ": 29702, "##ʑ": 29703, "##ʒ": 29704, "##ʔ": 29705, "##ʰ": 29706, "##ʲ": 29707, "##ʳ": 29708, "##ʷ": 29709, "##ʸ": 29710, "##ʻ": 29711, "##ʼ": 29712, "##ʾ": 29713, "##ʿ": 29714, "##ˈ": 29715, "##ˡ": 29716, "##ˢ": 29717, "##ˣ": 29718, "##ˤ": 29719, "##β": 29720, "##γ": 29721, "##δ": 29722, "##ε": 29723, "##ζ": 29724, "##θ": 29725, "##κ": 29726, "##λ": 29727, "##μ": 29728, "##ξ": 29729, "##ο": 29730, "##π": 29731, "##ρ": 29732, "##σ": 29733, "##τ": 29734, "##υ": 29735, "##φ": 29736, "##χ": 29737, "##ψ": 29738, "##ω": 29739, "##б": 29740, "##г": 29741, "##д": 29742, "##ж": 29743, "##з": 29744, "##м": 29745, "##п": 29746, "##с": 29747, "##у": 29748, "##ф": 29749, "##х": 29750, "##ц": 29751, "##ч": 29752, "##ш": 29753, "##щ": 29754, "##ъ": 29755, "##э": 29756, "##ю": 29757, "##ђ": 29758, "##є": 29759, "##і": 29760, "##ј": 29761, "##љ": 29762, "##њ": 29763, "##ћ": 29764, "##ӏ": 29765, "##ա": 29766, "##բ": 29767, "##գ": 29768, "##դ": 29769, "##ե": 29770, "##թ": 29771, "##ի": 29772, "##լ": 29773, "##կ": 29774, "##հ": 29775, "##մ": 29776, "##յ": 29777, "##ն": 29778, "##ո": 29779, "##պ": 29780, "##ս": 29781, "##վ": 29782, "##տ": 29783, "##ր": 29784, "##ւ": 29785, "##ք": 29786, "##־": 29787, "##א": 29788, "##ב": 29789, "##ג": 29790, "##ד": 29791, "##ו": 29792, "##ז": 29793, "##ח": 29794, "##ט": 29795, "##י": 29796, "##ך": 29797, "##כ": 29798, "##ל": 29799, "##ם": 29800, "##מ": 29801, "##ן": 29802, "##נ": 29803, "##ס": 29804, "##ע": 29805, "##ף": 29806, "##פ": 29807, "##ץ": 29808, "##צ": 29809, "##ק": 29810, "##ר": 29811, "##ש": 29812, "##ת": 29813, "##،": 29814, "##ء": 29815, "##ب": 29816, "##ت": 29817, "##ث": 29818, "##ج": 29819, "##ح": 29820, "##خ": 29821, "##ذ": 29822, "##ز": 29823, "##س": 29824, "##ش": 29825, "##ص": 29826, "##ض": 29827, "##ط": 29828, "##ظ": 29829, "##ع": 29830, "##غ": 29831, "##ـ": 29832, "##ف": 29833, "##ق": 29834, "##ك": 29835, "##و": 29836, "##ى": 29837, "##ٹ": 29838, "##پ": 29839, "##چ": 29840, "##ک": 29841, "##گ": 29842, "##ں": 29843, "##ھ": 29844, "##ہ": 29845, "##ے": 29846, "##अ": 29847, "##आ": 29848, "##उ": 29849, "##ए": 29850, "##क": 29851, "##ख": 29852, "##ग": 29853, "##च": 29854, "##ज": 29855, "##ट": 29856, "##ड": 29857, "##ण": 29858, "##त": 29859, "##थ": 29860, "##द": 29861, "##ध": 29862, "##न": 29863, "##प": 29864, "##ब": 29865, "##भ": 29866, "##म": 29867, "##य": 29868, "##र": 29869, "##ल": 29870, "##व": 29871, "##श": 29872, "##ष": 29873, "##स": 29874, "##ह": 29875, "##ा": 29876, "##ि": 29877, "##ी": 29878, "##ो": 29879, "##।": 29880, "##॥": 29881, "##ং": 29882, "##অ": 29883, "##আ": 29884, "##ই": 29885, "##উ": 29886, "##এ": 29887, "##ও": 29888, "##ক": 29889, "##খ": 29890, "##গ": 29891, "##চ": 29892, "##ছ": 29893, "##জ": 29894, "##ট": 29895, "##ড": 29896, "##ণ": 29897, "##ত": 29898, "##থ": 29899, "##দ": 29900, "##ধ": 29901, "##ন": 29902, "##প": 29903, "##ব": 29904, "##ভ": 29905, "##ম": 29906, "##য": 29907, "##র": 29908, "##ল": 29909, "##শ": 29910, "##ষ": 29911, "##স": 29912, "##হ": 29913, "##া": 29914, "##ি": 29915, "##ী": 29916, "##ে": 29917, "##க": 29918, "##ச": 29919, "##ட": 29920, "##த": 29921, "##ந": 29922, "##ன": 29923, "##ப": 29924, "##ம": 29925, "##ய": 29926, "##ர": 29927, "##ல": 29928, "##ள": 29929, "##வ": 29930, "##ா": 29931, "##ி": 29932, "##ு": 29933, "##ே": 29934, "##ை": 29935, "##ನ": 29936, "##ರ": 29937, "##ಾ": 29938, "##ක": 29939, "##ය": 29940, "##ර": 29941, "##ල": 29942, "##ව": 29943, "##ා": 29944, "##ก": 29945, "##ง": 29946, "##ต": 29947, "##ท": 29948, "##น": 29949, "##พ": 29950, "##ม": 29951, "##ย": 29952, "##ร": 29953, "##ล": 29954, "##ว": 29955, "##ส": 29956, "##อ": 29957, "##า": 29958, "##เ": 29959, "##་": 29960, "##།": 29961, "##ག": 29962, "##ང": 29963, "##ད": 29964, "##ན": 29965, "##པ": 29966, "##བ": 29967, "##མ": 29968, "##འ": 29969, "##ར": 29970, "##ལ": 29971, "##ས": 29972, "##မ": 29973, "##ა": 29974, "##ბ": 29975, "##გ": 29976, "##დ": 29977, "##ე": 29978, "##ვ": 29979, "##თ": 29980, "##ი": 29981, "##კ": 29982, "##ლ": 29983, "##მ": 29984, "##ნ": 29985, "##ო": 29986, "##რ": 29987, "##ს": 29988, "##ტ": 29989, "##უ": 29990, "##ᄀ": 29991, "##ᄂ": 29992, "##ᄃ": 29993, "##ᄅ": 29994, "##ᄆ": 29995, "##ᄇ": 29996, "##ᄉ": 29997, "##ᄊ": 29998, "##ᄋ": 29999, "##ᄌ": 30000, "##ᄎ": 30001, "##ᄏ": 30002, "##ᄐ": 30003, "##ᄑ": 30004, "##ᄒ": 30005, "##ᅡ": 30006, "##ᅢ": 30007, "##ᅥ": 30008, "##ᅦ": 30009, "##ᅧ": 30010, "##ᅩ": 30011, "##ᅪ": 30012, "##ᅭ": 30013, "##ᅮ": 30014, "##ᅯ": 30015, "##ᅲ": 30016, "##ᅳ": 30017, "##ᅴ": 30018, "##ᅵ": 30019, "##ᆨ": 30020, "##ᆫ": 30021, "##ᆯ": 30022, "##ᆷ": 30023, "##ᆸ": 30024, "##ᆼ": 30025, "##ᴬ": 30026, "##ᴮ": 30027, "##ᴰ": 30028, "##ᴵ": 30029, "##ᴺ": 30030, "##ᵀ": 30031, "##ᵃ": 30032, "##ᵇ": 30033, "##ᵈ": 30034, "##ᵉ": 30035, "##ᵍ": 30036, "##ᵏ": 30037, "##ᵐ": 30038, "##ᵒ": 30039, "##ᵖ": 30040, "##ᵗ": 30041, "##ᵘ": 30042, "##ᵣ": 30043, "##ᵤ": 30044, "##ᵥ": 30045, "##ᶜ": 30046, "##ᶠ": 30047, "##‐": 30048, "##‑": 30049, "##‒": 30050, "##–": 30051, "##—": 30052, "##―": 30053, "##‖": 30054, "##‘": 30055, "##’": 30056, "##‚": 30057, "##“": 30058, "##”": 30059, "##„": 30060, "##†": 30061, "##‡": 30062, "##•": 30063, "##…": 30064, "##‰": 30065, "##′": 30066, "##″": 30067, "##›": 30068, "##‿": 30069, "##⁄": 30070, "##⁰": 30071, "##ⁱ": 30072, "##⁴": 30073, "##⁵": 30074, "##⁶": 30075, "##⁷": 30076, "##⁸": 30077, "##⁹": 30078, "##⁻": 30079, "##ⁿ": 30080, "##₅": 30081, "##₆": 30082, "##₇": 30083, "##₈": 30084, "##₉": 30085, "##₊": 30086, "##₍": 30087, "##₎": 30088, "##ₐ": 30089, "##ₑ": 30090, "##ₒ": 30091, "##ₓ": 30092, "##ₕ": 30093, "##ₖ": 30094, "##ₗ": 30095, "##ₘ": 30096, "##ₚ": 30097, "##ₛ": 30098, "##ₜ": 30099, "##₤": 30100, "##₩": 30101, "##€": 30102, "##₱": 30103, "##₹": 30104, "##ℓ": 30105, "##№": 30106, "##ℝ": 30107, "##™": 30108, "##⅓": 30109, "##⅔": 30110, "##←": 30111, "##↑": 30112, "##→": 30113, "##↓": 30114, "##↔": 30115, "##↦": 30116, "##⇄": 30117, "##⇌": 30118, "##⇒": 30119, "##∂": 30120, "##∅": 30121, "##∆": 30122, "##∇": 30123, "##∈": 30124, "##∗": 30125, "##∘": 30126, "##√": 30127, "##∞": 30128, "##∧": 30129, "##∨": 30130, "##∩": 30131, "##∪": 30132, "##≈": 30133, "##≡": 30134, "##≤": 30135, "##≥": 30136, "##⊂": 30137, "##⊆": 30138, "##⊕": 30139, "##⊗": 30140, "##⋅": 30141, "##─": 30142, "##│": 30143, "##■": 30144, "##▪": 30145, "##●": 30146, "##★": 30147, "##☆": 30148, "##☉": 30149, "##♠": 30150, "##♣": 30151, "##♥": 30152, "##♦": 30153, "##♯": 30154, "##⟨": 30155, "##⟩": 30156, "##ⱼ": 30157, "##⺩": 30158, "##⺼": 30159, "##⽥": 30160, "##、": 30161, "##。": 30162, "##〈": 30163, "##〉": 30164, "##《": 30165, "##》": 30166, "##「": 30167, "##」": 30168, "##『": 30169, "##』": 30170, "##〜": 30171, "##あ": 30172, "##い": 30173, "##う": 30174, "##え": 30175, "##お": 30176, "##か": 30177, "##き": 30178, "##く": 30179, "##け": 30180, "##こ": 30181, "##さ": 30182, "##し": 30183, "##す": 30184, "##せ": 30185, "##そ": 30186, "##た": 30187, "##ち": 30188, "##っ": 30189, "##つ": 30190, "##て": 30191, "##と": 30192, "##な": 30193, "##に": 30194, "##ぬ": 30195, "##ね": 30196, "##の": 30197, "##は": 30198, "##ひ": 30199, "##ふ": 30200, "##へ": 30201, "##ほ": 30202, "##ま": 30203, "##み": 30204, "##む": 30205, "##め": 30206, "##も": 30207, "##や": 30208, "##ゆ": 30209, "##よ": 30210, "##ら": 30211, "##り": 30212, "##る": 30213, "##れ": 30214, "##ろ": 30215, "##を": 30216, "##ん": 30217, "##ァ": 30218, "##ア": 30219, "##ィ": 30220, "##イ": 30221, "##ウ": 30222, "##ェ": 30223, "##エ": 30224, "##オ": 30225, "##カ": 30226, "##キ": 30227, "##ク": 30228, "##ケ": 30229, "##コ": 30230, "##サ": 30231, "##シ": 30232, "##ス": 30233, "##セ": 30234, "##タ": 30235, "##チ": 30236, "##ッ": 30237, "##ツ": 30238, "##テ": 30239, "##ト": 30240, "##ナ": 30241, "##ニ": 30242, "##ノ": 30243, "##ハ": 30244, "##ヒ": 30245, "##フ": 30246, "##ヘ": 30247, "##ホ": 30248, "##マ": 30249, "##ミ": 30250, "##ム": 30251, "##メ": 30252, "##モ": 30253, "##ャ": 30254, "##ュ": 30255, "##ョ": 30256, "##ラ": 30257, "##リ": 30258, "##ル": 30259, "##レ": 30260, "##ロ": 30261, "##ワ": 30262, "##ン": 30263, "##・": 30264, "##ー": 30265, "##一": 30266, "##三": 30267, "##上": 30268, "##下": 30269, "##不": 30270, "##世": 30271, "##中": 30272, "##主": 30273, "##久": 30274, "##之": 30275, "##也": 30276, "##事": 30277, "##二": 30278, "##五": 30279, "##井": 30280, "##京": 30281, "##人": 30282, "##亻": 30283, "##仁": 30284, "##介": 30285, "##代": 30286, "##仮": 30287, "##伊": 30288, "##会": 30289, "##佐": 30290, "##侍": 30291, "##保": 30292, "##信": 30293, "##健": 30294, "##元": 30295, "##光": 30296, "##八": 30297, "##公": 30298, "##内": 30299, "##出": 30300, "##分": 30301, "##前": 30302, "##劉": 30303, "##力": 30304, "##加": 30305, "##勝": 30306, "##北": 30307, "##区": 30308, "##十": 30309, "##千": 30310, "##南": 30311, "##博": 30312, "##原": 30313, "##口": 30314, "##古": 30315, "##史": 30316, "##司": 30317, "##合": 30318, "##吉": 30319, "##同": 30320, "##名": 30321, "##和": 30322, "##囗": 30323, "##四": 30324, "##国": 30325, "##國": 30326, "##土": 30327, "##地": 30328, "##坂": 30329, "##城": 30330, "##堂": 30331, "##場": 30332, "##士": 30333, "##夏": 30334, "##外": 30335, "##大": 30336, "##天": 30337, "##太": 30338, "##夫": 30339, "##奈": 30340, "##女": 30341, "##子": 30342, "##学": 30343, "##宀": 30344, "##宇": 30345, "##安": 30346, "##宗": 30347, "##定": 30348, "##宣": 30349, "##宮": 30350, "##家": 30351, "##宿": 30352, "##寺": 30353, "##將": 30354, "##小": 30355, "##尚": 30356, "##山": 30357, "##岡": 30358, "##島": 30359, "##崎": 30360, "##川": 30361, "##州": 30362, "##巿": 30363, "##帝": 30364, "##平": 30365, "##年": 30366, "##幸": 30367, "##广": 30368, "##弘": 30369, "##張": 30370, "##彳": 30371, "##後": 30372, "##御": 30373, "##德": 30374, "##心": 30375, "##忄": 30376, "##志": 30377, "##忠": 30378, "##愛": 30379, "##成": 30380, "##我": 30381, "##戦": 30382, "##戸": 30383, "##手": 30384, "##扌": 30385, "##政": 30386, "##文": 30387, "##新": 30388, "##方": 30389, "##日": 30390, "##明": 30391, "##星": 30392, "##春": 30393, "##昭": 30394, "##智": 30395, "##曲": 30396, "##書": 30397, "##月": 30398, "##有": 30399, "##朝": 30400, "##木": 30401, "##本": 30402, "##李": 30403, "##村": 30404, "##東": 30405, "##松": 30406, "##林": 30407, "##森": 30408, "##楊": 30409, "##樹": 30410, "##橋": 30411, "##歌": 30412, "##止": 30413, "##正": 30414, "##武": 30415, "##比": 30416, "##氏": 30417, "##民": 30418, "##水": 30419, "##氵": 30420, "##氷": 30421, "##永": 30422, "##江": 30423, "##沢": 30424, "##河": 30425, "##治": 30426, "##法": 30427, "##海": 30428, "##清": 30429, "##漢": 30430, "##瀬": 30431, "##火": 30432, "##版": 30433, "##犬": 30434, "##王": 30435, "##生": 30436, "##田": 30437, "##男": 30438, "##疒": 30439, "##発": 30440, "##白": 30441, "##的": 30442, "##皇": 30443, "##目": 30444, "##相": 30445, "##省": 30446, "##真": 30447, "##石": 30448, "##示": 30449, "##社": 30450, "##神": 30451, "##福": 30452, "##禾": 30453, "##秀": 30454, "##秋": 30455, "##空": 30456, "##立": 30457, "##章": 30458, "##竹": 30459, "##糹": 30460, "##美": 30461, "##義": 30462, "##耳": 30463, "##良": 30464, "##艹": 30465, "##花": 30466, "##英": 30467, "##華": 30468, "##葉": 30469, "##藤": 30470, "##行": 30471, "##街": 30472, "##西": 30473, "##見": 30474, "##訁": 30475, "##語": 30476, "##谷": 30477, "##貝": 30478, "##貴": 30479, "##車": 30480, "##軍": 30481, "##辶": 30482, "##道": 30483, "##郎": 30484, "##郡": 30485, "##部": 30486, "##都": 30487, "##里": 30488, "##野": 30489, "##金": 30490, "##鈴": 30491, "##镇": 30492, "##長": 30493, "##門": 30494, "##間": 30495, "##阝": 30496, "##阿": 30497, "##陳": 30498, "##陽": 30499, "##雄": 30500, "##青": 30501, "##面": 30502, "##風": 30503, "##食": 30504, "##香": 30505, "##馬": 30506, "##高": 30507, "##龍": 30508, "##龸": 30509, "##fi": 30510, "##fl": 30511, "##!": 30512, "##(": 30513, "##)": 30514, "##,": 30515, "##-": 30516, "##.": 30517, "##/": 30518, "##:": 30519, "##?": 30520, "##~": 30521 } } } --- ### Spring Ai Client Chat/Src/Test/Resources/Bikes.Json (spring-ai-client-chat/src/test/resources/bikes.json) [ { "name": "E-Adrenaline 8.0 EX1", "shortDescription": "a versatile and comfortable e-MTB designed for adrenaline enthusiasts who want to explore all types of terrain. It features a powerful motor and advanced suspension to provide a smooth and responsive ride, with a variety of customizable settings to fit any rider's needs.", "description": "## Overview\r\nIt's right for you if...\r\nYou want to push your limits on challenging trails and terrain, with the added benefit of an electric assist to help you conquer steep climbs and rough terrain. You also want a bike with a comfortable and customizable fit, loaded with high-quality components and technology.\r\n\r\nThe tech you get\r\nA lightweight, full ADV Mountain Carbon frame with a customizable geometry, including an adjustable head tube and chainstay length. A powerful and efficient motor with a 375Wh battery that can assist up to 28 mph when it's on, and provides a smooth and seamless transition when it's off. A SRAM EX1 8-speed drivetrain, a RockShox Lyrik Ultimate fork, and a RockShox Super Deluxe Ultimate rear shock.\r\n\r\nThe final word\r\nOur E-Adrenaline 8.0 EX1 is the perfect bike for adrenaline enthusiasts who want to explore all types of terrain. It's versatile, comfortable, and loaded with advanced technology to provide a smooth and responsive ride, no matter where your adventures take you.\r\n\r\n\r\n## Features\r\nVersatile and customizable\r\nThe E-Adrenaline 8.0 EX1 features a customizable geometry, including an adjustable head tube and chainstay length, so you can fine-tune your ride to fit your needs and preferences. It also features a variety of customizable settings, including suspension tuning, motor assistance levels, and more.\r\n\r\nPowerful and efficient\r\nThe bike is equipped with a powerful and efficient motor that provides a smooth and seamless transition between human power and electric assist. It can assist up to 28 mph when it's on, and provides zero drag when it's off.\r\n\r\nAdvanced suspension\r\nThe E-Adrenaline 8.0 EX1 features a RockShox Lyrik Ultimate fork and a RockShox Super Deluxe Ultimate rear shock, providing advanced suspension technology to absorb shocks and bumps on any terrain. The suspension is also customizable to fit your riding style and preferences.\r\n\r\n\r\n## Specs\r\nFrameset\r\nFrame ADV Mountain Carbon main frame & stays, adjustable head tube and chainstay length, tapered head tube, Knock Block, Control Freak internal routing, Boost148, 150mm travel\r\nFork RockShox Lyrik Ultimate, DebonAir spring, Charger 2.1 RC2 damper, remote lockout, tapered steerer, 42mm offset, Boost110, 15mm Maxle Stealth, 160mm travel\r\nShock RockShox Super Deluxe Ultimate, DebonAir spring, Thru Shaft 3-position damper, 230x57.5mm\r\n\r\nWheels\r\nWheel front Bontrager Line Elite 30, ADV Mountain Carbon, Tubeless Ready, 6-bolt, Boost110, 15mm thru axle\r\nWheel rear Bontrager Line Elite 30, ADV Mountain Carbon, Tubeless Ready, 54T Rapid Drive, 6-bolt, Shimano MicroSpline freehub, Boost148, 12mm thru axle\r\nSkewer rear Bontrager Switch thru axle, removable lever\r\nTire Bontrager XR5 Team Issue, Tubeless Ready, Inner Strength sidewall, aramid bead, 120tpi, 29x2.50''\r\nTire part Bontrager TLR sealant, 6oz\r\n\r\nDrivetrain\r\nShifter SRAM EX1, 8 speed\r\nRear derailleur SRAM EX1, 8 speed\r\nCrank Bosch Performance CX, magnesium motor body, 250 watt, 75 Nm torque\r\nChainring SRAM EX1, 18T, steel\r\nCassette SRAM EX1, 11-48, 8 speed\r\nChain SRAM EX1, 8 speed\r\n\r\nComponents\r\nSaddle Bontrager Arvada, hollow chromoly rails, 138mm width\r\nSeatpost Bontrager Line Elite Dropper, internal routing, 31.6mm\r\nHandlebar Bontrager Line Pro, ADV Carbon, 35mm, 27.5mm rise, 780mm width\r\nGrips Bontrager XR Trail Elite, alloy lock-on\r\nStem Bontrager Line Pro, 35mm, Knock Block, Blendr compatible, 0 degree, 50mm length\r\nHeadset Knock Block Integrated, 62-degree radius, cartridge bearing, 1-1\/8'' top, 1.5'' bottom\r\nBrake SRAM G2 RSC hydraulic disc, carbon levers\r\nBrake rotor SRAM Centerline, centerlock, round edge, 200mm\r\n\r\nAccessories\r\nE-bike system Bosch Performance CX, magnesium motor body, 250 watt, 75 Nm torque\r\nBattery Bosch PowerTube 625, 625Wh\r\nCharger Bosch 4A standard charger\r\nController Bosch Kiox with Anti-theft solution, Bluetooth connectivity, 1.9'' display\r\nTool Bontrager Switch thru axle, removable lever\r\n\r\nWeight\r\nWeight M - 20.25 kg \/ 44.6 lbs (with TLR sealant, no tubes)\r\nWeight limit This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\r\n\r\n## Sizing & fit\r\n\r\n| Size | Rider Height | Inseam |\r\n|:----:|:------------------------:|:--------------------:|\r\n| S | 155 - 170 cm 5'1\" - 5'7\" | 73 - 80 cm 29\" - 31.5\" |\r\n| M | 163 - 178 cm 5'4\" - 5'10\" | 77 - 83 cm 30.5\" - 32.5\" |\r\n| L | 176 - 191 cm 5'9\" - 6'3\" | 83 - 89 cm 32.5\" - 35\" |\r\n| XL | 188 - 198 cm 6'2\" - 6'6\" | 88 - 93 cm 34.5\" - 36.5\" |\r\n\r\n\r\n## Geometry\r\n\r\nAll measurements provided in cm unless otherwise noted.\r\nSizing table\r\n| Frame size letter | S | M | L | XL |\r\n|---------------------------|-------|-------|-------|-------|\r\n| Actual frame size | 15.8 | 17.8 | 19.8 | 21.8 |\r\n| Wheel size | 29\" | 29\" | 29\" | 29\" |\r\n| A \u2014 Seat tube | 40.0 | 42.5 | 47.5 | 51.0 |\r\n| B \u2014 Seat tube angle | 72.5\u00B0 | 72.8\u00B0 | 73.0\u00B0 | 73.0\u00B0 |\r\n| C \u2014 Head tube length | 9.5 | 10.5 | 11.0 | 11.5 |\r\n| D \u2014 Head angle | 67.8\u00B0 | 67.8\u00B0 | 67.8\u00B0 | 67.8\u00B0 |\r\n| E \u2014 Effective top tube | 59.0 | 62.0 | 65.0 | 68.0 |\r\n| F \u2014 Bottom bracket height | 32.5 | 32.5 | 32.5 | 32.5 |\r\n| G \u2014 Bottom bracket drop | 5.5 | 5.5 | 5.5 | 5.5 |\r\n| H \u2014 Chainstay length | 45.0 | 45.0 | 45.0 | 45.0 |\r\n| I \u2014 Offset | 4.5 | 4.5 | 4.5 | 4.5 |\r\n| J \u2014 Trail | 11.0 | 11.0 | 11.0 | 11.0 |\r\n| K \u2014 Wheelbase | 113.0 | 117.0 | 120.0 | 123.0 |\r\n| L \u2014 Standover | 77.0 | 77.0 | 77.0 | 77.0 |\r\n| M \u2014 Frame reach | 41.0 | 44.5 | 47.5 | 50.0 |\r\n| N \u2014 Frame stack | 61.0 | 62.0 | 62.5 | 63.0 |", "price": 1499.99, "tags": [ "bicycle" ] }, { "name": "Enduro X Pro", "shortDescription": "The Enduro X Pro is the ultimate mountain bike for riders who demand the best. With its full carbon frame and top-of-the-line components, this bike is ready to tackle any trail, from technical downhill descents to grueling uphill climbs.", "text": "## Overview\nIt's right for you if...\nYou're an experienced mountain biker who wants a high-performance bike that can handle any terrain. You want a bike with the best components available, including a full carbon frame, suspension system, and hydraulic disc brakes.\n\nThe tech you get\nOur top-of-the-line full carbon frame with aggressive geometry and a slack head angle for maximum control. It's equipped with a Fox Factory suspension system with 170mm of travel in the front and 160mm in the rear, a Shimano XTR 12-speed drivetrain, and hydraulic disc brakes for maximum stopping power. The bike also features a dropper seatpost for easy adjustments on the fly.\n\nThe final word\nThe Enduro X Pro is the ultimate mountain bike for riders who demand the best. With its full carbon frame, top-of-the-line components, and aggressive geometry, this bike is ready to take on any trail. Whether you're a seasoned pro or just starting out, the Enduro X Pro will help you take your riding to the next level.\n\n## Features\nFull carbon frame\nAggressive geometry with a slack head angle\nFox Factory suspension system with 170mm of travel in the front and 160mm in the rear\nShimano XTR 12-speed drivetrain\nHydraulic disc brakes for maximum stopping power\nDropper seatpost for easy adjustments on the fly\n\n## Specifications\nFrameset\nFrame\tFull carbon frame\nFork\tFox Factory suspension system with 170mm of travel\nRear suspension\tFox Factory suspension system with 160mm of travel\n\nWheels\nWheel size\t27.5\" or 29\"\nTires\tTubeless-ready Maxxis tires\n\nDrivetrain\nShifters\tShimano XTR 12-speed\nFront derailleur\tN/A\nRear derailleur\tShimano XTR\nCrankset\tShimano XTR\nCassette\tShimano XTR 12-speed\nChain\tShimano XTR\n\nComponents\nBrakes\tHydraulic disc brakes\nHandlebar\tAlloy handlebar\nStem\tAlloy stem\nSeatpost\tDropper seatpost\n\nAccessories\nPedals\tNot included\n\nWeight\nWeight\tApproximately 27-29 lbs\n\n## Sizing\n| Size | Rider Height |\n|:----:|:-------------------------:|\n| S | 5'4\" - 5'8\" (162-172cm) |\n| M | 5'8\" - 5'11\" (172-180cm) |\n| L | 5'11\" - 6'3\" (180-191cm) |\n| XL | 6'3\" - 6'6\" (191-198cm) |\n\n## Geometry\n| Size | S | M | L | XL |\n|:----:|:---------------:|:---------------:|:-----------------:|:---------------:|\n| A - Seat tube length | 390mm | 425mm | 460mm | 495mm |\n| B - Effective top tube length | 585mm | 610mm | 635mm | 660mm |\n| C - Head tube angle | 65.5° | 65.5° | 65.5° | 65.5° |\n| D - Seat tube angle | 76° | 76° | 76° | 76° |\n| E - Chainstay length | 435mm | 435mm | 435mm | 435mm |\n| F - Head tube length | 100mm | 110mm | 120mm | 130mm |\n| G - BB drop | 20mm | 20mm | 20mm | 20mm |\n| H - Wheelbase | 1155mm | 1180mm | 1205mm | 1230mm |\n| I - Standover height | 780mm | 800mm | 820mm | 840mm |\n| J - Reach | 425mm | 450mm | 475mm | 500mm |\n| K - Stack | 610mm | 620mm | 630mm | 640mm |", "price": 599.99, "tags": [ "bicycle" ] }, { "name": "Blaze X1", "shortDescription": "Blaze X1 is a high-performance road bike that offers superior speed and agility, making it perfect for competitive racing or fast-paced group rides. The bike features a lightweight carbon frame, aerodynamic tube shapes, a 12-speed Shimano Ultegra drivetrain, and hydraulic disc brakes for precise stopping power. With its sleek design and cutting-edge technology, Blaze X1 is a bike that is built to perform and dominate on any road.", "description": "## Overview\nIt's right for you if...\nYou're a competitive road cyclist or an enthusiast who enjoys fast-paced group rides. You want a bike that is lightweight, agile, and delivers exceptional speed.\n\nThe tech you get\nBlaze X1 features a lightweight carbon frame with a tapered head tube and aerodynamic tube shapes for maximum speed and efficiency. The bike is equipped with a 12-speed Shimano Ultegra drivetrain for smooth and precise shifting, Shimano hydraulic disc brakes for powerful and reliable stopping power, and Bontrager Aeolus Elite 35 carbon wheels for increased speed and agility.\n\nThe final word\nBlaze X1 is a high-performance road bike that is designed to deliver exceptional speed and agility. With its cutting-edge technology and top-of-the-line components, it's a bike that is built to perform and dominate on any road.\n\n## Features\nSpeed and efficiency\nBlaze X1's lightweight carbon frame and aerodynamic tube shapes offer maximum speed and efficiency, allowing you to ride faster and farther with ease.\n\nPrecision stopping power\nShimano hydraulic disc brakes provide precise and reliable stopping power, even in wet or muddy conditions.\n\nAgility and control\nBontrager Aeolus Elite 35 carbon wheels make Blaze X1 incredibly agile and responsive, allowing you to navigate tight turns and corners with ease.\n\nSmooth and precise shifting\nThe 12-speed Shimano Ultegra drivetrain offers smooth and precise shifting, so you can easily find the right gear for any terrain.\n\n## Specifications\nFrameset\nFrame\tADV Carbon, tapered head tube, BB90, direct mount rim brakes, internal cable routing, DuoTrap S compatible, 130x9mm QR\nFork\tADV Carbon, tapered steerer, direct mount rim brakes, internal brake routing, 100x9mm QR\n\nWheels\nWheel front\tBontrager Aeolus Elite 35, ADV Carbon, Tubeless Ready, 35mm rim depth, 100x9mm QR\nWheel rear\tBontrager Aeolus Elite 35, ADV Carbon, Tubeless Ready, 35mm rim depth, Shimano 11-speed freehub, 130x9mm QR\nTire front\tBontrager R3 Hard-Case Lite, aramid bead, 120 tpi, 700x25c\nTire rear\tBontrager R3 Hard-Case Lite, aramid bead, 120 tpi, 700x25c\nMax tire size\t25c Bontrager tires (with at least 4mm of clearance to frame)\n\nDrivetrain\nShifter\tShimano Ultegra R8020, 12 speed\nFront derailleur\tShimano Ultegra R8000, braze-on\nRear derailleur\tShimano Ultegra R8000, short cage, 30T max cog\nCrank\tSize: 50, 52, 54\nShimano Ultegra R8000, 50/34 (compact), 170mm length\nSize: 56, 58, 60, 62\nShimano Ultegra R8000, 50/34 (compact), 172.5mm length\nBottom bracket\tBB90, Shimano press-fit\nCassette\tShimano Ultegra R8000, 11-30, 12 speed\nChain\tShimano Ultegra HG701, 12 speed\n\nComponents\nSaddle\tBontrager Montrose Elite, titanium rails, 138mm width\nSeatpost\tBontrager carbon seatmast cap, 20mm offset\nHandlebar\tBontrager Elite Aero VR-CF, alloy, 31.8mm, internal cable routing, 40cm width\nGrips\tBontrager Supertack Perf tape\nStem\tBontrager Elite, 31.8mm, Blendr-compatible, 7 degree, 80mm length\nBrake Shimano Ultegra hydraulic disc brake\n\nWeight\nWeight\t56 - 8.91 kg / 19.63 lbs (with tubes)\nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 275 pounds (125 kg).\n\n## Sizing\n| Size | Rider height |\n|------|-------------|\n| 50 | 162-166cm |\n| 52 | 165-170cm |\n| 54 | 168-174cm |\n| 56 | 174-180cm |\n| 58 | 179-184cm |\n| 60 | 184-189cm |\n| 62 | 189-196cm |\n\n## Geometry\n| Frame size | 50cm | 52cm | 54cm | 56cm | 58cm | 60cm | 62cm |\n|------------|-------|-------|-------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c | 700c | 700c | 700c |\n| A - Seat tube | 443mm | 460mm | 478mm | 500mm | 520mm | 540mm | 560mm |\n| B - Seat tube angle | 74.1° | 73.9° | 73.7° | 73.4° | 73.2° | 73.0° | 72.8° |\n| C - Head tube length | 100mm | 110mm | 130mm | 150mm | 170mm | 190mm | 210mm |\n| D - Head angle | 71.4° | 72.0° | 72.5° | 73.0° | 73.3° | 73.6° | 73.8° |\n| E - Effective top tube | 522mm | 535mm | 547mm | 562mm | 577mm | 593mm | 610mm |\n| F - Bottom bracket height | 268mm | 268mm | 268mm | 268mm | 268mm | 268mm | 268mm |\n| G - Bottom bracket drop | 69mm | 69mm | 69mm | 69mm | 69mm | 69mm | 69mm |\n| H - Chainstay length | 410mm | 410mm | 410mm | 410mm | 410mm | 410mm | 410mm |\n| I - Offset | 50mm | 50mm | 50mm | 50mm | 50mm | 50mm | 50mm |\n| J - Trail | 65mm | 62mm | 59mm | 56mm | 55mm | 53mm | 52mm |\n| K - Wheelbase | 983mm | 983mm | 990mm | 1005mm | 1019mm | 1036mm | 1055mm |\n| L - Standover | 741mm | 765mm | 787mm | 806mm | 825mm | 847mm | 869mm |", "price": 799.99, "tags": [ "bicycle", "mountain bike" ] }, { "name": "Celerity X5", "shortDescription": "Celerity X5 is a versatile and reliable road bike that is designed for experienced and amateur riders alike. It's designed to provide smooth and comfortable rides over long distances. With an ultra-lightweight and responsive carbon fiber frame, Shimano 105 groupset, hydraulic disc brakes, and 28mm wide tires, this bike ensures efficient power transfer, precise handling, and superior stopping power.", "description": "## Overview\n\nIt's right for you if... \nYou are looking for a high-performance road bike that offers a perfect balance of speed, comfort, and control. You enjoy long-distance rides and need a bike that is designed to handle various road conditions with ease. You also appreciate the latest technology and reliable components that make your riding experience more enjoyable.\n\nThe tech you get \nCelerity X5 is equipped with a full carbon fiber frame that ensures maximum strength and durability while keeping the weight down. It features a Shimano 105 groupset with 11-speed gearing for precise and efficient shifting. Hydraulic disc brakes offer superior stopping power, and 28mm wide tires provide comfort and stability on various road surfaces. Internal cable routing enhances the bike's sleek appearance.\n\nThe final word \nIf you are looking for a high-performance road bike that offers comfort, speed, and control, Celerity X5 is the perfect choice. With its lightweight carbon fiber frame, reliable components, and advanced technology, this bike is designed to help you enjoy long-distance rides with ease.\n\n## Features \n\nLightweight and responsive \nCelerity X5 comes with a full carbon fiber frame that is not only lightweight but also responsive, providing excellent handling and control.\n\nHydraulic disc brakes \nThis bike is equipped with hydraulic disc brakes that provide superior stopping power in all weather conditions, ensuring your safety and confidence on the road.\n\nComfortable rides \nThe 28mm wide tires and carbon seat post provide ample cushioning, ensuring a smooth and comfortable ride over long distances.\n\nSleek appearance \nThe bike's internal cable routing enhances its sleek appearance while also protecting the cables from the elements, ensuring smooth shifting for longer periods.\n\n## Specifications \n\nFrameset \nFrame\tCelerity X5 Full Carbon Fiber Frame, Internal Cable Routing, Tapered Headtube, Press Fit Bottom Bracket, 12x142mm Thru-Axle \nFork\tCelerity X5 Full Carbon Fiber Fork, Internal Brake Routing, 12x100mm Thru-Axle \n\nWheels \nWheelset\tAlexRims CXD7 Wheelset \nTire\tSchwalbe Durano Plus 700x28mm \nInner Tubes\tSchwalbe SV15 700x18-28mm \nSkewers\tCelerity X5 Thru-Axle Skewers \n\nDrivetrain \nShifter\tShimano 105 R7025 Hydraulic Disc Shifters \nFront Derailleur\tShimano 105 R7000 \nRear Derailleur\tShimano 105 R7000 \nCrankset\tShimano 105 R7000 50-34T \nBottom Bracket\tShimano BB72-41B \nCassette\tShimano 105 R7000 11-30T \nChain\tShimano HG601 11-Speed Chain \n\nComponents \nSaddle\tSelle Royal Asphalt Saddle \nSeatpost\tCelerity X5 Carbon Seatpost \nHandlebar\tCelerity X5 Compact Handlebar \nStem\tCelerity X5 Aluminum Stem \nHeadset\tFSA Orbit IS-2 \n\nBrakes \nBrakes\tShimano 105 R7025 Hydraulic Disc Brakes \nRotors\tShimano SM-RT70 160mm Rotors \n\nAccessories \nPedals\tCelerity X5 Road Pedals \n\nWeight \nWeight\t8.2 kg / 18.1 lbs \nWeight Limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 120 kg (265 lbs).\n\n## Sizing \n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| 49 | 155 - 162 cm 5'1\" - 5'4\" | 71 - 76 cm 28\" - 30\" |\n| 52 | 162 - 170 cm 5'4\" - 5'7\" | 74 - 79 cm 29\" - 31\" |\n| 54 | 170 - 178 cm 5'7\" - 5'10\" | 77 - 83 cm 30\" - 32\" |\n| 56 | 178 - 185 cm 5'10\" - 6'1\" | 82 - 88 cm 32\" - 34\" |\n| 58 | 185 - 193 cm 6'1\" - 6'4\" | 86 - 92 cm 34\" - 36\" |\n| 61 | 193 - 200 cm 6'4\" - 6'7\" | 90 - 95 cm 35\" - 37\" |\n\n## Geometry \n| Frame size number | 49 cm | 52 cm | 54 cm | 56 cm | 58 cm | 61 cm |\n|---------------------------------------|-------|-------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c | 700c | 700c |\n| A — Seat tube | 47.5 | 50.0 | 52.0 | 54.0 | 56.0 | 58.5 |\n| B — Seat tube angle | 75.0° | 74.5° | 74.0° | 73.5° | 73.0° | 72.5° |\n| C — Head tube length | 12.0 | 14.5 | 16.5 | 18.5 | 20.5 | 23.5 |\n| D — Head angle | 70.0° | 71.0° | 71.5° | 72.0° | 72.5° | 72.5° |\n| E — Effective top tube | 52.5 | 53.5 | 54.5 | 56.0 | 57.5 | 59.5 |\n| G — Bottom bracket drop | 7.0 | 7.0 | 7.0 | 7.0 | 7.0 | 7.0 |\n| H — Chainstay length | 41.5 | 41.5 | 41.5 | 41.5 | 41.5 | 41.5 |\n| K — Wheelbase | 98.4 | 98.9 | 99.8 | 100.8 | 101.7 | 103.6 |\n| L — Standover | 72.0 | 74.0 | 76.0 | 78.0 | 80.0 | 82.0 |\n| M — Frame reach | 36.2 | 36.8 | 37.3 | 38.1 | 38.6 | 39.4 |\n| N — Frame stack | 52.0 | 54.3 | 56.2 | 58.1 | 59.8 | 62.4 |\n| Saddle rail height min | 67.0 | 69.5 | 71.5 | 74.0 | 76.0 | 78.0 |\n| Saddle rail height max | 75.0 | 77.5 | 79.5 | 82.0 | 84.0 | 86.0 |", "price": 399.99, "tags": [ "bicycle", "city bike" ] }, { "name": "Velocity V8", "shortDescription": "Velocity V8 is a high-performance road bike that is designed to deliver speed, agility, and control on the road. With its lightweight aluminum frame, carbon fiber fork, Shimano Tiagra groupset, and hydraulic disc brakes, this bike is perfect for experienced riders who are looking for a fast and responsive bike that can handle various road conditions.", "description": "## Overview\n\nIt's right for you if... \nYou are an experienced rider who is looking for a high-performance road bike that is lightweight, agile, and responsive. You want a bike that can handle long-distance rides, steep climbs, and fast descents with ease. You also appreciate the latest technology and reliable components that make your riding experience more enjoyable.\n\nThe tech you get \nVelocity V8 features a lightweight aluminum frame with a carbon fiber fork that ensures a comfortable ride without sacrificing stiffness and power transfer. It comes with a Shimano Tiagra groupset with 10-speed gearing for precise and efficient shifting. Hydraulic disc brakes offer superior stopping power in all weather conditions, while 28mm wide tires provide comfort and stability on various road surfaces. Internal cable routing enhances the bike's sleek appearance.\n\nThe final word \nIf you are looking for a high-performance road bike that is lightweight, fast, and responsive, Velocity V8 is the perfect choice. With its lightweight aluminum frame, reliable components, and advanced technology, this bike is designed to help you enjoy fast and comfortable rides on the road.\n\n## Features \n\nLightweight and responsive \nVelocity V8 comes with a lightweight aluminum frame that is not only lightweight but also responsive, providing excellent handling and control.\n\nHydraulic disc brakes \nThis bike is equipped with hydraulic disc brakes that provide superior stopping power in all weather conditions, ensuring your safety and confidence on the road.\n\nComfortable rides \nThe 28mm wide tires and carbon fork provide ample cushioning, ensuring a smooth and comfortable ride over long distances.\n\nSleek appearance \nThe bike's internal cable routing enhances its sleek appearance while also protecting the cables from the elements, ensuring smooth shifting for longer periods.\n\n## Specifications \n\nFrameset \nFrame\tVelocity V8 Aluminum Frame, Internal Cable Routing, Tapered Headtube, Press Fit Bottom Bracket, 12x142mm Thru-Axle \nFork\tVelocity V8 Carbon Fiber Fork, Internal Brake Routing, 12x100mm Thru-Axle \n\nWheels \nWheelset\tAlexRims CXD7 Wheelset \nTire\tSchwalbe Durano Plus 700x28mm \nInner Tubes\tSchwalbe SV15 700x18-28mm \nSkewers\tVelocity V8 Thru-Axle Skewers \n\nDrivetrain \nShifter\tShimano Tiagra Hydraulic Disc Shifters \nFront Derailleur\tShimano Tiagra \nRear Derailleur\tShimano Tiagra \nCrankset\tShimano Tiagra 50-34T \nBottom Bracket\tShimano BB-RS500-PB \nCassette\tShimano Tiagra 11-32T \nChain\tShimano HG54 10-Speed Chain \n\nComponents \nSaddle\tVelocity V8 Saddle \nSeatpost\tVelocity V8 Aluminum Seatpost \nHandlebar\tVelocity V8 Compact Handlebar \nStem\tVelocity V8 Aluminum Stem \nHeadset\tFSA Orbit IS-2 \n\nBrakes \nBrakes\tShimano Tiagra Hydraulic Disc Brakes \nRotors\tShimano SM-RT64 160mm Rotors \n\nAccessories \nPedals\tVelocity V8 Road Pedals \n\nWeight \nWeight\t9.4 kg / 20.7 lbs \nWeight Limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 120 kg (265 lbs).\n\n## Sizing \n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| 49 | 155 - 162 cm 5'1\" - 5'4\" | 71 - 76 cm 28\" - 30\" |\n| 52 | 162 - 170 cm 5'4\" - 5'7\" | 74 - 79 cm 29\" - 31\" |\n| 54 | 170 - 178 cm 5'7\" - 5'10\" | 77 - 83 cm 30\" - 32\" |\n| 56 | 178 - 185 cm 5'10\" - 6'1\" | 82 - 88 cm 32\" - 34\" |\n| 58 | 185 - 193 cm 6'1\" - 6'4\" | 86 - 92 cm 34\" - 36\" |\n| 61 | 193 - 200 cm 6'4\" - 6'7\" | 90 - 95 cm 35\" - 37\" |\n\n## Geometry \n| Frame size number | 49 cm | 52 cm | 54 cm | 56 cm | 58 cm | 61 cm |\n|---------------------------------------|-------|-------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c | 700c | 700c |\n| A — Seat tube | 47.5 | 50.0 | 52.0 | 54.0 | 56.0 | 58.5 |\n| B — Seat tube angle | 75.0° | 74.5° | 74.0° | 73.5° | 73.0° | 72.5° |\n| C — Head tube length | 12.0 | 14.5 | 16.5 | 18.5 | 20.5 | 23.5 |\n| D — Head angle | 70.0° | 71.0° | 71.5° | 72.0° | 72.5° | 72.5° |\n| E — Effective top tube | 52.5 | 53.5 | 54.5 | 56.0 | 57.5 | 59.5 |\n| G — Bottom bracket drop | 7.0 | 7.0 | 7.0 | 7.0 | 7.0 | 7.0 |\n| H — Chainstay length | 41.5 | 41.5 | 41.5 | 41.5 | 41.5 | 41.5 |\n| K — Wheelbase | 98.4 | 98.9 | 99.8 | 100.8 | 101.7 | 103.6 |\n| L — Standover | 72.0 | 74.0 | 76.0 | 78.0 | 80.0 | 82.0 |\n| M — Frame reach | 36.2 | 36.8 | 37.3 | 38.1 | 38.6 | 39.4 |\n| N — Frame stack | 52.0 | 54.3 | 56.2 | 58.1 | 59.8 | 62.4 |\n| Saddle rail height min | 67.0 | 69.5 | 71.5 | 74.0 | 76.0 | 78.0 |\n| Saddle rail height max | 75.0 | 77.5 | 79.5 | 82.0 | 84.0 | 86.0 |", "price": 1899.99, "tags": [ "bicycle", "electric bike" ] }, { "name": "VeloCore X9 eMTB", "shortDescription": "The VeloCore X9 eMTB is a light, agile and versatile electric mountain bike designed for adventure and performance. Its purpose-built frame and premium components offer an exhilarating ride experience on both technical terrain and smooth singletrack.", "description": "## Overview\nIt's right for you if...\nYou love exploring new trails and testing your limits on challenging terrain. You want an electric mountain bike that offers power when you need it, without sacrificing performance or agility. You're looking for a high-quality bike with top-notch components and a sleek design.\n\nThe tech you get\nA lightweight, full carbon frame with custom geometry, a 140mm RockShox Pike Ultimate fork with Charger 2.1 damper, and a Fox Float DPS Performance shock. A Shimano STEPS E8000 motor and 504Wh battery that provide up to 62 miles of range and 20 mph assistance. A Shimano XT 12-speed drivetrain, Shimano SLX brakes, and DT Swiss wheels.\n\nThe final word\nThe VeloCore X9 eMTB delivers power and agility in equal measure. It's a versatile and capable electric mountain bike that can handle any trail with ease. With premium components, a custom carbon frame, and a sleek design, this bike is built for adventure.\n\n## Features\nAgile and responsive\n\nThe VeloCore X9 eMTB is designed to be nimble and responsive on the trail. Its custom carbon frame offers a perfect balance of stiffness and compliance, while the suspension system provides smooth and stable performance on technical terrain.\n\nPowerful and efficient\n\nThe Shimano STEPS E8000 motor and 504Wh battery provide up to 62 miles of range and 20 mph assistance. The motor delivers smooth and powerful performance, while the battery offers reliable and consistent power for long rides.\n\nCustomizable ride experience\n\nThe VeloCore X9 eMTB comes with an intuitive and customizable Shimano STEPS display that allows you to adjust the level of assistance, monitor your speed and battery life, and customize your ride experience to suit your needs.\n\nPremium components\n\nThe VeloCore X9 eMTB is equipped with high-end components, including a Shimano XT 12-speed drivetrain, Shimano SLX brakes, and DT Swiss wheels. These components offer reliable and precise performance, allowing you to push your limits with confidence.\n\n## Specs\nFrameset\nFrame\tVeloCore carbon fiber frame, Boost, tapered head tube, internal cable routing, 140mm travel\nFork\tRockShox Pike Ultimate, Charger 2.1 damper, DebonAir spring, 15x110mm Boost Maxle Ultimate, 46mm offset, 140mm travel\nShock\tFox Float DPS Performance, EVOL, 3-position adjust, Kashima Coat, 210x50mm\n\nWheels\nWheel front\tDT Swiss XM1700 Spline, 30mm internal width, 15x110mm Boost axle\nWheel rear\tDT Swiss XM1700 Spline, 30mm internal width, Shimano Microspline driver, 12x148mm Boost axle\nTire front\tMaxxis Minion DHF, 29x2.5\", EXO+ casing, tubeless ready\nTire rear\tMaxxis Minion DHR II, 29x2.4\", EXO+ casing, tubeless ready\n\nDrivetrain\nShifter\tShimano XT M8100, 12-speed\nRear derailleur\tShimano XT M8100, Shadow Plus, long cage, 51T max cog\nCrankset\tShimano STEPS E8000, 165mm length, 34T chainring\nCassette\tShimano XT M8100, 10-51T, 12-speed\nChain\tShimano CN-M8100, 12-speed\nPedals\tNot included\n\nComponents\nSaddle\tBontrager Arvada, hollow chromoly rails\nSeatpost\tDrop Line, internal routing, 31.6mm (15.5: 100mm, 17.5 & 18.5: 125mm, 19.5 & 21.5: 150mm)\nHandlebar\tBontrager Line Pro, ADV Carbon, 35mm, 27.5mm rise, 780mm width\nStem\tBontrager Line Pro, 35mm, Knock Block, 0 degree, 50mm length\nGrips\tBontrager XR Trail Elite, alloy lock-on\nHeadset\tIntegrated, sealed cartridge bearing, 1-1/8\" top, 1.5\" bottom\nBrakeset\tShimano SLX M7120, 4-piston hydraulic disc\n\nAccessories\nBattery\tShimano STEPS BT-E8010, 504Wh\nCharger\tShimano STEPS EC-E8004, 4A\nController\tShimano STEPS E8000 display\nBike weight\tM - 22.5 kg / 49.6 lbs (with tubes)\n\n## Sizing & fit\n\n| Size | Rider Height |\n|:----:|:------------------------:|\n| S | 162 - 170 cm 5'4\" - 5'7\" |\n| M | 170 - 178 cm 5'7\" - 5'10\"|\n| L | 178 - 186 cm 5'10\" - 6'1\"|\n| XL | 186 - 196 cm 6'1\" - 6'5\" |\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\n\n| Frame size | S | M | L | XL |\n|---------------------------|-------|-------|-------|-------|\n| A — Seat tube | 40.6 | 43.2 | 47.0 | 51.0 |\n| B — Seat tube angle | 75.0° | 75.0° | 75.0° | 75.0° |\n| C — Head tube length | 9.6 | 10.6 | 11.6 | 12.6 |\n| D — Head angle | 66.5° | 66.5° | 66.5° | 66.5° |\n| E — Effective top tube | 60.4 | 62.6 | 64.8 | 66.9 |\n| F — Bottom bracket height | 33.2 | 33.2 | 33.2 | 33.2 |\n| G — Bottom bracket drop | 3.0 | 3.0 | 3.0 | 3.0 |\n| H — Chainstay length | 45.5 | 45.5 | 45.5 | 45.5 |\n| I — Offset | 4.6 | 4.6 | 4.6 | 4.6 |\n| J — Trail | 11.9 | 11.9 | 11.9 | 11.9 |\n| K — Wheelbase | 117.0 | 119.3 | 121.6 | 123.9 |\n| L — Standover | 75.9 | 75.9 | 78.6 | 78.6 |\n| M — Frame reach | 43.6 | 45.6 | 47.6 | 49.6 |\n| N — Frame stack | 60.5 | 61.5 | 62.4 | 63.4 |", "price": 1299.99, "tags": [ "bicycle", "touring bike" ] }, { "name": "Zephyr 8.8 GX Eagle AXS Gen 3", "shortDescription": "Zephyr 8.8 GX Eagle AXS is a light and nimble full-suspension mountain bike. It's designed to handle technical terrain with ease and has a smooth and efficient ride feel. The sleek and powerful Bosch Performance Line CX motor and removable Powertube battery provide a boost to your pedaling and give you long-lasting riding time. The bike also features high-end components and advanced technology for an ultimate mountain biking experience.", "description": "## Overview\nIt's right for you if...\nYou're an avid mountain biker looking for a high-performance e-MTB that can tackle challenging trails. You want a bike with a powerful motor, efficient suspension, and advanced technology to enhance your riding experience. You also need a bike that's reliable and durable for long-lasting use.\n\nThe tech you get\nA lightweight, full carbon frame with 150mm of rear travel and a 160mm RockShox Pike Ultimate fork with Charger 2.1 RCT3 damper, remote lockout, and DebonAir spring. A Bosch Performance Line CX motor and removable Powertube 625Wh battery that can assist up to 20mph when it's on and gives zero drag when it's off, plus an easy-to-use handlebar-mounted Bosch Purion controller. A SRAM GX Eagle AXS wireless electronic drivetrain, a RockShox Reverb Stealth dropper, and DT Swiss HX1501 Spline One wheels.\n\nThe final word\nZephyr 8.8 GX Eagle AXS is a high-performance e-MTB that's designed to handle technical terrain with ease. With a powerful Bosch motor and long-lasting battery, you can conquer challenging climbs and enjoy long rides. The bike also features high-end components and advanced technology for an ultimate mountain biking experience.\n\n## Features\nPowerful motor\n\nThe Bosch Performance Line CX motor provides a boost to your pedaling and can assist up to 20mph. It has four power modes and a walk-assist function for easy navigation on steep climbs. The motor is also reliable and durable for long-lasting use.\n\nEfficient suspension\n\nZephyr 8.8 has a 150mm of rear travel and a 160mm RockShox Pike Ultimate fork with Charger 2.1 RCT3 damper, remote lockout, and DebonAir spring. The suspension is efficient and responsive, allowing you to handle technical terrain with ease.\n\nRemovable battery\n\nThe Powertube 625Wh battery is removable for easy charging and storage. It provides long-lasting riding time and can be replaced with a spare battery for even longer rides. The battery is also durable and weather-resistant for all-season riding.\n\nAdvanced technology\n\nZephyr 8.8 is equipped with advanced technology, including a Bosch Purion controller for easy motor control, a SRAM GX Eagle AXS wireless electronic drivetrain for precise shifting, and a RockShox Reverb Stealth dropper for adjustable saddle height. The bike also has DT Swiss HX1501 Spline One wheels for reliable performance on any terrain.\n\nCarbon frame\n\nThe full carbon frame is lightweight and durable, providing a smooth and efficient ride. It's also designed with a tapered head tube, internal cable routing, and Boost148 spacing for enhanced stiffness and responsiveness.\n\n## Specs\nFrameset\nFrame\tCarbon main frame & stays, tapered head tube, internal routing, Boost148, 150mm travel\nFork\tRockShox Pike Ultimate, Charger 2.1 RCT3 damper, DebonAir spring, remote lockout, tapered steerer, Boost110, 15mm Maxle Stealth, 160mm travel\nShock\tRockShox Deluxe RT3, DebonAir spring, 205mm x 57.5mm\nMax compatible fork travel\t170mm\n\nWheels\nWheel front\tDT Swiss HX1501 Spline One, Centerlock, 30mm inner width, 110x15mm Boost\nWheel rear\tDT Swiss HX1501 Spline One, Centerlock, 30mm inner width, SRAM XD driver, 148x12mm Boost\nTire\tBontrager XR4 Team Issue, Tubeless Ready, Inner Strength sidewall, aramid bead, 120tpi, 29x2.40''\nMax tire size\t29x2.60\"\n\nDrivetrain\nShifter\tSRAM GX Eagle AXS, wireless, 12 speed\nRear derailleur\tSRAM GX Eagle AXS\nCrank\tBosch Gen 4, 32T\nChainring\tSRAM X-Sync 2, 32T, direct-mount\nCassette\tSRAM PG-1275 Eagle, 10-52, 12 speed\nChain\tSRAM GX Eagle, 12 speed\n\nComponents\nSaddle\tBontrager Arvada, hollow titanium rails, 138mm width\nSeatpost\tRockShox Reverb Stealth, 31.6mm, internal routing, 150mm (S), 170mm (M/L), 200mm (XL)\nHandlebar\tBontrager Line Pro, ADV Carbon, 35mm, 27.5mm rise, 780mm width\nGrips\tBontrager XR Trail Elite, alloy lock-on\nStem\tBontrager Line Pro, Knock Block, 35mm, 0 degree, 50mm length\nHeadset\tIntegrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom\nBrake\tSRAM Code RSC hydraulic disc, 200mm (front), 180mm (rear)\nBrake rotor\tSRAM CenterLine, centerlock, round edge, 200mm (front), 180mm (rear)\n\nAccessories\nE-bike system\tBosch Performance Line CX\nBattery\tBosch Powertube 625Wh\nCharger\tBosch 4A compact charger\nController\tBosch Purion\nTool\tBontrager multi-tool, integrated storage bag\n\nWeight\nWeight\tM - 24.08 kg / 53.07 lbs (with TLR sealant, no tubes)\nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n\n## Sizing & fit\n\n| Size | Rider Height | Inseam |\n|:----:|:------------------------:|:--------------------:|\n| S | 153 - 162 cm 5'0\" - 5'4\" | 67 - 74 cm 26\" - 29\" |\n| M | 161 - 172 cm 5'3\" - 5'8\" | 74 - 79 cm 29\" - 31\" |\n| L | 171 - 180 cm 5'7\" - 5'11\" | 79 - 84 cm 31\" - 33\" |\n| XL | 179 - 188 cm 5'10\" - 6'2\" | 84 - 89 cm 33\" - 35\" |\n\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\nSizing table\n| Frame size letter | S | M | L | XL |\n|---------------------------|-------|-------|-------|-------|\n| Actual frame size | 15.5 | 17.5 | 19.5 | 21.5 |\n| Wheel size | 29\" | 29\" | 29\" | 29\" |\n| A — Seat tube | 39.4 | 41.9 | 44.5 | 47.6 |\n| B — Seat tube angle | 76.1° | 76.1° | 76.1° | 76.1° |\n| C — Head tube length | 9.6 | 10.5 | 11.5 | 12.5 |\n| D — Head angle | 65.5° | 65.5° | 65.5° | 65.5° |\n| E — Effective top tube | 58.6 | 61.3 | 64.0 | 66.7 |\n| F — Bottom bracket height | 34.0 | 34.0 | 34.0 | 34.0 |\n| G — Bottom bracket drop | 1.0 | 1.0 | 1.0 | 1.0 |\n| H — Chainstay length | 45.0 | 45.0 | 45.0 | 45.0 |\n| I — Offset | 4.6 | 4.6 | 4.6 | 4.6 |\n| J — Trail | 10.5 | 10.5 | 10.5 | 10.5 |\n| K — Wheelbase | 119.5 | 122.3 | 125.0 | 127.8 |\n| L — Standover | 72.7 | 74.7 | 77.6 | 81.0 |\n|", "price": 1499.99, "tags": [ "bicycle", "electric bike", "city bike" ] }, { "name": "Velo 99 XR1 AXS", "shortDescription": "Velo 99 XR1 AXS is a next-generation bike designed for fast-paced adventure seekers and speed enthusiasts. Built for high-performance racing, the bike boasts state-of-the-art technology and premium components. It is the ultimate bike for riders who want to push their limits and get their adrenaline pumping.", "description": "## Overview\nIt's right for you if...\nYou are a passionate cyclist looking for a bike that can keep up with your speed, agility, and endurance. You are an adventurer who loves to explore new terrains and challenge yourself on the toughest courses. You want a bike that is lightweight, durable, and packed with the latest technology.\n\nThe tech you get\nA lightweight, full carbon frame with advanced aerodynamics and integrated cable routing for a clean look. A high-performance SRAM XX1 Eagle AXS wireless electronic drivetrain, featuring a 12-speed cassette and a 32T chainring. A RockShox SID Ultimate fork with a remote lockout, 120mm travel, and Charger Race Day damper. A high-end SRAM G2 Ultimate hydraulic disc brake with carbon levers. A FOX Transfer SL dropper post for quick and easy height adjustments. DT Swiss XRC 1501 carbon wheels for superior speed and handling.\n\nThe final word\nVelo 99 XR1 AXS is a premium racing bike that can help you achieve your goals and reach new heights. It is designed for speed, agility, and performance, and it is packed with the latest technology and premium components. If you are a serious cyclist who wants the best, this is the bike for you.\n\n## Features\nAerodynamic design\n\nThe Velo 99 XR1 AXS features a state-of-the-art frame design that reduces drag and improves speed. It has an aerodynamic seatpost, integrated cable routing, and a sleek, streamlined look that sets it apart from other bikes.\n\nWireless electronic drivetrain\n\nThe SRAM XX1 Eagle AXS drivetrain features a wireless electronic system that provides precise, instant shifting and unmatched efficiency. It eliminates the need for cables and makes the bike lighter and faster.\n\nHigh-performance suspension\n\nThe RockShox SID Ultimate fork and Charger Race Day damper provide 120mm of smooth, responsive suspension that can handle any terrain. The fork also has a remote lockout for quick adjustments on the fly.\n\nSuperior braking power\n\nThe SRAM G2 Ultimate hydraulic disc brake system delivers unmatched stopping power and control. It has carbon levers for a lightweight, ergonomic design and precision control.\n\nCarbon wheels\n\nThe DT Swiss XRC 1501 carbon wheels are ultra-lightweight, yet incredibly strong and durable. They provide superior speed and handling, making the bike more agile and responsive.\n\n## Specs\nFrameset\nFrame\tFull carbon frame, integrated cable routing, aerodynamic design, Boost148\nFork\tRockShox SID Ultimate, Charger Race Day damper, remote lockout, tapered steerer, Boost110, 15mm Maxle Stealth, 120mm travel\n\nWheels\nWheel front\tDT Swiss XRC 1501 carbon wheel, Boost110, 15mm thru axle\nWheel rear\tDT Swiss XRC 1501 carbon wheel, SRAM XD driver, Boost148, 12mm thru axle\nTire\tSchwalbe Racing Ray, Performance Line, Addix, 29x2.25\"\nTire part\tSchwalbe Doc Blue Professional, 500ml\nMax tire size\t29x2.3\"\n\nDrivetrain\nShifter\tSRAM Eagle AXS, wireless, 12-speed\nRear derailleur\tSRAM XX1 Eagle AXS\nCrank\tSRAM XX1 Eagle, 32T, carbon\nChainring\tSRAM X-SYNC, 32T, alloy\nCassette\tSRAM Eagle XG-1299, 10-52, 12-speed\nChain\tSRAM XX1 Eagle, 12-speed\nMax chainring size\t1x: 32T\n\nComponents\nSaddle\tBontrager Montrose Elite, carbon rails, 138mm width\nSeatpost\tFOX Transfer SL, 125mm travel, internal routing, 31.6mm\nHandlebar\tBontrager Kovee Pro, ADV Carbon, 35mm, 5mm rise, 720mm width\nGrips\tBontrager XR Endurance Elite\nStem\tBontrager Kovee Pro, 35mm, Blendr compatible, 7 degree, 60mm length\nHeadset\tIntegrated, cartridge bearing, 1-1/8\" top, 1.5\" bottom\nBrake\tSRAM G2 Ultimate hydraulic disc, carbon levers, 180mm rotors\n\nAccessories\nBike computer\tBontrager Trip 300\nTool\tBontrager Flatline Pro pedal wrench, T25 Torx\n\n\n## Sizing & fit\n\n| Size | Rider Height | Inseam |\n|:----:|:------------------------:|:--------------------:|\n| S | 158 - 168 cm 5'2\" - 5'6\" | 74 - 78 cm 29\" - 31\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" | 78 - 82 cm 31\" - 32\" |\n| L | 173 - 183 cm 5'8\" - 6'0\" | 82 - 86 cm 32\" - 34\" |\n| XL | 180 - 193 cm 5'11\" - 6'4\" | 86 - 90 cm 34\" - 35\" |\n\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\nSizing table\n| Frame size letter | S | M | L | XL |\n|---------------------------|-------|-------|-------|-------|\n| Actual frame size | 15.5 | 17.5 | 19.5 | 21.5 |\n| Wheel size | 29\" | 29\" | 29\" | 29\" |\n| A — Seat tube | 39.9 | 43.0 | 47.0 | 51.0 |\n| B — Seat tube angle | 74.5° | 74.5° | 74.5° | 74.5° |\n| C — Head tube length | 9.0 | 10.0 | 11.0 | 12.0 |\n| D — Head angle | 68.0° | 68.0° | 68.0° | 68.0° |\n| E — Effective top tube | 57.8 | 59.7 | 61.6 | 63.6 |\n| F — Bottom bracket height | 33.0 | 33.0 | 33.0 | 33.0 |\n| G — Bottom bracket drop | 5.0 | 5.0 | 5.0 | 5.0 |\n| H — Chainstay length | 43.0 | 43.0 | 43.0 | 43.0 |\n| I — Offset | 4.2 | 4.2 | 4.2 | 4.2 |\n| J — Trail | 9.7 | 9.7 | 9.7 | 9.7 |\n| K — Wheelbase | 112.5 | 114.5 | 116.5 | 118.6 |\n| L — Standover | 75.9 | 77.8 | 81.5 | 84.2 |\n| M — Frame reach | 41.6 | 43.4 | 45.2 | 47.1 |\n| N — Frame stack | 58.2 | 58.9 | 59.3 | 59.9 |", "price": 1099.99, "tags": [ "bicycle", "mountain bike" ] }, { "name": "AURORA 11S E-MTB", "shortDescription": "The AURORA 11S is a powerful and stylish electric mountain bike designed to take you on thrilling off-road adventures. With its sturdy frame and premium components, this bike is built to handle any terrain. It features a high-performance motor, long-lasting battery, and advanced suspension system that guarantee a smooth and comfortable ride.", "description": "## Overview\nIt's right for you if...\nYou want a top-of-the-line e-MTB that is both powerful and stylish. You also want a bike that can handle any terrain, from steep climbs to rocky descents. With its advanced features and premium components, the AURORA 11S is designed for serious off-road riders who demand the best.\n\nThe tech you get\nA sturdy aluminum frame with advanced suspension system that provides 120mm of travel. A 750W brushless motor that delivers up to 28mph, and a 48V/14Ah lithium-ion battery that provides up to 60 miles of range on a single charge. An advanced 11-speed Shimano drivetrain with hydraulic disc brakes for precise shifting and reliable stopping power. \n\nThe final word\nThe AURORA 11S is a top-of-the-line e-MTB that delivers exceptional performance and style. Whether you're tackling steep climbs or hitting rocky descents, this bike is built to handle any terrain with ease. With its advanced features and premium components, the AURORA 11S is the perfect choice for serious off-road riders who demand the best.\n\n## Features\nPowerful and efficient\n\nThe AURORA 11S is equipped with a high-performance 750W brushless motor that delivers up to 28mph. The motor is powered by a long-lasting 48V/14Ah lithium-ion battery that provides up to 60 miles of range on a single charge.\n\nAdvanced suspension system\n\nThe bike's advanced suspension system provides 120mm of travel, ensuring a smooth and comfortable ride on any terrain. The front suspension is a Suntour XCR32 Air fork, while the rear suspension is a KS-281 hydraulic shock absorber.\n\nPremium components\n\nThe AURORA 11S features an advanced 11-speed Shimano drivetrain with hydraulic disc brakes. The bike is also equipped with a Tektro HD-E725 hydraulic disc brake system that provides reliable stopping power.\n\nSleek and stylish design\n\nWith its sleek and stylish design, the AURORA 11S is sure to turn heads on the trail. The bike's sturdy aluminum frame is available in a range of colors, including black, blue, and red.\n\n## Specs\nFrameset\nFrame Material: Aluminum\nFrame Size: S, M, L\nFork: Suntour XCR32 Air, 120mm Travel\nShock Absorber: KS-281 Hydraulic Shock Absorber\n\nWheels\nWheel Size: 27.5 inches\nTires: Kenda K1151 Nevegal, 27.5x2.35\nRims: Alloy Double Wall\nSpokes: 32H, Stainless Steel\n\nDrivetrain\nShifters: Shimano SL-M7000\nRear Derailleur: Shimano RD-M8000\nCrankset: Prowheel 42T, Alloy Crank Arm\nCassette: Shimano CS-M7000, 11-42T\nChain: KMC X11EPT\n\nBrakes\nBrake System: Tektro HD-E725 Hydraulic Disc Brake\nBrake Rotors: 180mm Front, 160mm Rear\n\nE-bike system\nMotor: 750W Brushless\nBattery: 48V/14Ah Lithium-Ion\nCharger: 48V/3A Smart Charger\nController: Intelligent Sinusoidal Wave\n\nWeight\nWeight: 59.5 lbs\n\n## Sizing & fit\n| Size | Rider Height | Standover Height |\n|------|-------------|-----------------|\n| S | 5'2\"-5'6\" | 28.5\" |\n| M | 5'7\"-6'0\" | 29.5\" |\n| L | 6'0\"-6'4\" | 30.5\" |\n\n## Geometry\nAll measurements provided in cm.\nSizing table\n| Frame size letter | S | M | L |\n|-------------------|-----|-----|-----|\n| Wheel Size | 27.5\"| 27.5\"| 27.5\"|\n| Seat tube length | 44.5| 48.5| 52.5|\n| Head tube angle | 68° | 68° | 68° |\n| Seat tube angle | 74.5°| 74.5°| 74.5°|\n| Effective top tube | 57.5| 59.5| 61.5|\n| Head tube length | 12.0| 12.0| 13.0|\n| Chainstay length | 45.5| 45.5| 45.5|\n| Bottom bracket height | 30.0| 30.0| 30.0|\n| Wheelbase | 115.0|116.5|118.5|", "price": 1999.99, "tags": [ "bicycle", "road bike" ] }, { "name": "VeloTech V9.5 AXS Gen 3", "shortDescription": "VeloTech V9.5 AXS is a sleek and fast carbon bike that combines high-end tech with a comfortable ride. It's designed to provide the ultimate experience for the most serious riders. The bike comes with a lightweight and powerful motor that can be activated when needed, and you get a spec filled with premium parts.", "description": "## Overview\nIt's right for you if...\nYou want a bike that is fast, efficient, and delivers an adrenaline-filled experience. You are looking for a bike that is built with cutting-edge technology, and you want a ride that is both comfortable and exciting.\n\nThe tech you get\nA lightweight and durable full carbon frame with a fork that has 100mm of travel. The bike comes with a powerful motor that can deliver up to 20 mph of assistance. The drivetrain is a wireless electronic system that is precise and reliable. The bike is also equipped with hydraulic disc brakes, tubeless-ready wheels, and comfortable grips.\n\nThe final word\nThe VeloTech V9.5 AXS is a high-end bike that delivers an incredible experience for serious riders. It combines the latest technology with a comfortable ride, making it perfect for long rides, tough climbs, and fast descents.\n\n## Features\nFast and efficient\nThe VeloTech V9.5 AXS comes with a powerful motor that can provide up to 20 mph of assistance. The motor is lightweight and efficient, providing a boost when you need it without adding bulk. The bike's battery is removable, allowing you to ride without assistance when you don't need it.\n\nSmart software for the trail\nThe VeloTech V9.5 AXS is equipped with intelligent software that delivers a smooth and responsive ride. The software allows the motor to respond immediately as you start to pedal, delivering more power over a wider cadence range. You can also customize your user settings to suit your preferences.\n\nComfortable ride\nThe VeloTech V9.5 AXS is designed to provide a comfortable ride, even on long rides. The bike's fork has 100mm of travel, providing ample cushioning for rough terrain. The bike's grips are also designed to provide a comfortable and secure grip, even on the most challenging rides.\n\n## Specs\nFrameset\nFrame\tCarbon fiber frame with internal cable routing and Boost148\nFork\t100mm of travel with remote lockout\nShock\tN/A\n\nWheels\nWheel front\tCarbon fiber tubeless-ready wheel\nWheel rear\tCarbon fiber tubeless-ready wheel\nSkewer rear\t12mm thru-axle\nTire\tTubeless-ready tire\nTire part\tTubeless sealant\n\nDrivetrain\nShifter\tWireless electronic shifter\nRear derailleur\tWireless electronic derailleur\nCrank\tCarbon fiber crankset with chainring\nCrank arm\tCarbon fiber crank arm\nChainring\tAlloy chainring\nCassette\t12-speed cassette\nChain\t12-speed chain\n\nComponents\nSaddle\tCarbon fiber saddle\nSeatpost\tCarbon fiber seatpost\nHandlebar\tCarbon fiber handlebar\nGrips\tComfortable and secure grips\nStem\tCarbon fiber stem\nHeadset\tCarbon fiber headset\nBrake\tHydraulic disc brakes\nBrake rotor\tDisc brake rotor\n\nAccessories\nE-bike system\tPowerful motor with removable battery\nBattery\tLithium-ion battery\nCharger\tFast charging adapter\nController\tHandlebar-mounted controller\nTool\tBasic toolkit\n\nWeight\nWeight\tM - 17.5 kg / 38.5 lbs (with tubeless sealant)\n\nWeight limit\nThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing & fit\n| Size | Rider Height | Inseam |\n|:----:|:------------------------:|:--------------------:|\n| S | 160 - 170 cm 5'3\" - 5'7\" | 74 - 79 cm 29\" - 31\" |\n| M | 170 - 180 cm 5'7\" - 5'11\" | 79 - 84 cm 31\" - 33\" |\n| L | 180 - 190 cm 5'11\" - 6'3\" | 84 - 89 cm 33\" - 35\" |\n| XL | 190 - 200 cm 6'3\" - 6'7\" | 89 - 94 cm 35\" - 37\" |\n\n## Geometry\nAll measurements provided in cm unless otherwise noted.\nSizing table\n| Frame size letter | S | M | L | XL |\n|---------------------------|-------|-------|-------|-------|\n| Actual frame size | 50.0 | 53.3 | 55.6 | 58.8 |\n| Wheel size | 29\" | 29\" | 29\" | 29\" |\n| A — Seat tube | 39.4 | 43.2 | 48.3 | 53.3 |\n| B — Seat tube angle | 72.3° | 72.6° | 72.8° | 72.8° |\n| C — Head tube length | 9.0 | 10.0 | 10.5 | 11.0 |\n| D — Head angle | 67.5° | 67.5° | 67.5° | 67.5° |\n| E — Effective top tube | 58.0 | 61.7 | 64.8 | 67.0 |\n| F — Bottom bracket height | 32.3 | 32.3 | 32.3 | 32.3 |\n| G — Bottom bracket drop | 5.0 | 5.0 | 5.0 | 5.0 |\n| H — Chainstay length | 44.7 | 44.7 | 44.7 | 44.7 |\n| I — Offset | 4.2 | 4.2 | 4.2 | 4.2 |\n| J — Trail | 10.9 | 10.9 | 10.9 | 10.9 |\n| K — Wheelbase | 112.6 | 116.5 | 119.7 | 121.9 |\n| L — Standover | 76.8 | 76.8 | 76.8 | 76.8 |\n| M — Frame reach | 40.5 | 44.0 | 47.0 | 49.0 |\n| N — Frame stack | 60.9 | 61.8 | 62.2 | 62.7 |", "price": 1699.99, "tags": [ "bicycle", "electric bike", "city bike" ] }, { "name": "Axiom D8 E-Mountain Bike", "shortDescription": "The Axiom D8 is an electrifying mountain bike that is built for adventure. It boasts a light aluminum frame, a powerful motor and the latest tech to tackle the toughest of terrains. The D8 provides assistance without adding bulk to the bike, giving you the flexibility to ride like a traditional mountain bike or have an extra push when you need it.", "description": "## Overview \nIt's right for you if... \nYou're looking for an electric mountain bike that can handle a wide variety of terrain, from flowing singletrack to technical descents. You also want a bike that offers a powerful motor that provides assistance without adding bulk to the bike. The D8 is designed to take you anywhere, quickly and comfortably.\n\nThe tech you get \nA lightweight aluminum frame with 140mm of travel, a Suntour fork with hydraulic lockout, and a reliable and powerful Bafang M400 mid-motor that provides a boost up to 20 mph. The bike features a Shimano Deore drivetrain, hydraulic disc brakes, and a dropper seat post. With the latest tech on-board, the D8 is designed to take you to new heights.\n\nThe final word \nThe Axiom D8 is an outstanding electric mountain bike that is designed for adventure. It's built with the latest tech and provides the flexibility to ride like a traditional mountain bike or have an extra push when you need it. Whether you're a beginner or an experienced rider, the D8 is the perfect companion for your next adventure.\n\n## Features \nBuilt for Adventure \n\nThe D8 features a lightweight aluminum frame that is built to withstand rugged terrain. It comes equipped with 140mm of travel and a Suntour fork that can handle even the toughest of trails. With this bike, you're ready to take on anything the mountain can throw at you.\n\nPowerful Motor \n\nThe Bafang M400 mid-motor provides reliable and powerful assistance without adding bulk to the bike. You can quickly and easily switch between the different assistance levels to find the perfect balance between range and power.\n\nShimano Deore Drivetrain \n\nThe Shimano Deore drivetrain is reliable and offers smooth shifting on any terrain. You can easily adjust the gears to match your riding style and maximize your performance on the mountain.\n\nDropper Seat Post \n\nThe dropper seat post allows you to easily adjust your seat height on the fly, so you can maintain the perfect position for any terrain. With the flick of a switch, you can quickly and easily lower or raise your seat to match the terrain.\n\nHydraulic Disc Brakes \n\nThe D8 features powerful hydraulic disc brakes that offer reliable stopping power in any weather condition. You can ride with confidence knowing that you have the brakes to stop on a dime.\n\n## Specs \nFrameset \nFrame\tAluminum frame with 140mm of travel \nFork\tSuntour fork with hydraulic lockout, 140mm of travel \nShock\tN/A \nMax compatible fork travel\t140mm \n \nWheels \nWheel front\tAlloy wheel \nWheel rear\tAlloy wheel \nSkewer rear\tThru axle \nTire\t29\" x 2.35\" \nTire part\tN/A \nMax tire size\t29\" x 2.6\" \n \nDrivetrain \nShifter\tShimano Deore \nRear derailleur\tShimano Deore \nCrank\tBafang M400 \nCrank arm\tN/A \nChainring\tN/A \nCassette\tShimano Deore \nChain\tShimano Deore \nMax chainring size\tN/A \n \nComponents \nSaddle\tAxiom D8 saddle \nSeatpost\tDropper seat post \nHandlebar\tAxiom D8 handlebar \nGrips\tAxiom D8 grips \nStem\tAxiom D8 stem \nHeadset\tAxiom D8 headset \nBrake\tHydraulic disc brakes \nBrake rotor\t180mm \n\nAccessories \nE-bike system\tBafang M400 mid-motor \nBattery\tLithium-ion battery, 500Wh \nCharger\tLithium-ion charger \nController\tBafang M400 controller \nTool\tN/A \n \nWeight \nWeight\tM - 22 kg / 48.5 lbs \nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 136 kg (300 lbs). \n \n \n## Sizing & fit \n \n| Size | Rider Height | Inseam | \n|:----:|:------------------------:|:--------------------:| \n| S | 152 - 165 cm 5'0\" - 5'5\" | 70 - 76 cm 27\" - 30\" | \n| M | 165 - 178 cm 5'5\" - 5'10\" | 76 - 81 cm 30\" - 32\" | \n| L | 178 - 185 cm 5'10\" - 6'1\" | 81 - 86 cm 32\" - 34\" | \n| XL | 185 - 193 cm 6'1\" - 6'4\" | 86 - 91 cm 34\" - 36\" | \n \n \n## Geometry \n \nAll measurements provided in cm unless otherwise noted. \nSizing table \n| Frame size letter | S | M | L | XL | \n|---------------------------|-------|-------|-------|-------| \n| Actual frame size | 41.9 | 46.5 | 50.8 | 55.9 | \n| Wheel size | 29\" | 29\" | 29\" | 29\" | \n| A — Seat tube | 42.0 | 46.5 | 51.0 | 56.0 | \n| B — Seat tube angle | 74.0° | 74.0° | 74.0° | 74.0° | \n| C — Head tube length | 11.0 | 12.0 | 13.0 | 15.0 | \n| D — Head angle | 68.0° | 68.0° | 68.0° | 68.0° | \n| E — Effective top tube | 57.0 | 60.0 | 62.0 | 65.0 | \n| F — Bottom bracket height | 33.0 | 33.0 | 33.0 | 33.0 | \n| G — Bottom bracket drop | 3.0 | 3.0 | 3.0 | 3.0 | \n| H — Chainstay length | 46.0 | 46.0 | 46.0 | 46.0 | \n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 | \n| J — Trail | 10.9 | 10.9 | 10.9 | 10.9 | \n| K — Wheelbase | 113.0 | 116.0 | 117.5 | 120.5 | \n| L — Standover | 73.5 | 75.5 | 76.5 | 79.5 | \n| M — Frame reach | 41.0 | 43.5 | 45.0 | 47.5 | \n| N — Frame stack | 60.5 | 61.5 | 62.5 | 64.5 |", "price": 1399.99, "tags": [ "bicycle", "electric bike", "mountain bike" ] }, { "name": "Velocity X1", "shortDescription": "Velocity X1 is a high-performance road bike designed for speed enthusiasts. It features a lightweight yet durable frame, aerodynamic design, and top-quality components, making it the perfect choice for those who want to take their cycling experience to the next level.", "description": "## Overview\nIt's right for you if...\nYou're an experienced cyclist looking for a bike that can keep up with your need for speed. You want a bike that's lightweight, aerodynamic, and built to perform, whether you're training for a race or just pushing yourself to go faster.\n\nThe tech you get\nA lightweight aluminum frame with a carbon fork, Shimano Ultegra groupset with a wide range of gearing, hydraulic disc brakes, aerodynamic carbon wheels, and a vibration-absorbing handlebar with ergonomic grips.\n\nThe final word\nVelocity X1 is the ultimate road bike for speed enthusiasts. Its lightweight frame, aerodynamic design, and top-quality components make it the perfect choice for those who want to take their cycling experience to the next level.\n\n\n## Features\n\nAerodynamic design\nVelocity X1 is built with an aerodynamic design to help you go faster with less effort. It features a sleek profile, hidden cables, and a carbon fork that cuts through the wind, reducing drag and increasing speed.\n\nHydraulic disc brakes\nVelocity X1 comes equipped with hydraulic disc brakes, providing excellent stopping power in all weather conditions. They're also low maintenance, with minimal adjustments needed over time.\n\nCarbon wheels\nThe Velocity X1's aerodynamic carbon wheels provide excellent speed and responsiveness, helping you achieve your fastest times yet. They're also lightweight, reducing overall bike weight and making acceleration and handling even easier.\n\nShimano Ultegra groupset\nThe Shimano Ultegra groupset provides smooth shifting and reliable performance, ensuring you get the most out of every ride. With a wide range of gearing options, it's ideal for tackling any terrain, from steep climbs to fast descents.\n\n\n## Specifications\nFrameset\nFrame with Fork\tAluminium frame, internal cable routing, 135x9mm QR\nFork\tCarbon, hidden cable routing, 100x9mm QR\n\nWheels\nWheel front\tCarbon, 30mm deep rim, 23mm width, 100x9mm QR\nWheel rear\tCarbon, 30mm deep rim, 23mm width, 135x9mm QR\nSkewer front\t100x9mm QR\nSkewer rear\t135x9mm QR\nTire\tContinental Grand Prix 5000, 700x25mm, folding bead\nMax tire size\t700x28mm without fenders\n\nDrivetrain\nShifter\tShimano Ultegra R8020, 11 speed\nRear derailleur\tShimano Ultegra R8000, 11 speed\n*Crank\tSize: S, M\nShimano Ultegra R8000, 50/34T, 170mm length\nSize: L, XL\nShimano Ultegra R8000, 50/34T, 175mm length\nBottom bracket\tShimano BB-RS500-PB, PressFit\nCassette\tShimano Ultegra R8000, 11-30T, 11 speed\nChain\tShimano Ultegra HG701, 11 speed\nPedal\tNot included\nMax chainring size\t50/34T\n\nComponents\nSaddle\tBontrager Montrose Comp, steel rails, 138mm width\nSeatpost\tBontrager Comp, 6061 alloy, 27.2mm, 8mm offset, 330mm length\n*Handlebar\tSize: S, M, L\nBontrager Elite Aero VR-CF, alloy, 31.8mm, 93mm reach, 123mm drop, 400mm width\nSize: XL\nBontrager Elite Aero VR-CF, alloy, 31.8mm, 93mm reach, 123mm drop, 420mm width\nGrips\tBontrager Supertack Perf tape\n*Stem\tSize: S, M, L\nBontrager Elite Blendr, 31.8mm clamp, 7 degree, 90mm length\nSize: XL\nBontrager Elite Blendr, 31.8mm clamp, 7 degree, 100mm length\nBrake\tShimano Ultegra R8070 hydraulic disc, flat mount\nBrake rotor\tShimano RT800, centerlock, 160mm\nRotor size\tMax brake rotor sizes: 160mm front & rear\n\nWeight\nWeight\tM - 8.15 kg / 17.97 lbs\nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 275 pounds (125 kg).\n\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| S | 162 - 170 cm 5'4\" - 5'7\" | 74 - 78 cm 29\" - 31\" |\n| M | 170 - 178 cm 5'7\" - 5'10\" | 77 - 82 cm 30\" - 32\" |\n| L | 178 - 186 cm 5'10\" - 6'1\" | 82 - 86 cm 32\" - 34\" |\n| XL | 186 - 196 cm 6'1\" - 6'5\" | 87 - 92 cm 34\" - 36\" |\n\n\n## Geometry\n| Frame size letter | S | M | L | XL |\n|---------------------------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 50.0 | 52.0 | 54.0 | 56.0 |\n| B — Seat tube angle | 74.0° | 73.5° | 73.0° | 72.5° |\n| C — Head tube length | 13.0 | 15.0 | 17.0 | 19.0 |\n| D — Head angle | 71.0° | 72.0° | 72.0° | 72.5° |\n| E — Effective top tube | 53.7 | 55.0 | 56.5 | 58.0 |\n| F — Bottom bracket height | 27.5 | 27.5 | 27.5 | 27.5 |\n| G — Bottom bracket drop | 7.3 | 7.3 | 7.3 | 7.3 |\n| H — Chainstay length | 41.0 | 41.0 | 41.0 | 41.0 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 6.0 | 6.0 | 6.0 | 5.8 |\n| K — Wheelbase | 98.2 | 99.1 | 100.1 | 101.0 |\n| L — Standover | 75.2 | 78.2 | 81.1 | 84.1 |\n| M — Frame reach | 37.5 | 38.3 | 39.1 | 39.9 |\n| N — Frame stack | 53.3 | 55.4 | 57.4 | 59.5 |", "price": 1799.99, "tags": [ "bicycle", "touring bike" ] }, { "name": "Velocity V9", "shortDescription": "Velocity V9 is a high-performance hybrid bike that combines speed and comfort for riders who demand the best of both worlds. The lightweight aluminum frame, along with the carbon fork and seat post, provide optimal stiffness and absorption to tackle any terrain. A 2x Shimano Deore drivetrain, hydraulic disc brakes, and 700c wheels with high-quality tires make it a versatile ride for commuters, fitness riders, and weekend adventurers alike.", "description": "## Overview\nIt's right for you if...\nYou want a fast, versatile bike that can handle anything from commuting to weekend adventures. You value comfort as much as speed and performance. You want a reliable and durable bike that will last for years to come.\n\nThe tech you get\nA lightweight aluminum frame with a carbon fork and seat post, a 2x Shimano Deore drivetrain with a wide range of gearing, hydraulic disc brakes, and 700c wheels with high-quality tires. The Velocity V9 is designed for riders who demand both performance and comfort in one package.\n\nThe final word\nThe Velocity V9 is the perfect bike for riders who want speed and performance without sacrificing comfort. The lightweight aluminum frame and carbon components provide optimal stiffness and absorption, while the 2x Shimano Deore drivetrain and hydraulic disc brakes ensure precise shifting and stopping power. Whether you're commuting, hitting the trails, or training for your next race, the Velocity V9 has everything you need to achieve your goals.\n\n## Features\n\n2x drivetrain\nA 2x drivetrain means more versatility and a wider range of gearing options. Whether you're climbing hills or sprinting on the flats, the Velocity V9 has the perfect gear for any situation.\n\nCarbon components\nThe Velocity V9 features a carbon fork and seat post to provide optimal stiffness and absorption. This means you can ride faster and more comfortably over any terrain.\n\nHydraulic disc brakes\nHydraulic disc brakes provide unparalleled stopping power and modulation in any weather condition. You'll feel confident and in control no matter where you ride.\n\n## Specifications\nFrameset\nFrame with Fork\tAluminum frame with carbon fork and seat post, internal cable routing, fender mounts, 135x5mm ThruSkew\nFork\tCarbon fork, hidden fender mounts, flat mount disc, 5x100mm thru-skew\n\nWheels\nWheel front\tDouble wall aluminum rims, 700c, quick release hub\nWheel rear\tDouble wall aluminum rims, 700c, quick release hub\nTire\tKenda Kwick Tendril, puncture resistant, reflective sidewall, 700x32c\nMax tire size\t700x35c without fenders, 700x32c with fenders\n\nDrivetrain\nShifter\tShimano Deore, 10 speed\nFront derailleur\tShimano Deore\nRear derailleur\tShimano Deore\nCrank\tShimano Deore, 46-30T, 170mm (S/M), 175mm (L/XL)\nBottom bracket\tShimano BB52, 68mm, threaded\nCassette\tShimano Deore, 11-36T, 10 speed\nChain\tShimano HG54, 10 speed\nPedal\tWellgo alloy platform\n\nComponents\nSaddle\tVelo VL-2158, steel rails\nSeatpost\tCarbon seat post, 27.2mm\nHandlebar\tAluminum, 31.8mm clamp, 15mm rise, 680mm width\nGrips\tVelo ergonomic grips\nStem\tAluminum, 31.8mm clamp, 7 degree, 90mm length\nBrake\tShimano hydraulic disc, MT200 lever, MT200 caliper\nBrake rotor\tShimano RT56, centerlock, 160mm\nRotor size\tMax brake rotor sizes: 160mm front & rear\n\nWeight\nWeight\tM - 11.5 kg / 25.35 lbs\nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| S | 155 - 165 cm 5'1\" - 5'5\" | 72 - 78 cm 28\" - 31\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n| XL | 186 - 197 cm 6'1\" - 6'6\" | 87 - 93 cm 34\" - 37\" |\n\n## Geometry\n| Frame size | S | M | L | XL |\n|--------------------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 44.0 | 48.0 | 52.0 | 56.0 |\n| B — Seat tube angle | 74.5° | 74.0° | 73.5° | 73.0° |\n| C — Head tube length | 14.5 | 16.0 | 18.0 | 20.0 |\n| D — Head angle | 71.0° | 71.0° | 71.5° | 71.5° |\n| E — Effective top tube | 56.5 | 57.5 | 58.5 | 59.5 |\n| F — Bottom bracket height | 27.0 | 27.0 | 27.0 | 27.0 |\n| G — Bottom bracket drop | 7.0 | 7.0 | 7.0 | 7.0 |\n| H — Chainstay length | 43.0 | 43.0 | 43.0 | 43.0 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 7.0 | 7.0 | 6.6 | 6.6 |\n| K — Wheelbase | 105.4 | 106.3 | 107.2 | 108.2 |\n| L — Standover | 73.2 | 77.1 | 81.2 | 85.1 |\n| M — Frame reach | 39.0 | 39.8 | 40.4 | 41.3 |\n| N — Frame stack | 57.0 | 58.5 | 60.0 | 61.5 |", "price": 2199.99, "tags": [ "bicycle", "electric bike", "mountain bike" ] }, { "name": "Aero Pro X", "shortDescription": "Aero Pro X is a high-end racing bike designed for serious cyclists who demand speed, agility, and superior performance. The lightweight carbon frame and fork, combined with the aerodynamic design, provide optimal stiffness and efficiency to maximize your speed. The bike features a 2x Shimano Ultegra drivetrain, hydraulic disc brakes, and 700c wheels with high-quality tires. Whether you're competing in a triathlon or climbing steep hills, Aero Pro X delivers exceptional performance and precision handling.", "description": "## Overview\nIt's right for you if...\nYou are a competitive cyclist looking for a bike that is designed for racing. You want a bike that delivers exceptional speed, agility, and precision handling. You demand superior performance and reliability from your equipment.\n\nThe tech you get\nA lightweight carbon frame with an aerodynamic design, a carbon fork with hidden fender mounts, a 2x Shimano Ultegra drivetrain with a wide range of gearing, hydraulic disc brakes, and 700c wheels with high-quality tires. Aero Pro X is designed for serious cyclists who demand nothing but the best.\n\nThe final word\nAero Pro X is the ultimate racing bike for serious cyclists. The lightweight carbon frame and aerodynamic design deliver maximum speed and efficiency, while the 2x Shimano Ultegra drivetrain and hydraulic disc brakes ensure precise shifting and stopping power. Whether you're competing in a triathlon or a criterium race, Aero Pro X delivers the performance you need to win.\n\n## Features\n\nAerodynamic design\nThe Aero Pro X features an aerodynamic design that reduces drag and maximizes efficiency. The bike is optimized for speed and agility, so you can ride faster and farther with less effort.\n\nHydraulic disc brakes\nHydraulic disc brakes provide unrivaled stopping power and modulation in any weather condition. You'll feel confident and in control no matter where you ride.\n\nCarbon components\nThe Aero Pro X features a carbon fork with hidden fender mounts to provide optimal stiffness and absorption. This means you can ride faster and more comfortably over any terrain.\n\n## Specifications\nFrameset\nFrame with Fork\tCarbon frame with an aerodynamic design, internal cable routing, 3s chain keeper, 142x12mm thru-axle\nFork\tCarbon fork with hidden fender mounts, flat mount disc, 100x12mm thru-axle\n\nWheels\nWheel front\tDouble wall carbon rims, 700c, thru-axle hub\nWheel rear\tDouble wall carbon rims, 700c, thru-axle hub\nTire\tContinental Grand Prix 5000, folding bead, 700x25c\nMax tire size\t700x28c without fenders, 700x25c with fenders\n\nDrivetrain\nShifter\tShimano Ultegra, 11 speed\nFront derailleur\tShimano Ultegra\nRear derailleur\tShimano Ultegra\nCrank\tShimano Ultegra, 52-36T, 170mm (S), 172.5mm (M), 175mm (L/XL)\nBottom bracket\tShimano BB72, 68mm, PressFit\nCassette\tShimano Ultegra, 11-30T, 11 speed\nChain\tShimano HG701, 11 speed\nPedal\tNot included\n\nComponents\nSaddle\tBontrager Montrose Elite, carbon rails, 138mm width\nSeatpost\tCarbon seat post, 27.2mm, 20mm offset\nHandlebar\tBontrager XXX Aero, carbon, 31.8mm clamp, 75mm reach, 125mm drop\nGrips\tBontrager Supertack Perf tape\nStem\tBontrager Pro, 31.8mm clamp, 7 degree, 90mm length\nBrake\tShimano hydraulic disc, Ultegra lever, Ultegra caliper\nBrake rotor\tShimano RT800, centerlock, 160mm\nRotor size\tMax brake rotor sizes: 160mm front & rear\n\nWeight\nWeight\tM - 8.36 kg / 18.42 lbs\nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 275 pounds (125 kg).\n\n## Sizing\n| Size | Rider Height |\n|:----:|:-------------------------:|\n| S | 155 - 165 cm 5'1\" - 5'5\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" |\n| XL | 186 - 197 cm 6'1\" - 6'6\" |\n\n## Geometry\n| Frame size | S | M | L | XL |\n|--------------------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 50.6 | 52.4 | 54.3 | 56.2 |\n| B — Seat tube angle | 75.5° | 74.5° | 73.5° | 72.5° |\n| C — Head tube length | 12.0 | 14.0 | 16.0 | 18.0 |\n| D — Head angle | 72.5° | 73.0° | 73.5° | 74.0° |\n| E — Effective top tube | 53.8 | 55.4 | 57.0 | 58.6 |\n| F — Bottom bracket height | 26.5 | 26.5 | 26.5 | 26.5 |\n| G — Bottom bracket drop | 7.0 | 7.0 | 7.0 | 7.0 |\n| H — Chainstay length | 41.0 | 41.0 | 41.0 | 41.0 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 6.0 | 6.0 | 6.0 | 6.0 |\n| K — Wheelbase | 97.1 | 98.7 | 100.2 | 101.8 |\n| L — Standover | 73.8 | 76.2 | 78.5 | 80.8 |\n| M — Frame reach | 38.8 | 39.5 | 40.2 | 40.9 |\n| N — Frame stack | 52.8 | 54.7 | 56.6 | 58.5 |", "price": 1599.99, "tags": [ "bicycle", "road bike" ] }, { "name": "Voltex+ Ultra Lowstep", "shortDescription": "Voltex+ Ultra Lowstep is a high-performance electric hybrid bike designed for riders who seek speed, comfort, and reliability during their everyday rides. Equipped with a powerful and efficient Voltex Drive Pro motor and a fully-integrated 600Wh battery, this e-bike allows you to cover longer distances on a single charge. The Voltex+ Ultra Lowstep comes with premium components that prioritize comfort and safety, such as a suspension seatpost, wide and stable tires, and integrated lights.", "description": "## Overview\n\nIt's right for you if...\nYou want an e-bike that provides a boost for faster rides and effortless usage. Durability is crucial, and you need a bike with one of the most powerful and efficient motors.\n\nThe tech you get\nA lightweight Delta Carbon Fiber frame with an ultra-lowstep design, a Voltex Drive Pro (350W, 75Nm) motor capable of maintaining speeds up to 30 mph, an extended range 600Wh battery integrated into the frame, and a Voltex Control Panel. Additionally, it features a 12-speed Shimano drivetrain, hydraulic disc brakes for optimal all-weather stopping power, a suspension seatpost, wide puncture-resistant tires for added stability, ergonomic grips, a kickstand, lights, and a cargo rack.\n\nThe final word\nThis bike offers enhanced enjoyment and ease of use on long commutes, leisure rides, and adventures. With its extended-range battery, powerful Voltex motor, user-friendly controller, and a seatpost that smooths out road vibrations, it guarantees an exceptional riding experience.\n\n## Features\n\nUltra-fast assistance\n\nExperience speeds up to 30 mph with the cutting-edge Voltex Drive Pro motor, allowing you to breeze through errands, commutes, and joyrides.\n\n## Specs\n\nFrameset\n- Frame: Delta Carbon Fiber, Removable Integrated Battery (RIB), sleek welds, rack & fender mounts, internal routing, kickstand mount, 135x5mm QR\n- Fork: Voltex Alloy, threaded steel steerer, rack mounts, post mount disc, 460mm axle-to-crown, ThruSkew 5mm QR\n- Max compatible fork travel: 50mm\n\nWheels\n- Hub front: Formula DC-20, alloy, 6-bolt, 5x100mm QR\n- Skewer front: 132x5mm QR, ThruSkew\n- Hub rear: Formula DC-22, alloy, 6-bolt, Shimano 8/9/10 freehub, 135x5mm QR\n- Skewer rear: 153x5mm bolt-on\n- Rim: Voltex Connection, double-wall, 32-hole, 20 mm width, Schrader valve\n- Tire: Voltex E6 Hard-Case Lite, reflective, wire bead, 60tpi, 700x50c\n- Max tire size: 700x50mm with or without fenders\n\nDrivetrain\n- Shifter: Shimano Deore XT M8100, 12-speed\n- Rear derailleur: Shimano Deore XT M8100, long cage\n- Crank: Voltex alloy, 170mm length\n- Chainring: FSA, 44T, aluminum with guard\n- Cassette: Shimano Deore XT M8100, 10-51, 12-speed\n- Chain: KMC E12 Turbo\n- Pedal: Voltex Urban pedals\n\nComponents\n- Saddle: Voltex Boulevard\n- Seatpost: Alloy, suspension, 31.6mm, 300mm length\n- Handlebar: Voltex alloy, 31.8mm, comfort sweep, 620mm width (XS, S, M), 660mm width (L)\n- Grips: Voltex Satellite Elite, alloy lock-on\n- Stem: Voltex alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 85mm length (XS, S), 105mm length (M, L)\n- Headset: VP sealed cartridge, 1-1/8'', threaded\n- Brake: Shimano MT520 hydraulic disc\n- Brake rotor: Shimano RT56, 6-bolt, 180mm (XS, S, M, L), 160mm (XS, S, M, L)\n\nAccessories\n- Battery: Voltex PowerTube 600Wh\n- Charger: Voltex compact 2A, 100-240V\n- Computer: Voltex Control Panel\n- Motor: Voltex Drive Pro, 75Nm, 30mph\n- Light: Voltex Solo for e-bike, taillight (XS, S, M, L), Voltex MR8, 180 lumen, 60 lux, LED, headlight (XS, S, M, L)\n- Kickstand: Adjustable length rear mount alloy kickstand\n- Cargo rack: Voltex-compatible alloy rear rack, maximum load 25 kg / 55 lbs\n- Fender: Voltex wide (XS, S, M, L), Voltex plastic (XS, S, M, L)\n\nWeight\n- Weight: M - 20.50 kg / 45.19 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 330 pounds (150 kg).\n\n## Sizing\n\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| XS | 147 - 155 cm 4'10\" - 5'1\" | 69 - 73 cm 27\" - 29\" |\n| S | 155 - 165 cm 5'1\" - 5'5\" | 72 - 78 cm 28\" - 31\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\n\nSizing table\n\n| Frame size number | 40 cm | 45 cm | 50 cm | 55 cm |\n|---------------------------|-------|-------|-------|-------|\n| Frame size letter | XS | S | M | L |\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 38.0 | 43.0 | 48.0 | 53.0 |\n| B — Seat tube angle | 70.5° | 70.5° | 70.5° | 70.5° |\n| C — Head tube length | 15.0 | 15.0 | 17.0 | 19.0 |\n| D — Head angle | 69.2° | 69.2° | 69.2° | 69.2° |\n| E — Effective top tube | 57.2 | 57.7 | 58.8 | 60.0 |\n| F — Bottom bracket height | 30.3 | 30.3 | 30.3 | 30.3 |\n| G — Bottom bracket drop | 6.0 | 6.0 | 6.0 | 6.0 |\n| H — Chainstay length | 48.5 | 48.5 | 48.5 | 48.5 |\n| I — Offset | 5.0 | 5.0 | 5.0 | 5.0 |\n| J — Trail | 9.0 | 9.0 | 9.0 | 9.0 |\n| K — Wheelbase | 111.8 | 112.3 | 113.6 | 114.8 |\n| L — Standover | 42.3 | 42.3 | 42.3 | 42.3 |\n| M — Frame reach | 36.0 | 38.0 | 38.0 | 38.0 |\n| N — Frame stack | 62.0 | 62.0 | 63.9 | 65.8 |\n| Stem length | 8.0 | 8.5 | 8.5 | 10.5 |\n\nPlease note that the specifications and features listed above are subject to change and may vary based on different models and versions of the Voltex+ Ultra Lowstep bike.", "price": 2999.99, "tags": [ "bicycle", "road bike", "professional" ] }, { "name": "SwiftRide Hybrid", "shortDescription": "SwiftRide Hybrid is a versatile and efficient bike designed for riders who want a smooth and enjoyable ride on various terrains. It incorporates advanced technology and high-quality components to provide a comfortable and reliable cycling experience.", "description": "## Overview\n\nIt's right for you if...\nYou are looking for a bike that combines the benefits of an electric bike with the versatility of a hybrid. You value durability, speed, and ease of use.\n\nThe tech you get\nThe SwiftRide Hybrid features a lightweight and durable aluminum frame, making it easy to handle and maneuver. It is equipped with a powerful electric motor that offers a speedy assist, helping you reach speeds of up to 25 mph. The bike comes with a removable and fully-integrated 500Wh battery, providing a long-range capacity for extended rides. It also includes a 10-speed Shimano drivetrain, hydraulic disc brakes for precise stopping power, wide puncture-resistant tires for stability, and integrated lights for enhanced visibility.\n\nThe final word\nThe SwiftRide Hybrid is designed for riders who want a bike that can handle daily commutes, recreational rides, and adventures. With its efficient motor, intuitive controls, and comfortable features, it offers an enjoyable and hassle-free riding experience.\n\n## Features\n\nEfficient electric assist\nExperience the thrill of effortless riding with the powerful electric motor that provides a speedy assist, making your everyday rides faster and more enjoyable.\n\n## Specs\n\nFrameset\n- Frame: Lightweight Aluminum, Removable Integrated Battery (RIB), rack & fender mounts, internal routing, 135x5mm QR\n- Fork: SwiftRide Alloy, threaded steel steerer, rack mounts, post mount disc, 460mm axle-to-crown, ThruSkew 5mm QR\n- Max compatible fork travel: 50mm\n\nWheels\n- Hub front: Formula DC-20, alloy, 6-bolt, 5x100mm QR\n- Skewer front: 132x5mm QR, ThruSkew\n- Hub rear: Formula DC-22, alloy, 6-bolt, Shimano 8/9/10 freehub, 135x5mm QR\n- Skewer rear: 153x5mm bolt-on\n- Rim: SwiftRide Connection, double-wall, 32-hole, 20 mm width, Schrader valve\n- Tire: SwiftRide E6 Hard-Case Lite, reflective, wire bead, 60tpi, 700x50c\n- Max tire size: 700x50mm with or without fenders\n\nDrivetrain\n- Shifter: Shimano Deore M4100, 10 speed\n- Rear derailleur: Shimano Deore M5120, long cage\n- Crank: ProWheel alloy, 170mm length\n- Chainring: FSA, 42T, steel w/guard\n- Cassette: Shimano Deore M4100, 11-42, 10 speed\n- Chain: KMC E10\n- Pedal: SwiftRide City pedals\n\nComponents\n- Saddle: SwiftRide Boulevard\n- Seatpost: Alloy, suspension, 31.6mm, 300mm length\n- Handlebar:\n - Size: XS, S, M - SwiftRide alloy, 31.8mm, comfort sweep, 620mm width\n - Size: L - SwiftRide alloy, 31.8mm, comfort sweep, 660mm width\n- Grips: SwiftRide Satellite Elite, alloy lock-on\n- Stem:\n - Size: XS, S - SwiftRide alloy quill, 31.8mm clamp, adjustable rise, 85mm length\n - Size: M, L - SwiftRide alloy quill, 31.8mm clamp, adjustable rise, 105mm length\n- Headset: VP sealed cartridge, 1-1/8'', threaded\n- Brake: Shimano MT200 hydraulic disc\n- Brake rotor:\n - Size: XS, S, M, L - Shimano RT26, 6-bolt, 180mm\n - Size: XS, S, M, L - Shimano RT26, 6-bolt, 160mm\n\nAccessories\n- Battery: SwiftRide PowerTube 500Wh\n- Charger: SwiftRide compact 2A, 100-240V\n- Computer: SwiftRide Purion\n- Motor: SwiftRide Performance Line Sport, 65Nm, 25mph\n- Light:\n - Size: XS, S, M, L - SwiftRide SOLO for e-bike, taillight\n - Size: XS, S, M, L - SwiftRide MR8, 180 lumen, 60 lux, LED, headlight\n- Kickstand: Adjustable length rear mount alloy kickstand\n- Cargo rack: SwiftRide-compatible alloy rear rack, maximum load 25 kg / 55 lbs\n- Fender:\n - Size: XS, S, M, L - SwiftRide wide\n - Size: XS, S, M, L - SwiftRide plastic\n\nWeight\n- Weight: M - 22.30 kg / 49.17 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| XS | 147 - 155 cm (4'10\" - 5'1\") | 69 - 73 cm (27\" - 29\") |\n| S | 155 - 165 cm (5'1\" - 5'5\") | 72 - 78 cm (28\" - 31\") |\n| M | 165 - 175 cm (5'5\" - 5'9\") | 77 - 83 cm (30\" - 33\") |\n| L | 175 - 186 cm (5'9\" - 6'1\") | 82 - 88 cm (32\" - 35\") |\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\n\nSizing table\n| Frame size number | 40 cm | 45 cm | 50 cm | 55 cm |\n|---------------------------|-------|-------|-------|-------|\n| Frame size letter | XS | S | M | L |\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 39.0 | 44.0 | 50.0 | 55.0 |\n| B — Seat tube angle | 71.0° | 71.0° | 71.0° | 71.0° |\n| C — Head tube length | 16.0 | 16.0 | 18.0 | 20.0 |\n| D — Head angle | 68.2° | 68.2° | 68.2° | 68.2° |\n| E — Effective top tube | 58.2 | 58.7 | 59.8 | 61.0 |\n| F — Bottom bracket height | 29.4 | 29.4 | 29.4 | 29.4 |\n| G — Bottom bracket drop | 6.5 | 6.5 | 6.5 | 6.5 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 9.5 | 9.5 | 9.5 | 9.5 |\n| K — Wheelbase | 112.2 | 112.7 | 114.0 | 115.2 |\n| L — Standover | 43.3 | 43.3 | 43.3 | 43.3 |\n| M — Frame reach | 36.5 | 38.5 | 38.5 | 38.5 |\n| N — Frame stack | 63.0 | 63.0 | 64.9 | 66.8 |\n| Stem length | 8.5 | 9.0 | 9.0 | 11.0 |", "price": 3999.99, "tags": [ "bicycle", "mountain bike", "professional" ] }, { "name": "RoadRunner E-Speed Lowstep", "shortDescription": "RoadRunner E-Speed Lowstep is a high-performance electric hybrid designed for riders seeking speed and excitement on their daily rides. It is equipped with a powerful and reliable ThunderBolt drive unit that offers exceptional acceleration. The bike features a fully-integrated 500Wh battery, allowing riders to cover longer distances on a single charge. With its comfortable and safe components, including a suspension seatpost, wide and stable tires, and integrated lights, the RoadRunner E-Speed Lowstep ensures a smooth and enjoyable ride.", "description": "## Overview\n\nIt's right for you if...\nYou're looking for an e-bike that provides an extra boost to reach your destination quickly and effortlessly. You prioritize durability and want a bike with one of the fastest motors available.\n\nThe tech you get\nA lightweight and sturdy ThunderBolt aluminum frame with a lowstep geometry. The bike is equipped with a ThunderBolt Performance Sport (250W, 65Nm) drive unit capable of reaching speeds up to 28 mph. It features a long-range 500Wh battery fully integrated into the frame and a ThunderBolt controller. Additionally, the bike has a 10-speed Shimano drivetrain, hydraulic disc brakes for reliable stopping power in all weather conditions, a suspension seatpost, wide puncture-resistant tires for stability, ergonomic grips, a kickstand, lights, and a rack and fenders.\n\nThe final word\nThe RoadRunner E-Speed Lowstep is designed to provide enjoyment and ease of use on longer commutes, recreational rides, and adventurous journeys. Its long-range battery, fast ThunderBolt motor, intuitive controller, and road-smoothing suspension seatpost make it the perfect choice for riders seeking both comfort and speed.\n\n## Features\n\nSuper speedy assist\n\nThe ThunderBolt Performance Sport drive unit allows you to accelerate up to 28mph, making errands, commutes, and joyrides a breeze.\n\n## Specs\n\nFrameset\n- Frame: ThunderBolt Smooth Aluminum, Removable Integrated Battery (RIB), sleek welds, rack & fender mounts, internal routing, kickstand mount, 135x5mm QR\n- Fork: RoadRunner Alloy, threaded steel steerer, rack mounts, post mount disc, 460mm axle-to-crown, ThruSkew 5mm QR\n- Max compatible fork travel: 50mm\n\nWheels\n- Hub front: ThunderBolt DC-20, alloy, 6-bolt, 5x100mm QR\n- Skewer front: 132x5mm QR, ThruSkew\n- Hub rear: ThunderBolt DC-22, alloy, 6-bolt, Shimano 8/9/10 freehub, 135x5mm QR\n- Skewer rear: 153x5mm bolt-on\n- Rim: ThunderBolt Connection, double-wall, 32-hole, 20 mm width, Schrader valve\n- Tire: ThunderBolt E6 Hard-Case Lite, reflective, wire bead, 60tpi, 700x50c\n- Max tire size: 700x50mm with or without fenders\n\nDrivetrain\n- Shifter: Shimano Deore M4100, 10 speed\n- Rear derailleur: Shimano Deore M5120, long cage\n- Crank: ProWheel alloy, 170mm length\n- Chainring: FSA, 42T, steel w/guard\n- Cassette: Shimano Deore M4100, 11-42, 10 speed\n- Chain: KMC E10\n- Pedal: RoadRunner City pedals\n\nComponents\n- Saddle: RoadRunner Boulevard\n- Seatpost: Alloy, suspension, 31.6mm, 300mm length\n- Handlebar:\n - Size: XS, S, M - RoadRunner alloy, 31.8mm, comfort sweep, 620mm width\n - Size: L - RoadRunner alloy, 31.8mm, comfort sweep, 660mm width\n- Grips: RoadRunner Satellite Elite, alloy lock-on\n- Stem:\n - Size: XS, S - RoadRunner alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 85mm length\n - Size: M, L - RoadRunner alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 105mm length\n- Headset: VP sealed cartridge, 1-1/8'', threaded\n- Brake: Shimano MT200 hydraulic disc\n- Brake rotor:\n - Size: XS, S, M, L - Shimano RT26, 6-bolt, 180mm\n - Size: XS, S, M, L - Shimano RT26, 6-bolt, 160mm\n\nAccessories\n- Battery: ThunderBolt PowerTube 500Wh\n- Charger: ThunderBolt compact 2A, 100-240V\n- Computer: ThunderBolt Purion\n- Motor: ThunderBolt Performance Line Sport, 65Nm, 28mph\n- Light:\n - Size: XS, S, M, L - ThunderBolt SOLO for e-bike, taillight\n - Size: XS, S, M, L - ThunderBolt MR8, 180 lumen, 60 lux, LED, headlight\n- Kickstand: Adjustable length rear mount alloy kickstand\n- Cargo rack: MIK-compatible alloy rear rack, maximum load 25 kg / 55 lbs\n- Fender:\n - Size: XS, S, M, L - RoadRunner wide\n - Size: XS, S, M, L - RoadRunner plastic\n\nWeight\n- Weight: M - 22.30 kg / 49.17 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| XS | 147 - 155 cm 4'10\" - 5'1\" | 69 - 73 cm 27\" - 29\" |\n| S | 155 - 165 cm 5'1\" - 5'5\" | 72 - 78 cm 28\" - 31\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\n\nSizing table\n| Frame size number | 40 cm | 45 cm | 50 cm | 55 cm |\n|---------------------------|-------|-------|-------|-------|\n| Frame size letter | XS | S | M | L |\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 39.0 | 44.0 | 50.0 | 55.0 |\n| B — Seat tube angle | 71.0° | 71.0° | 71.0° | 71.0° |\n| C — Head tube length | 16.0 | 16.0 | 18.0 | 20.0 |\n| D — Head angle | 68.2° | 68.2° | 68.2° | 68.2° |\n| E — Effective top tube | 58.2 | 58.7 | 59.8 | 61.0 |\n| F — Bottom bracket height | 29.4 | 29.4 | 29.4 | 29.4 |\n| G — Bottom bracket drop | 6.5 | 6.5 | 6.5 | 6.5 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 9.5 | 9.5 | 9.5 | 9.5 |\n| K — Wheelbase | 112.2 | 112.7 | 114.0 | 115.2 |\n| L — Standover | 43.3 | 43.3 | 43.3 | 43.3 |\n| M — Frame reach | 36.5 | 38.5 | 38.5 | 38.5 |\n| N — Frame stack | 63.0 | 63.0 | 64.9 | 66.8 |\n| Stem length | 8.5 | 9.0 | 9.0 | 11.0 |", "price": 4999.99, "tags": [ "bicycle", "road bike", "professional" ] }, { "name": "Hyperdrive Turbo X1", "shortDescription": "Hyperdrive Turbo X1 is a high-performance electric bike designed for riders seeking an exhilarating experience on their daily rides. It features a powerful and efficient Hyperdrive Sport drive unit and a sleek, integrated 500Wh battery for extended range. This e-bike is equipped with top-of-the-line components prioritizing comfort and safety, including a suspension seatpost, wide and stable tires, and integrated lights.", "description": "## Overview\n\nIt's right for you if...\nYou crave the thrill of an e-bike that can accelerate rapidly, reaching high speeds effortlessly. You value durability and are looking for a bike that is equipped with one of the fastest motors available.\n\nThe tech you get\nA lightweight Hyper Alloy frame with a lowstep geometry, a Hyperdrive Sport (300W, 70Nm) drive unit capable of maintaining speeds up to 30 mph, a long-range 500Wh battery seamlessly integrated into the frame, and an intuitive Hyper Control controller. Additionally, it features a 10-speed Shimano drivetrain, hydraulic disc brakes for reliable stopping power in all weather conditions, a suspension seatpost, wide puncture-resistant tires for enhanced stability, ergonomic grips, a kickstand, lights, and a rack and fenders.\n\nThe final word\nThis bike is designed for riders seeking enjoyment and convenience on longer commutes, recreational rides, and thrilling adventures. With its long-range battery, high-speed motor, user-friendly controller, and smooth-riding suspension seatpost, the Hyperdrive Turbo X1 guarantees an exceptional e-biking experience.\n\n## Features\n\nHyperboost Acceleration\nExperience adrenaline-inducing rides with the powerful Hyperdrive Sport drive unit that enables quick acceleration and effortless cruising through errands, commutes, and joyrides.\n\n## Specs\n\nFrameset\nFrame\tHyper Alloy, Removable Integrated Battery (RIB), seamless welds, rack & fender mounts, internal routing, kickstand mount, 135x5mm QR\nFork\tHyper Alloy, threaded steel steerer, rack mounts, post mount disc, 460mm axle-to-crown, ThruSkew 5mm QR\nMax compatible fork travel\t50mm\n\nWheels\nHub front\tFormula DC-20, alloy, 6-bolt, 5x100mm QR\nSkewer front\t132x5mm QR, ThruSkew\nHub rear\tFormula DC-22, alloy, 6-bolt, Shimano 8/9/10 freehub, 135x5mm QR\nSkewer rear\t153x5mm bolt-on\nRim\tHyper Connection, double-wall, 32-hole, 20 mm width, Schrader valve\nTire\tHyper E6 Hard-Case Lite, reflective, wire bead, 60tpi, 700x50c\nMax tire size\t700x50mm with or without fenders\n\nDrivetrain\nShifter\tShimano Deore M4100, 10 speed\nRear derailleur\tShimano Deore M5120, long cage\nCrank\tProWheel alloy, 170mm length\nChainring\tFSA, 42T, steel w/guard\nCassette\tShimano Deore M4100, 11-42, 10 speed\nChain\tKMC E10\nPedal\tHyper City pedals\n\nComponents\nSaddle\tHyper Boulevard\nSeatpost\tAlloy, suspension, 31.6mm, 300mm length\n*Handlebar\tSize: XS, S, M\nHyper alloy, 31.8mm, comfort sweep, 620mm width\nSize: L\nHyper alloy, 31.8mm, comfort sweep, 660mm width\nGrips\tHyper Satellite Elite, alloy lock-on\n*Stem\tSize: XS, S\nHyper alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 85mm length\nSize: M, L\nHyper alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 105mm length\nHeadset\tVP sealed cartridge, 1-1/8'', threaded\nBrake\tShimano MT200 hydraulic disc\n*Brake rotor\tSize: XS, S, M, L\nShimano RT26, 6-bolt,180mm\nSize: XS, S, M, L\nShimano RT26, 6-bolt,160mm\n\nAccessories\nBattery\tHyper PowerTube 500Wh\nCharger\tHyper compact 2A, 100-240V\nComputer\tHyper Control\nMotor\tHyperdrive Sport, 70Nm, 30mph\n*Light\tSize: XS, S, M, L\nSpanninga SOLO for e-bike, taillight\nSize: XS, S, M, L\nHerrmans MR8, 180 lumen, 60 lux, LED, headlight\nKickstand\tAdjustable length rear mount alloy kickstand\nCargo rack\tMIK-compatible alloy rear rack, maximum load 25 kg / 55 lbs\n*Fender\tSize: XS, S, M, L\nSKS wide\nSize: XS, S, M, L\nSKS plastic\n\nWeight\nWeight\tM - 22.30 kg / 49.17 lbs\nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| XS | 147 - 155 cm 4'10\" - 5'1\" | 69 - 73 cm 27\" - 29\" |\n| S | 155 - 165 cm 5'1\" - 5'5\" | 72 - 78 cm 28\" - 31\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\n\n| Frame size number | 40 cm | 45 cm | 50 cm | 55 cm |\n|---------------------------|-------|-------|-------|-------|\n| Frame size letter | XS | S | M | L |\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 39.0 | 44.0 | 50.0 | 55.0 |\n| B — Seat tube angle | 71.0° | 71.0° | 71.0° | 71.0° |\n| C — Head tube length | 16.0 | 16.0 | 18.0 | 20.0 |\n| D — Head angle | 68.2° | 68.2° | 68.2° | 68.2° |\n| E — Effective top tube | 58.2 | 58.7 | 59.8 | 61.0 |\n| F — Bottom bracket height | 29.4 | 29.4 | 29.4 | 29.4 |\n| G — Bottom bracket drop | 6.5 | 6.5 | 6.5 | 6.5 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 9.5 | 9.5 | 9.5 | 9.5 |\n| K — Wheelbase | 112.2 | 112.7 | 114.0 | 115.2 |\n| L — Standover | 43.3 | 43.3 | 43.3 | 43.3 |\n| M — Frame reach | 36.5 | 38.5 | 38.5 | 38.5 |\n| N — Frame stack | 63.0 | 63.0 | 64.9 | 66.8 |\n| Stem length | 8.5 | 9.0 | 9.0 | 11.0 |", "price": 1999.99, "tags": [ "bicycle", "city bike", "professional" ] }, { "name": "Horizon+ Evo Lowstep", "shortDescription": "The Horizon+ Evo Lowstep is a versatile electric hybrid bike designed for riders seeking a thrilling and efficient riding experience on a variety of terrains. With its powerful Bosch Performance Line Sport drive unit and integrated 500Wh battery, this e-bike enables riders to cover long distances with ease. Equipped with features prioritizing comfort and safety, such as a suspension seatpost, stable tires, and integrated lights, the Horizon+ Evo Lowstep is a reliable companion for everyday rides.", "description": "## Overview\n\nIt's right for you if...\nYou desire the convenience and speed of an e-bike to enhance your riding, and you want an intuitive and durable bicycle. You prioritize having one of the fastest motors developed by Bosch.\n\nThe tech you get\nA lightweight Alpha Smooth Aluminum frame with a lowstep geometry, a Bosch Performance Line Sport (250W, 65Nm) drive unit capable of sustaining speeds up to 28 mph, a fully encased 500Wh battery integrated into the frame, and a Bosch Purion controller. Additionally, it features a 10-speed Shimano drivetrain, hydraulic disc brakes for reliable stopping power in all weather conditions, a suspension seatpost, wide puncture-resistant tires for improved stability, ergonomic grips, a kickstand, lights, and a rack and fenders.\n\nThe final word\nThe Horizon+ Evo Lowstep offers an enjoyable and user-friendly riding experience for longer commutes, recreational rides, and adventures. It boasts an extended range battery, a high-performance Bosch motor, an intuitive controller, and a suspension seatpost for a smooth ride on various road surfaces.\n\n## Features\n\nSuper speedy assist\nExperience effortless cruising through errands, commutes, and joyrides with the new Bosch Performance Sport drive unit, allowing acceleration of up to 28 mph.\n\n## Specs\n\nFrameset\n- Frame: Alpha Platinum Aluminum, Removable Integrated Battery (RIB), smooth welds, rack & fender mounts, internal routing, kickstand mount, 135x5mm QR\n- Fork: Horizon Alloy, threaded steel steerer, rack mounts, post mount disc, 460mm axle-to-crown, ThruSkew 5mm QR\n- Max compatible fork travel: 50mm\n\nWheels\n- Front Hub: Formula DC-20, alloy, 6-bolt, 5x100mm QR\n- Front Skewer: 132x5mm QR, ThruSkew\n- Rear Hub: Formula DC-22, alloy, 6-bolt, Shimano 8/9/10 freehub, 135x5mm QR\n- Rear Skewer: 153x5mm bolt-on\n- Rim: Bontrager Connection, double-wall, 32-hole, 20mm width, Schrader valve\n- Tire: Bontrager E6 Hard-Case Lite, reflective, wire bead, 60tpi, 700x50c\n- Max tire size: 700x50mm with or without fenders\n\nDrivetrain\n- Shifter: Shimano Deore M4100, 10-speed\n- Rear Derailleur: Shimano Deore M5120, long cage\n- Crank: ProWheel alloy, 170mm length\n- Chainring: FSA, 42T, steel w/guard\n- Cassette: Shimano Deore M4100, 11-42, 10-speed\n- Chain: KMC E10\n- Pedal: Bontrager City pedals\n\nComponents\n- Saddle: Bontrager Boulevard\n- Seatpost: Alloy, suspension, 31.6mm, 300mm length\n- Handlebar:\n - Size: XS, S, M - Bontrager alloy, 31.8mm, comfort sweep, 620mm width\n - Size: L - Bontrager alloy, 31.8mm, comfort sweep, 660mm width\n- Grips: Bontrager Satellite Elite, alloy lock-on\n- Stem:\n - Size: XS, S - Bontrager alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 85mm length\n - Size: M, L - Bontrager alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 105mm length\n- Headset: VP sealed cartridge, 1-1/8\", threaded\n- Brake: Shimano MT200 hydraulic disc\n- Brake rotor:\n - Size: XS, S, M, L - Shimano RT26, 6-bolt, 180mm\n - Size: XS, S, M, L - Shimano RT26, 6-bolt, 160mm\n\nAccessories\n- Battery: Bosch PowerTube 500Wh\n- Charger: Bosch compact 2A, 100-240V\n- Computer: Bosch Purion\n- Motor: Bosch Performance Line Sport, 65Nm, 28mph\n- Light:\n - Size: XS, S, M, L - Spanninga SOLO for e-bike, taillight\n - Size: XS, S, M, L - Herrmans MR8, 180 lumen, 60 lux, LED, headlight\n- Kickstand: Adjustable length rear mount alloy kickstand\n- Cargo rack: MIK-compatible alloy rear rack, maximum load 25 kg / 55 lbs\n- Fender:\n - Size: XS, S, M, L - SKS wide\n - Size: XS, S, M, L - SKS plastic\n\nWeight\n- Weight: M - 22.30 kg / 49.17 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| XS | 147 - 155 cm 4'10\" - 5'1\" | 69 - 73 cm 27\" - 29\" |\n| S | 155 - 165 cm 5'1\" - 5'5\" | 72 - 78 cm 28\" - 31\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\nSizing table\n| Frame size number | 40 cm | 45 cm | 50 cm | 55 cm |\n|---------------------------|-------|-------|-------|-------|\n| Frame size letter | XS | S | M | L |\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 39.0 | 44.0 | 50.0 | 55.0 |\n| B — Seat tube angle | 71.0° | 71.0° | 71.0° | 71.0° |\n| C — Head tube length | 16.0 | 16.0 | 18.0 | 20.0 |\n| D — Head angle | 68.2° | 68.2° | 68.2° | 68.2° |\n| E — Effective top tube | 58.2 | 58.7 | 59.8 | 61.0 |\n| F — Bottom bracket height | 29.4 | 29.4 | 29.4 | 29.4 |\n| G — Bottom bracket drop | 6.5 | 6.5 | 6.5 | 6.5 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 9.5 | 9.5 | 9.5 | 9.5 |\n| K — Wheelbase | 112.2 | 112.7 | 114.0 | 115.2 |\n| L — Standover | 43.3 | 43.3 | 43.3 | 43.3 |\n| M — Frame reach | 36.5 | 38.5 | 38.5 | 38.5 |\n| N — Frame stack | 63.0 | 63.0 | 64.9 | 66.8 |\n| Stem length | 8.5 | 9.0 | 9.0 | 11.0 |", "price": 4499.99, "tags": [ "bicycle", "road bike", "professional" ] }, { "name": "FastRider X1", "shortDescription": "FastRider X1 is a high-performance e-bike designed for riders seeking speed and long-distance capabilities. Equipped with a powerful motor and a high-capacity battery, the FastRider X1 is perfect for daily commuters and e-bike enthusiasts. It boasts a sleek and functional design, making it a great alternative to car transportation. The bike also features a smartphone controller for easy navigation and entertainment options.", "description": "## Overview\nIt's right for you if...\nYou're looking for an e-bike that offers both speed and endurance. The FastRider X1 comes with a high-performance motor and a long-lasting battery, making it ideal for long-distance rides.\n\nThe tech you get\nThe FastRider X1 features a state-of-the-art motor and a spacious battery, ensuring a fast and efficient ride.\n\nThe final word\nWith the powerful motor and long-range battery, the FastRider X1 allows you to cover more distance at higher speeds.\n\n## Features\nConnect Your Ride with the FastRider App\nDownload the FastRider app and transform your smartphone into an on-board computer. Easily dock and charge your phone with the smartphone controller, and use the thumb pad on your handlebar to make calls, listen to music, get turn-by-turn directions, and more. The app also allows you to connect with fitness and health apps, syncing your routes and ride data.\n\nGoodbye, Car. Hello, Extended Range!\nWith the option to add the Range Boost feature, you can attach a second long-range battery to your FastRider X1, doubling the distance and time between charges. This enhancement allows you to ride longer, commute farther, and take on more adventurous routes.\n\nWhat is the range?\nTo estimate the distance you can travel on a single charge, use our range calculator tool. It automatically fills in the variables for this specific bike model and assumes an average rider, but you can adjust the settings to get the most accurate estimate for your needs.\n\n## Specifications\nFrameset\n- Frame: High-performance hydroformed alloy, Removable Integrated Battery, Range Boost-compatible, internal cable routing, Motor Armour, post-mount disc, 135x5 mm QR\n- Fork: FastRider rigid alloy fork, 1-1/8'' steel steerer, 100x15mm thru axle, post mount disc brake\n- Max compatible fork travel: 63mm\n\nWheels\n- Front Hub: FastRider sealed bearing, 32-hole 15mm alloy thru-axle\n- Front Skewer: FastRider Switch thru axle, removable lever\n- Rear Hub: FastRider alloy, sealed bearing, 6-bolt, 135x5mm QR\n- Rear Skewer: 148x5mm bolt-on\n- Rim: FastRider MD35, tubeless compatible, 32-hole, 35mm width, Presta valve\n- Spokes: Size: M, L, XL - 14g stainless steel, black\n- Tire: FastRider E6 Hard-Case Lite, reflective strip, 27.5x2.40''\n- Max tire size: 27.5x2.40\"\n\nDrivetrain\n- Shifter: Shimano Deore M4100, 10 speed\n- Rear derailleur: Size: M, L, XL - Shimano Deore M5120, long cage\n- Crank: Size: M - FastRider alloy, 170mm length / Size: L, XL - FastRider alloy, 175mm length\n- Chainring: FastRider 46T narrow/wide alloy, w/alloy guard\n- Cassette: Size: M, L, XL - Shimano Deore M4100, 11-42, 10 speed\n- Chain: Size: M, L, XL - KMC E10 / Size: M, L, XL - KMC X10e\n- Pedal: Size: M, L, XL - FastRider City pedals / Size: M, L, XL - Wellgo C157, boron axle, plastic body / Size: M, L, XL - slip-proof aluminum pedals with reflectors\n- Max chainring size: 1x: 48T\n\nComponents\n- Saddle: FastRider Commuter Comp\n- Seatpost: FastRider Comp, 6061 alloy, 31.6mm, 8mm offset, 330mm length\n- Handlebar: Size: M - FastRider alloy, 31.8mm, 15mm rise, 600mm width / Size: L, XL - FastRider alloy, 31.8mm, 15mm rise, 660mm width\n- Grips: FastRider Satellite Elite, alloy lock-on\n- Stem: Size: M - FastRider alloy, 31.8mm, Blendr compatible, 7-degree, 70mm length / Size: L - FastRider alloy, 31.8mm, Blendr compatible, 7-degree, 90mm length / Size: XL - FastRider alloy, 31.8mm, Blendr compatible, 7-degree, 100mm length\n- Headset: Size: M, L, XL - FSA IS-2 alloy, integrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom / Size: M, L, XL - FSA Integrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom\n- Brake: Shimano MT520 4-piston hydraulic disc, post-mount, 180mm rotor\n- Brake rotor: Shimano RT56, 6-bolt, 180mm\n- Rotor size: Max brake rotor sizes: 180mm front & rear\n\nAccessories\n- Battery: FastRider PowerTube 625Wh\n- Charger: FastRider standard 4A, 100-240V\n- Motor: FastRider Performance Speed, 85 Nm, 28 mph / 45 kph\n- Light: Size: M, L, XL - FastRider taillight, 50 lumens / Size: M, L, XL - FastRider headlight, 500 lumens\n- Kickstand: Size: M, L, XL - Rear mount, alloy / Size: M, L, XL - Adjustable length alloy kickstand\n- Cargo rack: FastRider integrated rear rack, aluminum\n- Fender: FastRider custom aluminum\n\nWeight\n- Weight: M - 25.54 kg / 56.3 lbs\n\nWeight limit\n- This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:------------------------:|:--------------------:|\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n| XL | 186 - 197 cm 6'1\" - 6'6\" | 87 - 93 cm 34\" - 37\" |\n\n## Geometry\n| Frame size letter | M | L | XL |\n|---------------------------|-------|-------|-------|\n| Wheel size | 27.5\" | 27.5\" | 27.5\" |\n| A — Seat tube | 44.6 | 49.1 | 53.4 |\n| B — Seat tube angle | 73.0° | 73.0° | 73.0° |\n| C — Head tube length | 16.5 | 19.5 | 23.0 |\n| D — Head angle | 69.5° | 70.0° | 70.5° |\n| E — Effective top tube | 59.5 | 60.7 | 62.2 |\n| F — Bottom bracket height | 29.5 | 29.5 | 29.5 |\n| G — Bottom bracket drop | 6.0 | 6.0 | 6.0 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.4 | 4.4 | 4.4 |\n| J — Trail | 8.6 | 8.1 | 7.9 |\n| K — Wheelbase | 114.6 | 115.0 | 116.4 |\n| L — Standover | 79.5 | 83.7 | 87.9 |\n| M — Frame reach | 40.5 | 40.8 | 41.2 |\n| N — Frame stack | 62.3 | 65.2 | 68.8 |", "price": 5499.99, "tags": [ "bicycle", "mountain bike", "professional" ] }, { "name": "SonicRide 8S", "shortDescription": "SonicRide 8S is a high-performance e-bike designed for riders who crave speed and long-distance capabilities. The advanced SonicDrive motor provides powerful assistance up to 28 mph, combined with a durable and long-lasting battery for extended rides. With its sleek design and thoughtful features, the SonicRide 8S is perfect for those who prefer the freedom of riding a bike over driving a car. Plus, it comes equipped with a smartphone controller for easy navigation, music, and more.", "description": "## Overview\nIt's right for you if...\nYou want a fast and efficient e-bike that can take you long distances. The SonicRide 8S features a hydroformed aluminum frame with a concealed 625Wh battery, a high-powered SonicDrive motor, and a Smartphone Controller. It also includes essential accessories such as lights, fenders, and a rear rack.\n\nThe tech you get\nThe SonicRide 8S is equipped with the fastest SonicDrive motor, ensuring exhilarating rides at high speeds. The long-range battery is perfect for commuters and riders looking to explore new horizons.\n\nThe final word\nWith the SonicDrive motor and long-lasting battery, you can enjoy extended rides at higher speeds.\n\n## Features\n\nConnect Your Ride with SonicRide App\nDownload the SonicRide app and transform your phone into an onboard computer. Simply attach it to the Smartphone Controller for docking and charging. Use the thumb pad on your handlebar to control calls, music, directions, and more. The Bluetooth® wireless technology allows you to connect with fitness and health apps, syncing your routes and ride data.\n\nSay Goodbye to Limited Range with Range Boost!\nExperience the convenience of Range Boost, an additional long-range 500Wh battery that seamlessly attaches to your bike's down tube. This upgrade allows you to double your distance and time between charges, enabling longer commutes and more adventurous rides. Range Boost is compatible with select SonicRide electric bike models.\n\nWhat is the range?\nFor an accurate estimate of how far you can ride on a single charge, use SonicRide's range calculator. We have pre-filled the variables for this specific bike model and the average rider, but you can adjust them to obtain the most accurate estimate.\n\n## Specifications\nFrameset\n- Frame: High-performance hydroformed alloy, Removable Integrated Battery, Range Boost-compatible, internal cable routing, Motor Armour, post-mount disc, 135x5 mm QR\n- Fork: SonicRide rigid alloy fork, 1-1/8'' steel steerer, 100x15mm thru axle, post mount disc brake\n- Max compatible fork travel: 63mm\n\nWheels\n- Front Hub: SonicRide sealed bearing, 32-hole 15mm alloy thru-axle\n- Front Skewer: SonicRide Switch thru axle, removable lever\n- Rear Hub: SonicRide alloy, sealed bearing, 6-bolt, 135x5mm QR\n- Rear Skewer: 148x5mm bolt-on\n- Rim: SonicRide MD35, tubeless compatible, 32-hole, 35mm width, Presta valve\n- Spokes: Size: M, L, XL - 14g stainless steel, black\n- Tire: SonicRide E6 Hard-Case Lite, reflective strip, 27.5x2.40''\n- Max tire size: 27.5x2.40\"\n\nDrivetrain\n- Shifter: Shimano Deore M4100, 10 speed\n- Rear Derailleur: Size: M, L, XL - Shimano Deore M5120, long cage\n- Crank: Size: M - SonicRide alloy, 170mm length; Size: L, XL - SonicRide alloy, 175mm length\n- Chainring: SonicRide 46T narrow/wide alloy, with alloy guard\n- Cassette: Size: M, L, XL - Shimano Deore M4100, 11-42, 10 speed\n- Chain: Size: M, L, XL - KMC E10; Size: M, L, XL - KMC X10e\n- Pedal: Size: M, L, XL - SonicRide City pedals; Size: M, L, XL - Wellgo C157, boron axle, plastic body; Size: M, L, XL - slip-proof aluminum pedals with reflectors\n- Max chainring size: 1x: 48T\n\nComponents\n- Saddle: SonicRide Commuter Comp\n- Seatpost: SonicRide Comp, 6061 alloy, 31.6mm, 8mm offset, 330mm length\n- Handlebar: Size: M - SonicRide alloy, 31.8mm, 15mm rise, 600mm width; Size: L, XL - SonicRide alloy, 31.8mm, 15mm rise, 660mm width\n- Grips: SonicRide Satellite Elite, alloy lock-on\n- Stem: Size: M - SonicRide alloy, 31.8mm, Blendr compatible, 7-degree, 70mm length; Size: L - SonicRide alloy, 31.8mm, Blendr compatible, 7-degree, 90mm length; Size: XL - SonicRide alloy, 31.8mm, Blendr compatible, 7-degree, 100mm length\n- Headset: Size: M, L, XL - SonicRide IS-2 alloy, integrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom; Size: M, L, XL - SonicRide Integrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom\n- Brake: Shimano MT520 4-piston hydraulic disc, post-mount, 180mm rotor\n- Brake rotor: Shimano RT56, 6-bolt, 180mm\n- Rotor size: Max brake rotor sizes: 180mm front & rear\n\nAccessories\n- Battery: SonicRide PowerTube 625Wh\n- Charger: SonicRide standard 4A, 100-240V\n- Motor: SonicRide Performance Speed, 85 Nm, 28 mph / 45 kph\n- Light: Size: M, L, XL - SonicRide Lync taillight, 50 lumens; Size: M, L, XL - SonicRide Lync headlight, 500 lumens\n- Kickstand: Size: M, L, XL - Rear mount, alloy; Size: M, L, XL - Adjustable length alloy kickstand\n- Cargo rack: SonicRide integrated rear rack, aluminum\n- Fender: SonicRide custom aluminum\n\nWeight\n- Weight: M - 25.54 kg / 56.3 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:------------------------:|:--------------------:|\n| M | 165 - 175 cm / 5'5\" - 5'9\" | 77 - 83 cm / 30\" - 33\" |\n| L | 175 - 186 cm / 5'9\" - 6'1\" | 82 - 88 cm / 32\" - 35\" |\n| XL | 186 - 197 cm / 6'1\" - 6'6\" | 87 - 93 cm / 34\" - 37\" |\n\n## Geometry\n| Frame size letter | M | L | XL |\n|---------------------------|-------|-------|-------|\n| Wheel size | 27.5\" | 27.5\" | 27.5\" |\n| A — Seat tube | 44.6 | 49.1 | 53.4 |\n| B — Seat tube angle | 73.0° | 73.0° | 73.0° |\n| C — Head tube length | 16.5 | 19.5 | 23.0 |\n| D — Head angle | 69.5° | 70.0° | 70.5° |\n| E — Effective top tube | 59.5 | 60.7 | 62.2 |\n| F — Bottom bracket height | 29.5 | 29.5 | 29.5 |\n| G — Bottom bracket drop | 6.0 | 6.0 | 6.0 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.4 | 4.4 | 4.4 |\n| J — Trail | 8.6 | 8.1 | 7.9 |\n| K — Wheelbase | 114.6 | 115.0 | 116.4 |\n| L — Standover | 79.5 | 83.7 | 87.9 |\n| M — Frame reach | 40.5 | 40.8 | 41.2 |", "price": 5999.99, "tags": [ "bicycle", "road bike", "professional" ] }, { "name": "SwiftVolt Pro", "shortDescription": "SwiftVolt Pro is a high-performance e-bike designed for riders seeking a thrilling and fast riding experience. Equipped with a powerful SwiftDrive motor that provides assistance up to 30 mph and a long-lasting battery, this bike is perfect for long-distance commuting and passionate e-bike enthusiasts. The sleek and innovative design features cater specifically to individuals who prioritize cycling over driving. Additionally, the bike is seamlessly integrated with your smartphone, allowing you to use it for navigation, music, and more.", "description": "## Overview\nThis bike is ideal for you if:\n- You desire a sleek and modern hydroformed aluminum frame that houses a 700Wh battery.\n- You want to maintain high speeds of up to 30 mph with the assistance of the SwiftDrive motor.\n- You appreciate the convenience of using your smartphone as a controller, which can be docked and charged on the handlebar.\n\n## Features\n\nConnect with SwiftSync App\nBy downloading the SwiftSync app, your smartphone becomes an interactive on-board computer. Attach it to the handlebar-mounted controller for easy access and charging. With the thumb pad, you can make calls, listen to music, receive turn-by-turn directions, and connect with fitness and health apps to track your routes and ride data via Bluetooth® wireless technology.\n\nEnhanced Range with BoostMax\nBoostMax offers the capability to attach a second 700Wh Swift battery to the downtube of your bike, effectively doubling the distance and time between charges. This allows for extended rides, longer commutes, and more significant adventures. BoostMax is compatible with select Swift electric bike models.\n\nRange Estimation\nFor an estimate of how far you can ride on a single charge, consult the Swift range calculator. The variables are automatically populated based on this bike model and the average rider, but you can modify them to obtain the most accurate estimate.\n\n## Specifications\nFrameset\n- Frame: Lightweight hydroformed alloy, Removable Integrated Battery, BoostMax-compatible, internal cable routing, post-mount disc, 135x5 mm QR\n- Fork: SwiftVolt rigid alloy fork, 1-1/8'' steel steerer, 100x15mm thru-axle, post-mount disc brake\n- Max compatible fork travel: 63mm\n\nWheels\n- Front Hub: Swift sealed bearing, 32-hole 15mm alloy thru-axle\n- Front Skewer: Swift Switch thru-axle, removable lever\n- Rear Hub: Swift alloy, sealed bearing, 6-bolt, 135x5mm QR\n- Rear Skewer: 148x5mm bolt-on\n- Rim: SwiftRim, tubeless compatible, 32-hole, 35mm width, Presta valve\n- Spokes: 14g stainless steel, black\n- Tire: Swift E6 Hard-Case Lite, reflective strip, 27.5x2.40''\n- Max tire size: 27.5x2.40\"\n\nDrivetrain\n- Shifter: Shimano Deore M4100, 10 speed\n- Rear Derailleur: Shimano Deore M5120, long cage\n- Crank: Swift alloy, 170mm length\n- Chainring: Swift 46T narrow/wide alloy, w/alloy guard\n- Cassette: Shimano Deore M4100, 11-42, 10 speed\n- Chain: KMC E10\n- Pedal: Swift City pedals\n- Max chainring size: 1x: 48T\n\nComponents\n- Saddle: Swift Commuter Comp\n- Seatpost: Swift Comp, 6061 alloy, 31.6mm, 8mm offset, 330mm length\n- Handlebar: Swift alloy, 31.8mm, 15mm rise, 600mm width (M), 660mm width (L, XL)\n- Grips: Swift Satellite Elite, alloy lock-on\n- Stem: Swift alloy, 31.8mm, Blendr compatible, 7 degree, 70mm length (M), 90mm length (L), 100mm length (XL)\n- Headset: FSA IS-2 alloy, integrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom\n- Brakes: Shimano MT520 4-piston hydraulic disc, post-mount, 180mm rotor\n- Brake Rotor: Shimano RT56, 6-bolt, 180mm\n- Rotor size: Max 180mm front & rear\n\nAccessories\n- Battery: Swift PowerTube 700Wh\n- Charger: Swift standard 4A, 100-240V\n- Motor: SwiftDrive, 90 Nm, 30 mph / 48 kph\n- Light: Swift Lync taillight, 50 lumens (M, L, XL), Swift Lync headlight, 500 lumens (M, L, XL)\n- Kickstand: Rear mount, alloy (M, L, XL), Adjustable length alloy kickstand (M, L, XL)\n- Cargo rack: SwiftVolt integrated rear rack, aluminum\n- Fender: Swift custom aluminum\n\nWeight\n- Weight: M - 25.54 kg / 56.3 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:---------------------:|:-------------:|\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n| XL | 186 - 197 cm 6'1\" - 6'6\" | 87 - 93 cm 34\" - 37\" |\n\n## Geometry\n| Frame size letter | M | L | XL |\n|---------------------------|-------|-------|-------|\n| Wheel size | 27.5\" | 27.5\" | 27.5\" |\n| A — Seat tube | 44.6 | 49.1 | 53.4 |\n| B — Seat tube angle | 73.0° | 73.0° | 73.0° |\n| C — Head tube length | 16.5 | 19.5 | 23.0 |\n| D — Head angle | 69.5° | 70.0° | 70.5° |\n| E — Effective top tube | 59.5 | 60.7 | 62.2 |\n| F — Bottom bracket height | 29.5 | 29.5 | 29.5 |\n| G — Bottom bracket drop | 6.0 | 6.0 | 6.0 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.4 | 4.4 | 4.4 |\n| J — Trail | 8.6 | 8.1 | 7.9 |\n| K — Wheelbase | 114.6 | 115.0 | 116.4 |\n| L — Standover | 79.5 | 83.7 | 87.9 |\n| M — Frame reach | 40.5 | 40.8 | 41.2 |\n| N — Frame stack | 62.3 | 65.2 | 68.8 |", "price": 2499.99, "tags": [ "bicycle", "city bike", "professional" ] }, { "name": "AgileEon 9X", "shortDescription": "AgileEon 9X is a high-performance e-bike designed for riders seeking speed and endurance. Equipped with a robust motor and an extended battery life, this bike is perfect for long-distance commuters and avid e-bike enthusiasts. It boasts innovative features tailored for individuals who prioritize cycling over driving. Additionally, the bike integrates seamlessly with your smartphone, allowing you to access navigation, music, and more.", "description": "## Overview\nIt's right for you if...\nYou crave speed and want to cover long distances efficiently. The AgileEon 9X features a sleek hydroformed aluminum frame that houses a powerful motor, along with a large-capacity battery for extended rides. It comes equipped with a 10-speed drivetrain, front and rear lighting, fenders, and a rear rack.\n\nThe tech you get\nDesigned for those constantly on the move, this bike includes a state-of-the-art motor and a high-capacity battery, making it an excellent choice for lengthy commutes.\n\nThe final word\nWith the AgileEon 9X, you can push your boundaries and explore new horizons thanks to its powerful motor and long-lasting battery.\n\n## Features\n\nConnect Your Ride with RideMate App\nMake use of the RideMate app to transform your smartphone into an onboard computer. Simply attach it to the RideMate controller to dock and charge, then utilize the thumb pad on your handlebar to make calls, listen to music, receive turn-by-turn directions, and more. The bike also supports Bluetooth® wireless technology, enabling seamless connectivity with fitness and health apps for route syncing and ride data.\n\nGoodbye, car. Hello, Extended Range!\nEnhance your riding experience with the Extended Range option, which allows for the attachment of an additional high-capacity 500Wh battery to your bike's downtube. This doubles the distance and time between charges, enabling longer rides, extended commutes, and more significant adventures. The Extended Range feature is compatible with select AgileEon electric bike models.\n\nWhat is the range?\nTo determine how far you can ride on a single charge, you can utilize the range calculator provided by AgileEon. We have pre-filled the variables for this specific model and an average rider, but adjustments can be made for a more accurate estimation.\n\n## Specifications\nFrameset\nFrame: High-performance hydroformed alloy, Removable Integrated Battery, Extended Range-compatible, internal cable routing, Motor Armor, post-mount disc, 135x5 mm QR\nFork: AgileEon rigid alloy fork, 1-1/8'' steel steerer, 100x15mm thru-axle, post-mount disc brake\nMax compatible fork travel: 63mm\n\nWheels\nFront Hub: AgileEon sealed bearing, 32-hole 15mm alloy thru-axle\nFront Skewer: AgileEon Switch thru-axle, removable lever\nRear Hub: AgileEon alloy, sealed bearing, 6-bolt, 135x5mm QR\nRear Skewer: 148x5mm bolt-on\nRim: AgileEon MD35, tubeless compatible, 32-hole, 35mm width, Presta valve\nSpokes:\n- Size: M, L, XL: 14g stainless steel, black\nTire: AgileEon E6 Hard-Case Lite, reflective strip, 27.5x2.40''\nMax tire size: 27.5x2.40\"\n\nDrivetrain\nShifter: Shimano Deore M4100, 10-speed\nRear derailleur:\n- Size: M, L, XL: Shimano Deore M5120, long cage\nCrank:\n- Size: M: AgileEon alloy, 170mm length\n- Size: L, XL: AgileEon alloy, 175mm length\nChainring: AgileEon 46T narrow/wide alloy, with alloy guard\nCassette:\n- Size: M, L, XL: Shimano Deore M4100, 11-42, 10-speed\nChain:\n- Size: M, L, XL: KMC E10\nPedal:\n- Size: M, L, XL: AgileEon City pedals\nMax chainring size: 1x: 48T\n\nComponents\nSaddle: AgileEon Commuter Comp\nSeatpost: AgileEon Comp, 6061 alloy, 31.6mm, 8mm offset, 330mm length\nHandlebar:\n- Size: M: AgileEon alloy, 31.8mm, 15mm rise, 600mm width\n- Size: L, XL: AgileEon alloy, 31.8mm, 15mm rise, 660mm width\nGrips: AgileEon Satellite Elite, alloy lock-on\nStem:\n- Size: M: AgileEon alloy, 31.8mm, Blendr compatible, 7-degree, 70mm length\n- Size: L: AgileEon alloy, 31.8mm, Blendr compatible, 7-degree, 90mm length\n- Size: XL: AgileEon alloy, 31.8mm, Blendr compatible, 7-degree, 100mm length\nHeadset:\n- Size: M, L, XL: AgileEon IS-2 alloy, integrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom\nBrake: Shimano MT520 4-piston hydraulic disc, post-mount, 180mm rotor\nBrake rotor: Shimano RT56, 6-bolt, 180mm\nRotor size: Max brake rotor sizes: 180mm front & rear\n\nAccessories\nBattery: AgileEon PowerTube 625Wh\nCharger: AgileEon standard 4A, 100-240V\nMotor: AgileEon Performance Speed, 85 Nm, 28 mph / 45 kph\nLight:\n- Size: M, L, XL: AgileEon taillight, 50 lumens\n- Size: M, L, XL: AgileEon headlight, 500 lumens\nKickstand:\n- Size: M, L, XL: Rear mount, alloy\n- Size: M, L, XL: Adjustable length alloy kickstand\nCargo rack: AgileEon integrated rear rack, aluminum\nFender: AgileEon custom aluminum\n\nWeight\nWeight: M - 25.54 kg / 56.3 lbs\nWeight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:------------------------:|:--------------------:|\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n| XL | 186 - 197 cm 6'1\" - 6'6\" | 87 - 93 cm 34\" - 37\" |\n\n## Geometry\n| Frame size letter | M | L | XL |\n|---------------------------|-------|-------|-------|\n| Wheel size | 27.5\" | 27.5\" | 27.5\" |\n| A — Seat tube | 44.6 | 49.1 | 53.4 |\n| B — Seat tube angle | 73.0° | 73.0° | 73.0° |\n| C — Head tube length | 16.5 | 19.5 | 23.0 |\n| D — Head angle | 69.5° | 70.0° | 70.5° |\n| E — Effective top tube | 59.5 | 60.7 | 62.2 |\n| F — Bottom bracket height | 29.5 | 29.5 | 29.5 |\n| G — Bottom bracket drop | 6.0 | 6.0 | 6.0 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.4 | 4.4 | 4.4 |\n| J — Trail | 8.6 | 8.1 | 7.9 |\n| K — Wheelbase | 114.6 | 115.0 | 116.4 |\n| L — Standover | 79.5 | 83.7 | 87.9 |\n| M — Frame reach | 40.5 | 40.8 | 41.2 |\n| N — Frame stack | 62.3 | 65.2 | 68.8 |", "price": 3499.99, "tags": [ "bicycle", "road bike", "professional" ] }, { "name": "Stealth R1X Pro", "shortDescription": "Stealth R1X Pro is a high-performance carbon road bike designed for riders who crave speed and exceptional handling. With its aerodynamic tube shaping, disc brakes, and lightweight carbon wheels, the Stealth R1X Pro offers unparalleled performance for competitive road cycling.", "description": "## Overview\nIt's right for you if...\nYou're a competitive cyclist looking for a road bike that offers superior performance in terms of speed, handling, and aerodynamics. You want a complete package that includes lightweight carbon wheels, without the need for future upgrades.\n\nThe tech you get\nThe Stealth R1X Pro features a lightweight and aerodynamic carbon frame, an advanced carbon fork, high-performance Shimano Ultegra 11-speed drivetrain, and powerful Ultegra disc brakes. The bike also comes equipped with cutting-edge Bontrager Aeolus Elite 35 carbon wheels.\n\nThe final word\nThe Stealth R1X Pro stands out with its combination of a fast and aerodynamic frame, high-end drivetrain, and top-of-the-line carbon wheels. Whether you're racing on local roads, participating in pro stage races, or engaging in hill climbing competitions, this bike is a formidable choice that delivers an exceptional riding experience.\n\n## Features\nSleek and aerodynamic design\nThe Stealth R1X Pro's aero tube shapes maximize speed and performance, making it faster on climbs and flats alike. The bike also features a streamlined Aeolus RSL bar/stem for improved front-end aerodynamics.\n\nDesigned for all riders\nThe Stealth R1X Pro is designed to provide an outstanding fit for riders of all genders, body types, riding styles, and abilities. It comes equipped with size-specific components to ensure a comfortable and efficient riding position for competitive riders.\n\n## Specifications\nFrameset\n- Frame: Ultralight carbon frame constructed with high-performance 500 Series ADV Carbon. It features Ride Tuned performance tube optimization, a tapered head tube, internal routing, DuoTrap S compatibility, flat mount disc brake mounts, and a 142x12mm thru axle.\n- Fork: Full carbon fork (Émonda SL) with a tapered carbon steerer, internal brake routing, flat mount disc brake mounts, and a 12x100mm thru axle.\n- Frame fit: H1.5 Race geometry.\n\nWheels\n- Front wheel: Bontrager Aeolus Elite 35 carbon wheel with a 35mm rim depth, ADV Carbon construction, Tubeless Ready compatibility, and a 100x12mm thru axle.\n- Rear wheel: Bontrager Aeolus Elite 35 carbon wheel with a 35mm rim depth, ADV Carbon construction, Tubeless Ready compatibility, Shimano 11/12-speed freehub, and a 142x12mm thru axle.\n- Front skewer: Bontrager Switch thru axle with a removable lever.\n- Rear skewer: Bontrager Switch thru axle with a removable lever.\n- Tire: Bontrager R2 Hard-Case Lite with an aramid bead, 60 tpi, and a size of 700x25c.\n- Maximum tire size: 28mm.\n\nDrivetrain\n- Shifter:\n - Size 47, 50, 52: Shimano Ultegra R8025 with short-reach levers, 11-speed.\n - Size 54, 56, 58, 60, 62: Shimano Ultegra R8020, 11-speed.\n- Front derailleur: Shimano Ultegra R8000, braze-on.\n- Rear derailleur: Shimano Ultegra R8000, short cage, with a maximum cog size of 30T.\n- Crank:\n - Size 47: Shimano Ultegra R8000 with 52/36 chainrings and a 165mm length.\n - Size 50, 52: Shimano Ultegra R8000 with 52/36 chainrings and a 170mm length.\n - Size 54, 56, 58: Shimano Ultegra R8000 with 52/36 chainrings and a 172.5mm length.\n - Size 60, 62: Shimano Ultegra R8000 with 52/36 chainrings and a 175mm length.\n- Bottom bracket: Praxis T47 threaded bottom bracket with internal bearings.\n- Cassette: Shimano Ultegra R8000, 11-30, 11-speed.\n- Chain: Shimano Ultegra HG701, 11-speed.\n- Maximum chainring size: 1x - 50T, 2x - 53/39.\n\nComponents\n- Saddle: Bontrager Aeolus Comp with steel rails and a width of 145mm.\n- Seatpost:\n - Size 47, 50, 52, 54: Bontrager carbon seatmast cap with a 20mm offset and a short length.\n - Size 56, 58, 60, 62: Bontrager carbon seatmast cap with a 20mm offset and a tall length.\n- Handlebar:\n - Size 47, 50: Bontrager Elite VR-C alloy handlebar with a 31.8mm clamp, 100mm reach, 124mm drop, and a width of 38cm.\n - Size 52: Bontrager Elite VR-C alloy handlebar with a 31.8mm clamp, 100mm reach, 124mm drop, and a width of 40cm.\n - Size 54, 56, 58: Bontrager Elite VR-C alloy handlebar with a 31.8mm clamp, 100mm reach, 124mm drop, and a width of 42cm.\n - Size 60, 62: Bontrager Elite VR-C alloy handlebar with a 31.8mm clamp, 100mm reach, 124mm drop, and a width of 44cm.\n- Handlebar tape: Bontrager Supertack Perf tape.\n- Stem:\n - Size 47: Bontrager Pro alloy stem with a 31.8mm clamp, Blendr compatibility, 7-degree rise, and a length of 70mm.\n - Size 50: Bontrager Pro alloy stem with a 31.8mm clamp, Blendr compatibility, 7-degree rise, and a length of 80mm.\n - Size 52, 54: Bontrager Pro alloy stem with a 31.8mm clamp, Blendr compatibility, 7-degree rise, and a length of 90mm.\n - Size 56: Bontrager Pro alloy stem with a 31.8mm clamp, Blendr compatibility, 7-degree rise, and a length of 100mm.\n - Size 58, 60, 62: Bontrager Pro alloy stem with a 31.8mm clamp, Blendr compatibility, 7-degree rise, and a length of 110mm.\n- Brake: Shimano Ultegra hydraulic disc brakes with flat mount calipers.\n- Brake rotor: Shimano RT800 with centerlock mounting, 160mm diameter.\n\nWeight\n- Weight: 8.03 kg (17.71 lbs) for the 56cm frame.\n- Weight limit: The bike has a maximum total weight limit (combined weight of the bicycle, rider, and cargo) of 275 pounds (125 kg).\n\n## Sizing\nPlease refer to the table below for the corresponding Stealth R1X Pro frame sizes, recommended rider height range, and inseam measurements:\n\n| Size | Rider Height | Inseam |\n|:----:|:---------------------:|:--------------:|\n| 47 | 152 - 158 cm (5'0\") | 71 - 75 cm |\n| 50 | 158 - 163 cm (5'2\") | 74 - 77 cm |\n| 52 | 163 - 168 cm (5'4\") | 76 - 79 cm |\n| 54 | 168 - 174 cm (5'6\") | 78 - 82 cm |\n| 56 | 174 - 180 cm (5'9\") | 81 - 85 cm |\n| 58 | 180 - 185 cm (5'11\") | 84 - 87 cm |\n| 60 | 185 - 190 cm (6'1\") | 86 - 90 cm |\n| 62 | 190 - 195 cm (6'3\") | 89 - 92 cm |\n\n## Geometry\nThe table below provides the geometry measurements for each frame size of the Stealth R1X Pro:\n\n| Frame size number | 47 cm | 50 cm | 52 cm | 54 cm | 56 cm | 58 cm | 60 cm | 62 cm |\n|-------------------------------|-------|-------|-------|-------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c | 700c | 700c | 700c | 700c |\n| A — Seat tube | 42.4 | 45.3 | 48.3 | 49.6 | 52.5 | 55.3 | 57.3 | 59.3 |\n| B — Seat tube angle | 74.6° | 74.6° | 74.2° | 73.7° | 73.3° | 73.0° | 72.8° | 72.5° |\n| C — Head tube length | 10.0 | 11.1 | 12.1 | 13.1 | 15.1 | 17.1 | 19.1 | 21.1 |\n| D — Head angle | 72.1° | 72.1° | 72.8° | 73.0° | 73.5° | 73.8° | 73.9° | 73.9° |\n| E — Effective top tube | 51.2 | 52.1 | 53.4 | 54.3 | 55.9 | 57.4 | 58.6 | 59.8 |\n| G — Bottom bracket drop | 7.2 | 7.2 | 7.2 | 7.0 | 7.0 | 6.8 | 6.8 | 6.8 |\n| H — Chainstay length | 41.0 | 41.0 | 41.0 | 41.0 | 41.0 | 41.1 | 41.1 | 41.2 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 | 4.0 | 4.0 | 4.0 | 4.0 |\n| J — Trail | 6.8 | 6.2 | 5.8 | 5.6 | 5.8 | 5.7 | 5.6 | 5.6 |\n| K — Wheelbase | 97.2 | 97.4 | 97.7 | 98.1 | 98.3 | 99.2 | 100.1 | 101.0 |\n| L — Standover | 69.2 | 71.1 | 73.2 | 74.4 | 76.8 | 79.3 | 81.1 | 82.9 |\n| M — Frame reach | 37.3 | 37.8 | 38.3 | 38.6 | 39.1 | 39.6 | 39.9 | 40.3 |\n| N — Frame stack | 50.7 | 52.1 | 53.3 | 54.1 | 56.3 | 58.1 | 60.1 | 62.0 |\n| Saddle rail height min (short mast) | 55.5 | 58.5 | 61.5 | 64.0 | 67.0 | 69.0 | 71.0 | 73.0 |\n| Saddle rail height max (short mast) | 61.5 | 64.5 | 67.5 | 70.0 | 73.0 | 75.0 | 77.0 | 79.0 |\n| Saddle rail height min (tall mast) | 59.0 | 62.0 | 65.0 | 67.5 | 70.5 | 72.5 | 74.5 | 76.5 |\n| Saddle rail height max (tall mast) | 65.0 | 68.0 | 71.0 | 73.5 | 76.5 | 78.5 | 80.5 | 82.5 |", "price": 2999.99, "tags": [ "bicycle", "mountain bike", "professional" ] }, { "name": "Avant SLR 6 Disc Pro", "shortDescription": "Avant SLR 6 Disc Pro is a high-performance carbon road bike designed for riders who prioritize speed and handling. With its aero tube shaping, disc brakes, and lightweight carbon wheels, it offers the perfect balance of speed and control.", "description": "## Overview\nIt's right for you if...\nYou're a rider who values exceptional performance on fast group rides and races, and you want a complete package that includes lightweight carbon wheels. The Avant SLR 6 Disc Pro is designed to provide the speed and aerodynamics you need to excel on any road.\n\nThe tech you get\nThe Avant SLR 6 Disc Pro features a lightweight 500 Series ADV Carbon frame and fork, Bontrager Aeolus Elite 35 carbon wheels, a full Shimano Ultegra 11-speed drivetrain, and powerful Ultegra disc brakes.\n\nThe final word\nThe standout feature of this bike is the combination of its aero frame, high-performance drivetrain, and top-quality carbon wheels. Whether you're racing, tackling challenging climbs, or participating in professional stage races, the Avant SLR 6 Disc Pro is a worthy choice that will enhance your performance.\n\n## Features\nAll-new aero design\nThe Avant SLR 6 Disc Pro features innovative aero tube shapes that provide an advantage in all riding conditions, whether it's climbing or riding on flat roads. Additionally, it is equipped with a sleek new Aeolus RSL bar/stem that enhances front-end aero performance.\n\nAwesome bikes for everyone\nThe Avant SLR 6 Disc Pro is designed with the belief that every rider, regardless of gender, body type, riding style, or ability, deserves a great bike. It is equipped with size-specific components that ensure a perfect fit for competitive riders of all genders.\n\n## Specifications\nFrameset\n- Frame: Ultralight 500 Series ADV Carbon, Ride Tuned performance tube optimization, tapered head tube, internal routing, DuoTrap S compatible, flat mount disc, 142x12mm thru axle\n- Fork: Avant SL full carbon, tapered carbon steerer, internal brake routing, flat mount disc, 12x100mm thru axle\n- Frame fit: H1.5 Race\n\nWheels\n- Front wheel: Bontrager Aeolus Elite 35, ADV Carbon, Tubeless Ready, 35mm rim depth, 100x12mm thru axle\n- Rear wheel: Bontrager Aeolus Elite 35, ADV Carbon, Tubeless Ready, 35mm rim depth, Shimano 11/12-speed freehub, 142x12mm thru axle\n- Front skewer: Bontrager Switch thru axle, removable lever\n- Rear skewer: Bontrager Switch thru axle, removable lever\n- Tire: Bontrager R2 Hard-Case Lite, aramid bead, 60 tpi, 700x25c\n- Max tire size: 28mm\n\nDrivetrain\n- Shifter: \n - Size 47, 50, 52: Shimano Ultegra R8025, short-reach lever, 11-speed\n - Size 54, 56, 58, 60, 62: Shimano Ultegra R8020, 11-speed\n- Front derailleur: Shimano Ultegra R8000, braze-on\n- Rear derailleur: Shimano Ultegra R8000, short cage, 30T max cog\n- Crank: \n - Size 47: Shimano Ultegra R8000, 52/36, 165mm length\n - Size 50, 52: Shimano Ultegra R8000, 52/36, 170mm length\n - Size 54, 56, 58: Shimano Ultegra R8000, 52/36, 172.5mm length\n - Size 60, 62: Shimano Ultegra R8000, 52/36, 175mm length\n- Bottom bracket: Praxis, T47 threaded, internal bearing\n- Cassette: Shimano Ultegra R8000, 11-30, 11-speed\n- Chain: Shimano Ultegra HG701, 11-speed\n- Max chainring size: 1x: 50T, 2x: 53/39\n\nComponents\n- Saddle: Bontrager Aeolus Comp, steel rails, 145mm width\n- Seatpost: \n - Size 47, 50, 52, 54: Bontrager carbon seatmast cap, 20mm offset, short length\n - Size 56, 58, 60, 62: Bontrager carbon seatmast cap, 20mm offset, tall length\n- Handlebar: \n - Size 47, 50: Bontrager Elite VR-C, alloy, 31.8mm, 100mm reach, 124mm drop, 38cm width\n - Size 52: Bontrager Elite VR-C, alloy, 31.8mm, 100mm reach, 124mm drop, 40cm width\n - Size 54, 56, 58: Bontrager Elite VR-C, alloy, 31.8mm, 100mm reach, 124mm drop, 42cm width\n - Size 60, 62: Bontrager Elite VR-C, alloy, 31.8mm, 100mm reach, 124mm drop, 44cm width\n- Handlebar tape: Bontrager Supertack Perf tape\n- Stem: \n - Size 47: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 70mm length\n - Size 50: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 80mm length\n - Size 52, 54: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 90mm length\n - Size 56: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 100mm length\n - Size 58, 60, 62: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 110mm length\n- Brake: Shimano Ultegra hydraulic disc, flat mount\n- Brake rotor: Shimano RT800, centerlock, 160mm\n\nWeight\n- Weight: 56 - 8.03 kg / 17.71 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 275 pounds (125 kg).\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| 47 | 152 - 158 cm 5'0\" - 5'2\" | 71 - 75 cm 28\" - 30\" |\n| 50 | 158 - 163 cm 5'2\" - 5'4\" | 74 - 77 cm 29\" - 30\" |\n| 52 | 163 - 168 cm 5'4\" - 5'6\" | 76 - 79 cm 30\" - 31\" |\n| 54 | 168 - 174 cm 5'6\" - 5'9\" | 78 - 82 cm 31\" - 32\" |\n| 56 | 174 - 180 cm 5'9\" - 5'11\" | 81 - 85 cm 32\" - 33\" |\n| 58 | 180 - 185 cm 5'11\" - 6'1\" | 84 - 87 cm 33\" - 34\" |\n| 60 | 185 - 190 cm 6'1\" - 6'3\" | 86 - 90 cm 34\" - 35\" |\n| 62 | 190 - 195 cm 6'3\" - 6'5\" | 89 - 92 cm 35\" - 36\" |\n\n## Geometry\n| Frame size number | 47 cm | 50 cm | 52 cm | 54 cm | 56 cm | 58 cm | 60 cm | 62 cm |\n|---------------------------------------|-------|-------|-------|-------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c | 700c | 700c | 700c | 700c |\n| A — Seat tube | 42.4 | 45.3 | 48.3 | 49.6 | 52.5 | 55.3 | 57.3 | 59.3 |\n| B — Seat tube angle | 74.6° | 74.6° | 74.2° | 73.7° | 73.3° | 73.0° | 72.8° | 72.5° |\n| C — Head tube length | 10.0 | 11.1 | 12.1 | 13.1 | 15.1 | 17.1 | 19.1 | 21.1 |\n| D — Head angle | 72.1° | 72.1° | 72.8° | 73.0° | 73.5° | 73.8° | 73.9° | 73.9° |\n| E — Effective top tube | 51.2 | 52.1 | 53.4 | 54.3 | 55.9 | 57.4 | 58.6 | 59.8 |\n| G — Bottom bracket drop | 7.2 | 7.2 | 7.2 | 7.0 | 7.0 | 6.8 | 6.8 | 6.8 |\n| H — Chainstay length | 41.0 | 41.0 | 41.0 | 41.0 | 41.0 | 41.1 | 41.1 | 41.2 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 | 4.0 | 4.0 | 4.0 | 4.0 |\n| J — Trail | 6.8 | 6.2 | 5.8 | 5.6 | 5.8 | 5.7 | 5.6 | 5.6 |\n| K — Wheelbase | 97.2 | 97.4 | 97.7 | 98.1 | 98.3 | 99.2 | 100.1 | 101.0 |\n| L — Standover | 69.2 | 71.1 | 73.2 | 74.4 | 76.8 | 79.3 | 81.1 | 82.9 |\n| M — Frame reach | 37.3 | 37.8 | 38.3 | 38.6 | 39.1 | 39.6 | 39.9 | 40.3 |\n| N — Frame stack | 50.7 | 52.1 | 53.3 | 54.1 | 56.3 | 58.1 | 60.1 | 62.0 |\n| Saddle rail height min (w/short mast) | 55.5 | 58.5 | 61.5 | 64.0 | 67.0 | 69.0 | 71.0 | 73.0 |\n| Saddle rail height max (w/short mast) | 61.5 | 64.5 | 67.5 | 70.0 | 73.0 | 75.0 | 77.0 | 79.0 |\n| Saddle rail height min (w/tall mast) | 59.0 | 62.0 | 65.0 | 67.5 | 70.5 | 72.5 | 74.5 | 76.5 |\n| Saddle rail height max (w/tall mast) | 65.0 | 68.0 | 71.0 | 73.5 | 76.5 | 78.5 | 80.5 | 82.5 |", "price": 999.99, "tags": [ "bicycle", "city bike", "professional" ] } ] --- ### Spring Ai Client Chat/Src/Test/Resources/Text Source (spring-ai-client-chat/src/test/resources/text_source.txt) Spring Framework Documentation Version 6.0.0 Chapter 1. Spring Framework Overview Spring makes it easy to create Java enterprise applications. It provides everything you need to embrace the Java language in an enterprise environment, with support for Groovy and Kotlin as alternative languages on the JVM, and with the flexibility to create many kinds of architectures depending on an application’s needs. As of Spring Framework 5.1, Spring requires JDK 8+ (Java SE 8+) and provides out-of-the-box support for JDK 11 LTS. Java SE 8 update 60 is suggested as the minimum patch release for Java 8, but it is generally recommended to use a recent patch release. Spring supports a wide range of application scenarios. In a large enterprise, applications often exist for a long time and have to run on a JDK and application server whose upgrade cycle is beyond developer control. Others may run as a single jar with the server embedded, possibly in a cloud environment. Yet others may be standalone applications (such as batch or integration workloads) that do not need a server. Spring is open source. It has a large and active community that provides continuous feedback based on a diverse range of real-world use cases. This has helped Spring to successfully evolve over a very long time. 1.1. What We Mean by "Spring" The term "Spring" means different things in different contexts. It can be used to refer to the Spring Framework project itself, which is where it all started. Over time, other Spring projects have been built on top of the Spring Framework. Most often, when people say "Spring", they mean the entire family of projects. This reference documentation focuses on the foundation: the Spring Framework itself. The Spring Framework is divided into modules. Applications can choose which modules they need. At the heart are the modules of the core container, including a configuration model and a dependency injection mechanism. Beyond that, the Spring Framework provides foundational support for different application architectures, including messaging, transactional data and persistence, and web. It also includes the Servlet-based Spring MVC web framework and, in parallel, the Spring WebFlux reactive web framework. A note about modules: Spring’s framework jars allow for deployment to JDK 9’s module path ("Jigsaw"). For use in Jigsaw-enabled applications, the Spring Framework 5 jars come with "Automatic-Module-Name" manifest entries which define stable language-level module names ("spring.core", "spring.context", etc.) independent from jar artifact names (the jars follow the same naming pattern with "-" instead of ".", e.g. "spring-core" and "spring-context"). Of course, Spring’s framework jars keep working fine on the classpath on both JDK 8 and 9+. 1.2. History of Spring and the Spring Framework Spring came into being in 2003 as a response to the complexity of the early J2EE specifications. While some consider Java EE and its modern-day successor Jakarta EE to be in competition with Spring, they are in fact complementary. The Spring programming model does not embrace the Jakarta EE platform specification; rather, it integrates with carefully selected individual specifications from the traditional EE umbrella: • Servlet API (JSR 340) • WebSocket API (JSR 356) • Concurrency Utilities (JSR 236) • JSON Binding API (JSR 367) • Bean Validation (JSR 303) • JPA (JSR 338) • JMS (JSR 914) • as well as JTA/JCA setups for transaction coordination, if necessary. The Spring Framework also supports the Dependency Injection (JSR 330) and Common Annotations (JSR 250) specifications, which application developers may choose to use instead of the Spring- specific mechanisms provided by the Spring Framework. Originally, those were based on common javax packages. As of Spring Framework 6.0, Spring has been upgraded to the Jakarta EE 9 level (e.g. Servlet 5.0+, JPA 3.0+), based on the jakarta namespace instead of the traditional javax packages. With EE 9 as the minimum and EE 10 supported already, Spring is prepared to provide out-of-the-box support for the further evolution of the Jakarta EE APIs. Spring Framework 6.0 is fully compatible with Tomcat 10.1, Jetty 11 and Undertow 2.3 as web servers, and also with Hibernate ORM 6.1. Over time, the role of Java/Jakarta EE in application development has evolved. In the early days of J2EE and Spring, applications were created to be deployed to an application server. Today, with the help of Spring Boot, applications are created in a devops- and cloud-friendly way, with the Servlet container embedded and trivial to change. As of Spring Framework 5, a WebFlux application does not even use the Servlet API directly and can run on servers (such as Netty) that are not Servlet containers. Spring continues to innovate and to evolve. Beyond the Spring Framework, there are other projects, such as Spring Boot, Spring Security, Spring Data, Spring Cloud, Spring Batch, among others. It’s important to remember that each project has its own source code repository, issue tracker, and release cadence. See spring.io/projects for the complete list of Spring projects. 1.3. Design Philosophy When you learn about a framework, it’s important to know not only what it does but what principles it follows. Here are the guiding principles of the Spring Framework: • Provide choice at every level. Spring lets you defer design decisions as late as possible. For example, you can switch persistence providers through configuration without changing your code. The same is true for many other infrastructure concerns and integration with third-party APIs. • Accommodate diverse perspectives. Spring embraces flexibility and is not opinionated about how things should be done. It supports a wide range of application needs with different perspectives. • Maintain strong backward compatibility. Spring’s evolution has been carefully managed to force few breaking changes between versions. Spring supports a carefully chosen range of JDK versions and third-party libraries to facilitate maintenance of applications and libraries that depend on Spring. • Care about API design. The Spring team puts a lot of thought and time into making APIs that are intuitive and that hold up across many versions and many years. • Set high standards for code quality. The Spring Framework puts a strong emphasis on meaningful, current, and accurate javadoc. It is one of very few projects that can claim clean code structure with no circular dependencies between packages. 1.4. Feedback and Contributions For how-to questions or diagnosing or debugging issues, we suggest using Stack Overflow. Click here for a list of the suggested tags to use on Stack Overflow. If you’re fairly certain that there is a problem in the Spring Framework or would like to suggest a feature, please use the GitHub Issues. If you have a solution in mind or a suggested fix, you can submit a pull request on Github. However, please keep in mind that, for all but the most trivial issues, we expect a ticket to be filed in the issue tracker, where discussions take place and leave a record for future reference. For more details see the guidelines at the CONTRIBUTING, top-level project page. 1.5. Getting Started If you are just getting started with Spring, you may want to begin using the Spring Framework by creating a Spring Boot-based application. Spring Boot provides a quick (and opinionated) way to create a production-ready Spring-based application. It is based on the Spring Framework, favors convention over configuration, and is designed to get you up and running as quickly as possible. You can use start.spring.io to generate a basic project or follow one of the "Getting Started" guides, such as Getting Started Building a RESTful Web Service. As well as being easier to digest, these guides are very task focused, and most of them are based on Spring Boot. They also cover other projects from the Spring portfolio that you might want to consider when solving a particular problem. Chapter 2. Core Technologies This part of the reference documentation covers all the technologies that are absolutely integral to the Spring Framework. Foremost amongst these is the Spring Framework’s Inversion of Control (IoC) container. A thorough treatment of the Spring Framework’s IoC container is closely followed by comprehensive coverage of Spring’s Aspect-Oriented Programming (AOP) technologies. The Spring Framework has its own AOP framework, which is conceptually easy to understand and which successfully addresses the 80% sweet spot of AOP requirements in Java enterprise programming. Coverage of Spring’s integration with AspectJ (currently the richest — in terms of features — and certainly most mature AOP implementation in the Java enterprise space) is also provided. AOT processing can be used to optimize your application ahead-of-time. It is typically used for native image deployment using GraalVM. 2.1. The IoC Container This chapter covers Spring’s Inversion of Control (IoC) container. 2.1.1. Introduction to the Spring IoC Container and Beans This chapter covers the Spring Framework implementation of the Inversion of Control (IoC) principle. IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes or a mechanism such as the Service Locator pattern. The org.springframework.beans and org.springframework.context packages are the basis for Spring Framework’s IoC container. The BeanFactory interface provides an advanced configuration mechanism capable of managing any type of object. ApplicationContext is a sub-interface of BeanFactory. It adds: • Easier integration with Spring’s AOP features • Message resource handling (for use in internationalization) • Event publication • Application-layer specific contexts such as the WebApplicationContext for use in web applications. In short, the BeanFactory provides the configuration framework and basic functionality, and the ApplicationContext adds more enterprise-specific functionality. The ApplicationContext is a complete superset of the BeanFactory and is used exclusively in this chapter in descriptions of Spring’s IoC container. For more information on using the BeanFactory instead of the ApplicationContext, see the section covering the BeanFactory API. In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container. 2.1.2. Container Overview The org.springframework.context.ApplicationContext interface represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the beans. The container gets its instructions on what objects to instantiate, configure, and assemble by reading configuration metadata. The configuration metadata is represented in XML, Java annotations, or Java code. It lets you express the objects that compose your application and the rich interdependencies between those objects. Several implementations of the ApplicationContext interface are supplied with Spring. In stand- alone applications, it is common to create an instance of ClassPathXmlApplicationContext or FileSystemXmlApplicationContext. While XML has been the traditional format for defining configuration metadata, you can instruct the container to use Java annotations or code as the metadata format by providing a small amount of XML configuration to declaratively enable support for these additional metadata formats. In most application scenarios, explicit user code is not required to instantiate one or more instances of a Spring IoC container. For example, in a web application scenario, a simple eight (or so) lines of boilerplate web descriptor XML in the web.xml file of the application typically suffices (see Convenient ApplicationContext Instantiation for Web Applications). If you use the Spring Tools for Eclipse (an Eclipse-powered development environment), you can easily create this boilerplate configuration with a few mouse clicks or keystrokes. The following diagram shows a high-level view of how Spring works. Your application classes are combined with configuration metadata so that, after the ApplicationContext is created and initialized, you have a fully configured and executable system or application. Figure 1. The Spring IoC container Configuration Metadata As the preceding diagram shows, the Spring IoC container consumes a form of configuration metadata. This configuration metadata represents how you, as an application developer, tell the Spring container to instantiate, configure, and assemble the objects in your application. Configuration metadata is traditionally supplied in a simple and intuitive XML format, which is what most of this chapter uses to convey key concepts and features of the Spring IoC container. XML-based metadata is not the only allowed form of configuration metadata. The Spring IoC container itself is totally decoupled from the format in which this  configuration metadata is actually written. These days, many developers choose Java-based configuration for their Spring applications. For information about using other forms of metadata with the Spring container, see: • Annotation-based configuration: Spring 2.5 introduced support for annotation-based configuration metadata. • Java-based configuration: Starting with Spring 3.0, many features provided by the Spring JavaConfig project became part of the core Spring Framework. Thus, you can define beans external to your application classes by using Java rather than XML files. To use these new features, see the @Configuration, @Bean, @Import, and @DependsOn annotations. Spring configuration consists of at least one and typically more than one bean definition that the container must manage. XML-based configuration metadata configures these beans as elements inside a top-level element. Java configuration typically uses @Bean-annotated methods within a @Configuration class. These bean definitions correspond to the actual objects that make up your application. Typically, you define service layer objects, data access objects (DAOs), presentation objects such as Struts Action instances, infrastructure objects such as Hibernate SessionFactories, JMS Queues, and so forth. Typically, one does not configure fine-grained domain objects in the container, because it is usually the responsibility of DAOs and business logic to create and load domain objects. However, you can use Spring’s integration with AspectJ to configure objects that have been created outside the control of an IoC container. See Using AspectJ to dependency-inject domain objects with Spring. The following example shows the basic structure of XML-based configuration metadata:   ① ②             ① The id attribute is a string that identifies the individual bean definition. ② The class attribute defines the type of the bean and uses the fully qualified classname. The value of the id attribute refers to collaborating objects. The XML for referring to collaborating objects is not shown in this example. See Dependencies for more information. Instantiating a Container The location path or paths supplied to an ApplicationContext constructor are resource strings that let the container load configuration metadata from a variety of external resources, such as the local file system, the Java CLASSPATH, and so on. Java ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml"); Kotlin val context = ClassPathXmlApplicationContext("services.xml", "daos.xml") After you learn about Spring’s IoC container, you may want to know more about Spring’s Resource abstraction (as described in Resources), which provides a  convenient mechanism for reading an InputStream from locations defined in a URI syntax. In particular, Resource paths are used to construct applications contexts, as described in Application Contexts and Resource Paths. The following example shows the service layer objects (services.xml) configuration file:               The following example shows the data access objects daos.xml file:               In the preceding example, the service layer consists of the PetStoreServiceImpl class and two data access objects of the types JpaAccountDao and JpaItemDao (based on the JPA Object-Relational Mapping standard). The property name element refers to the name of the JavaBean property, and the ref element refers to the name of another bean definition. This linkage between id and ref elements expresses the dependency between collaborating objects. For details of configuring an object’s dependencies, see Dependencies. Composing XML-based Configuration Metadata It can be useful to have bean definitions span multiple XML files. Often, each individual XML configuration file represents a logical layer or module in your architecture. You can use the application context constructor to load bean definitions from all these XML fragments. This constructor takes multiple Resource locations, as was shown in the previous section. Alternatively, use one or more occurrences of the element to load bean definitions from another file or files. The following example shows how to do so:           In the preceding example, external bean definitions are loaded from three files: services.xml, messageSource.xml, and themeSource.xml. All location paths are relative to the definition file doing the importing, so services.xml must be in the same directory or classpath location as the file doing the importing, while messageSource.xml and themeSource.xml must be in a resources location below the location of the importing file. As you can see, a leading slash is ignored. However, given that these paths are relative, it is better form not to use the slash at all. The contents of the files being imported, including the top level element, must be valid XML bean definitions, according to the Spring Schema. It is possible, but not recommended, to reference files in parent directories using a relative "../" path. Doing so creates a dependency on a file that is outside the current application. In particular, this reference is not recommended for classpath: URLs (for example, classpath:../services.xml), where the runtime resolution process chooses the “nearest” classpath root and then looks into its parent directory. Classpath configuration changes may lead to the choice of a different, incorrect directory.  You can always use fully qualified resource locations instead of relative paths: for example, file:C:/config/services.xml or classpath:/config/services.xml. However, be aware that you are coupling your application’s configuration to specific absolute locations. It is generally preferable to keep an indirection for such absolute locations — for example, through "${…}" placeholders that are resolved against JVM system properties at runtime. The namespace itself provides the import directive feature. Further configuration features beyond plain bean definitions are available in a selection of XML namespaces provided by Spring — for example, the context and util namespaces. The Groovy Bean Definition DSL As a further example for externalized configuration metadata, bean definitions can also be expressed in Spring’s Groovy Bean Definition DSL, as known from the Grails framework. Typically, such configuration live in a ".groovy" file with the structure shown in the following example: beans {   dataSource(BasicDataSource) {   driverClassName = "org.hsqldb.jdbcDriver"   url = "jdbc:hsqldb:mem:grailsDB"   username = "sa"   password = ""   settings = [mynew:"setting"]   }   sessionFactory(SessionFactory) {   dataSource = dataSource   }   myService(MyService) {   nestedBean = { AnotherBean bean ->   dataSource = dataSource   }   } } This configuration style is largely equivalent to XML bean definitions and even supports Spring’s XML configuration namespaces. It also allows for importing XML bean definition files through an importBeans directive. Using the Container The ApplicationContext is the interface for an advanced factory capable of maintaining a registry of different beans and their dependencies. By using the method T getBean(String name, Class requiredType), you can retrieve instances of your beans. The ApplicationContext lets you read bean definitions and access them, as the following example shows: Java // create and configure beans ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml"); // retrieve configured instance PetStoreService service = context.getBean("petStore", PetStoreService.class); // use configured instance List userList = service.getUsernameList(); Kotlin import org.springframework.beans.factory.getBean // create and configure beans val context = ClassPathXmlApplicationContext("services.xml", "daos.xml") // retrieve configured instance val service = context.getBean("petStore") // use configured instance var userList = service.getUsernameList() With Groovy configuration, bootstrapping looks very similar. It has a different context implementation class which is Groovy-aware (but also understands XML bean definitions). The following example shows Groovy configuration: Java ApplicationContext context = new GenericGroovyApplicationContext("services.groovy", "daos.groovy"); Kotlin val context = GenericGroovyApplicationContext("services.groovy", "daos.groovy") The most flexible variant is GenericApplicationContext in combination with reader delegates — for example, with XmlBeanDefinitionReader for XML files, as the following example shows: Java GenericApplicationContext context = new GenericApplicationContext(); new XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml"); context.refresh(); Kotlin val context = GenericApplicationContext() XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml") context.refresh() You can also use the GroovyBeanDefinitionReader for Groovy files, as the following example shows: Java GenericApplicationContext context = new GenericApplicationContext(); new GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy"); context.refresh(); Kotlin val context = GenericApplicationContext() GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy") context.refresh() You can mix and match such reader delegates on the same ApplicationContext, reading bean definitions from diverse configuration sources. You can then use getBean to retrieve instances of your beans. The ApplicationContext interface has a few other methods for retrieving beans, but, ideally, your application code should never use them. Indeed, your application code should have no calls to the getBean() method at all and thus have no dependency on Spring APIs at all. For example, Spring’s integration with web frameworks provides dependency injection for various web framework components such as controllers and JSF-managed beans, letting you declare a dependency on a specific bean through metadata (such as an autowiring annotation). 2.1.3. Bean Overview A Spring IoC container manages one or more beans. These beans are created with the configuration metadata that you supply to the container (for example, in the form of XML definitions). Within the container itself, these bean definitions are represented as BeanDefinition objects, which contain (among other information) the following metadata: • A package-qualified class name: typically, the actual implementation class of the bean being defined. • Bean behavioral configuration elements, which state how the bean should behave in the container (scope, lifecycle callbacks, and so forth). • References to other beans that are needed for the bean to do its work. These references are also called collaborators or dependencies. • Other configuration settings to set in the newly created object — for example, the size limit of the pool or the number of connections to use in a bean that manages a connection pool. This metadata translates to a set of properties that make up each bean definition. The following table describes these properties: Table 1. The bean definition Property Explained in… Class Instantiating Beans Name Naming Beans Scope Bean Scopes Constructor arguments Dependency Injection Properties Dependency Injection Autowiring mode Autowiring Collaborators Lazy initialization mode Lazy-initialized Beans Initialization method Initialization Callbacks Destruction method Destruction Callbacks In addition to bean definitions that contain information on how to create a specific bean, the ApplicationContext implementations also permit the registration of existing objects that are created outside the container (by users). This is done by accessing the ApplicationContext’s BeanFactory through the getBeanFactory() method, which returns the DefaultListableBeanFactory implementation. DefaultListableBeanFactory supports this registration through the registerSingleton(..) and registerBeanDefinition(..) methods. However, typical applications work solely with beans defined through regular bean definition metadata. Bean metadata and manually supplied singleton instances need to be registered as early as possible, in order for the container to properly reason about them during autowiring and other introspection steps. While overriding existing metadata and  existing singleton instances is supported to some degree, the registration of new beans at runtime (concurrently with live access to the factory) is not officially supported and may lead to concurrent access exceptions, inconsistent state in the bean container, or both. Naming Beans Every bean has one or more identifiers. These identifiers must be unique within the container that hosts the bean. A bean usually has only one identifier. However, if it requires more than one, the extra ones can be considered aliases. In XML-based configuration metadata, you use the id attribute, the name attribute, or both to specify the bean identifiers. The id attribute lets you specify exactly one id. Conventionally, these names are alphanumeric ('myBean', 'someService', etc.), but they can contain special characters as well. If you want to introduce other aliases for the bean, you can also specify them in the name attribute, separated by a comma (,), semicolon (;), or white space. As a historical note, in versions prior to Spring 3.1, the id attribute was defined as an xsd:ID type, which constrained possible characters. As of 3.1, it is defined as an xsd:string type. Note that bean id uniqueness is still enforced by the container, though no longer by XML parsers. You are not required to supply a name or an id for a bean. If you do not supply a name or id explicitly, the container generates a unique name for that bean. However, if you want to refer to that bean by name, through the use of the ref element or a Service Locator style lookup, you must provide a name. Motivations for not supplying a name are related to using inner beans and autowiring collaborators. Bean Naming Conventions The convention is to use the standard Java convention for instance field names when naming beans. That is, bean names start with a lowercase letter and are camel-cased from there. Examples of such names include accountManager, accountService, userDao, loginController, and so forth. Naming beans consistently makes your configuration easier to read and understand. Also, if you use Spring AOP, it helps a lot when applying advice to a set of beans related by name. With component scanning in the classpath, Spring generates bean names for unnamed components, following the rules described earlier: essentially, taking the simple class name and turning its initial character to lower-case. However, in the  (unusual) special case when there is more than one character and both the first and second characters are upper case, the original casing gets preserved. These are the same rules as defined by java.beans.Introspector.decapitalize (which Spring uses here). Aliasing a Bean outside the Bean Definition In a bean definition itself, you can supply more than one name for the bean, by using a combination of up to one name specified by the id attribute and any number of other names in the name attribute. These names can be equivalent aliases to the same bean and are useful for some situations, such as letting each component in an application refer to a common dependency by using a bean name that is specific to that component itself. Specifying all aliases where the bean is actually defined is not always adequate, however. It is sometimes desirable to introduce an alias for a bean that is defined elsewhere. This is commonly the case in large systems where configuration is split amongst each subsystem, with each subsystem having its own set of object definitions. In XML-based configuration metadata, you can use the element to accomplish this. The following example shows how to do so: In this case, a bean (in the same container) named fromName may also, after the use of this alias definition, be referred to as toName. For example, the configuration metadata for subsystem A may refer to a DataSource by the name of subsystemA-dataSource. The configuration metadata for subsystem B may refer to a DataSource by the name of subsystemB-dataSource. When composing the main application that uses both these subsystems, the main application refers to the DataSource by the name of myApp-dataSource. To have all three names refer to the same object, you can add the following alias definitions to the configuration metadata: Now each component and the main application can refer to the dataSource through a name that is unique and guaranteed not to clash with any other definition (effectively creating a namespace), yet they refer to the same bean. Java-configuration If you use Javaconfiguration, the @Bean annotation can be used to provide aliases. See Using the @Bean Annotation for details. Instantiating Beans A bean definition is essentially a recipe for creating one or more objects. The container looks at the recipe for a named bean when asked and uses the configuration metadata encapsulated by that bean definition to create (or acquire) an actual object. If you use XML-based configuration metadata, you specify the type (or class) of object that is to be instantiated in the class attribute of the element. This class attribute (which, internally, is a Class property on a BeanDefinition instance) is usually mandatory. (For exceptions, see Instantiation by Using an Instance Factory Method and Bean Definition Inheritance.) You can use the Class property in one of two ways: • Typically, to specify the bean class to be constructed in the case where the container itself directly creates the bean by calling its constructor reflectively, somewhat equivalent to Java code with the new operator. • To specify the actual class containing the static factory method that is invoked to create the object, in the less common case where the container invokes a static factory method on a class to create the bean. The object type returned from the invocation of the static factory method may be the same class or another class entirely. Nested class names If you want to configure a bean definition for a nested class, you may use either the binary name or the source name of the nested class. For example, if you have a class called SomeThing in the com.example package, and this SomeThing class has a static nested class called OtherThing, they can be separated by a dollar sign ($) or a dot (.). So the value of the class attribute in a bean definition would be com.example.SomeThing$OtherThing or com.example.SomeThing.OtherThing. Instantiation with a Constructor When you create a bean by the constructor approach, all normal classes are usable by and compatible with Spring. That is, the class being developed does not need to implement any specific interfaces or to be coded in a specific fashion. Simply specifying the bean class should suffice. However, depending on what type of IoC you use for that specific bean, you may need a default (empty) constructor. The Spring IoC container can manage virtually any class you want it to manage. It is not limited to managing true JavaBeans. Most Spring users prefer actual JavaBeans with only a default (no- argument) constructor and appropriate setters and getters modeled after the properties in the container. You can also have more exotic non-bean-style classes in your container. If, for example, you need to use a legacy connection pool that absolutely does not adhere to the JavaBean specification, Spring can manage it as well. With XML-based configuration metadata you can specify your bean class as follows: For details about the mechanism for supplying arguments to the constructor (if required) and setting object instance properties after the object is constructed, see Injecting Dependencies. Instantiation with a Static Factory Method When defining a bean that you create with a static factory method, use the class attribute to specify the class that contains the static factory method and an attribute named factory-method to specify the name of the factory method itself. You should be able to call this method (with optional arguments, as described later) and return a live object, which subsequently is treated as if it had been created through a constructor. One use for such a bean definition is to call static factories in legacy code. The following bean definition specifies that the bean will be created by calling a factory method. The definition does not specify the type (class) of the returned object, but rather the class containing the factory method. In this example, the createInstance() method must be a static method. The following example shows how to specify a factory method: The following example shows a class that would work with the preceding bean definition: Java public class ClientService {   private static ClientService clientService = new ClientService();   private ClientService() {}   public static ClientService createInstance() {   return clientService;   } } Kotlin class ClientService private constructor() {   companion object {   private val clientService = ClientService()   @JvmStatic   fun createInstance() = clientService   } } For details about the mechanism for supplying (optional) arguments to the factory method and setting object instance properties after the object is returned from the factory, see Dependencies and Configuration in Detail. Instantiation by Using an Instance Factory Method Similar to instantiation through a static factory method, instantiation with an instance factory method invokes a non-static method of an existing bean from the container to create a new bean. To use this mechanism, leave the class attribute empty and, in the factory-bean attribute, specify the name of a bean in the current (or parent or ancestor) container that contains the instance method that is to be invoked to create the object. Set the name of the factory method itself with the factory-method attribute. The following example shows how to configure such a bean:   The following example shows the corresponding class: Java public class DefaultServiceLocator {   private static ClientService clientService = new ClientServiceImpl();   public ClientService createClientServiceInstance() {   return clientService;   } } Kotlin class DefaultServiceLocator {   companion object {   private val clientService = ClientServiceImpl()   }   fun createClientServiceInstance(): ClientService {   return clientService   } } One factory class can also hold more than one factory method, as the following example shows:   The following example shows the corresponding class: Java public class DefaultServiceLocator {   private static ClientService clientService = new ClientServiceImpl();   private static AccountService accountService = new AccountServiceImpl();   public ClientService createClientServiceInstance() {   return clientService;   }   public AccountService createAccountServiceInstance() {   return accountService;   } } Kotlin class DefaultServiceLocator {   companion object {   private val clientService = ClientServiceImpl()   private val accountService = AccountServiceImpl()   }   fun createClientServiceInstance(): ClientService {   return clientService   }   fun createAccountServiceInstance(): AccountService {   return accountService   } } This approach shows that the factory bean itself can be managed and configured through dependency injection (DI). See Dependencies and Configuration in Detail. In Spring documentation, "factory bean" refers to a bean that is configured in the Spring container and that creates objects through an instance or static factory  method. By contrast, FactoryBean (notice the capitalization) refers to a Spring- specific FactoryBean implementation class. Determining a Bean’s Runtime Type The runtime type of a specific bean is non-trivial to determine. A specified class in the bean metadata definition is just an initial class reference, potentially combined with a declared factory method or being a FactoryBean class which may lead to a different runtime type of the bean, or not being set at all in case of an instance-level factory method (which is resolved via the specified factory-bean name instead). Additionally, AOP proxying may wrap a bean instance with an interface-based proxy with limited exposure of the target bean’s actual type (just its implemented interfaces). The recommended way to find out about the actual runtime type of a particular bean is a BeanFactory.getType call for the specified bean name. This takes all of the above cases into account and returns the type of object that a BeanFactory.getBean call is going to return for the same bean name. 2.1.4. Dependencies A typical enterprise application does not consist of a single object (or bean in the Spring parlance). Even the simplest application has a few objects that work together to present what the end-user sees as a coherent application. This next section explains how you go from defining a number of bean definitions that stand alone to a fully realized application where objects collaborate to achieve a goal. Dependency Injection Dependency injection (DI) is a process whereby objects define their dependencies (that is, the other objects with which they work) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies on its own by using direct construction of classes or the Service Locator pattern. Code is cleaner with the DI principle, and decoupling is more effective when objects are provided with their dependencies. The object does not look up its dependencies and does not know the location or class of the dependencies. As a result, your classes become easier to test, particularly when the dependencies are on interfaces or abstract base classes, which allow for stub or mock implementations to be used in unit tests. DI exists in two major variants: Constructor-based dependency injection and Setter-based dependency injection. Constructor-based Dependency Injection Constructor-based DI is accomplished by the container invoking a constructor with a number of arguments, each representing a dependency. Calling a static factory method with specific arguments to construct the bean is nearly equivalent, and this discussion treats arguments to a constructor and to a static factory method similarly. The following example shows a class that can only be dependency-injected with constructor injection: Java public class SimpleMovieLister {   // the SimpleMovieLister has a dependency on a MovieFinder   private final MovieFinder movieFinder;   // a constructor so that the Spring container can inject a MovieFinder   public SimpleMovieLister(MovieFinder movieFinder) {   this.movieFinder = movieFinder;   }   // business logic that actually uses the injected MovieFinder is omitted... } Kotlin // a constructor so that the Spring container can inject a MovieFinder class SimpleMovieLister(private val movieFinder: MovieFinder) {   // business logic that actually uses the injected MovieFinder is omitted... } Notice that there is nothing special about this class. It is a POJO that has no dependencies on container specific interfaces, base classes, or annotations. Constructor Argument Resolution Constructor argument resolution matching occurs by using the argument’s type. If no potential ambiguity exists in the constructor arguments of a bean definition, the order in which the constructor arguments are defined in a bean definition is the order in which those arguments are supplied to the appropriate constructor when the bean is being instantiated. Consider the following class: Java package x.y; public class ThingOne {   public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {   // ...   } } Kotlin package x.y class ThingOne(thingTwo: ThingTwo, thingThree: ThingThree) Assuming that the ThingTwo and ThingThree classes are not related by inheritance, no potential ambiguity exists. Thus, the following configuration works fine, and you do not need to specify the constructor argument indexes or types explicitly in the element.             When another bean is referenced, the type is known, and matching can occur (as was the case with the preceding example). When a simple type is used, such as true, Spring cannot determine the type of the value, and so cannot match by type without help. Consider the following class: Java package examples; public class ExampleBean {   // Number of years to calculate the Ultimate Answer   private final int years;   // The Answer to Life, the Universe, and Everything   private final String ultimateAnswer;   public ExampleBean(int years, String ultimateAnswer) {   this.years = years;   this.ultimateAnswer = ultimateAnswer;   } } Kotlin package examples class ExampleBean(   private val years: Int, // Number of years to calculate the Ultimate Answer   private val ultimateAnswer: String // The Answer to Life, the Universe, and Everything ) Constructor argument type matching In the preceding scenario, the container can use type matching with simple types if you explicitly specify the type of the constructor argument by using the type attribute, as the following example shows:     Constructor argument index You can use the index attribute to specify explicitly the index of constructor arguments, as the following example shows:     In addition to resolving the ambiguity of multiple simple values, specifying an index resolves ambiguity where a constructor has two arguments of the same type.  The index is 0-based. Constructor argument name You can also use the constructor parameter name for value disambiguation, as the following example shows:     Keep in mind that, to make this work out of the box, your code must be compiled with the debug flag enabled so that Spring can look up the parameter name from the constructor. If you cannot or do not want to compile your code with the debug flag, you can use the @ConstructorProperties JDK annotation to explicitly name your constructor arguments. The sample class would then have to look as follows: Java package examples; public class ExampleBean {   // Fields omitted   @ConstructorProperties({"years", "ultimateAnswer"})   public ExampleBean(int years, String ultimateAnswer) {   this.years = years;   this.ultimateAnswer = ultimateAnswer;   } } Kotlin package examples class ExampleBean @ConstructorProperties("years", "ultimateAnswer") constructor(val years: Int, val ultimateAnswer: String) Setter-based Dependency Injection Setter-based DI is accomplished by the container calling setter methods on your beans after invoking a no-argument constructor or a no-argument static factory method to instantiate your bean. The following example shows a class that can only be dependency-injected by using pure setter injection. This class is conventional Java. It is a POJO that has no dependencies on container specific interfaces, base classes, or annotations. Java public class SimpleMovieLister {   // the SimpleMovieLister has a dependency on the MovieFinder   private MovieFinder movieFinder;   // a setter method so that the Spring container can inject a MovieFinder   public void setMovieFinder(MovieFinder movieFinder) {   this.movieFinder = movieFinder;   }   // business logic that actually uses the injected MovieFinder is omitted... } Kotlin class SimpleMovieLister {   // a late-initialized property so that the Spring container can inject a MovieFinder   lateinit var movieFinder: MovieFinder   // business logic that actually uses the injected MovieFinder is omitted... } The ApplicationContext supports constructor-based and setter-based DI for the beans it manages. It also supports setter-based DI after some dependencies have already been injected through the constructor approach. You configure the dependencies in the form of a BeanDefinition, which you use in conjunction with PropertyEditor instances to convert properties from one format to another. However, most Spring users do not work with these classes directly (that is, programmatically) but rather with XML bean definitions, annotated components (that is, classes annotated with @Component, @Controller, and so forth), or @Bean methods in Java-based @Configuration classes. These sources are then converted internally into instances of BeanDefinition and used to load an entire Spring IoC container instance. Constructor-based or setter-based DI? Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies. Note that use of the @Autowired annotation on a setter method can be used to make the property be a required dependency; however, constructor injection with programmatic validation of arguments is preferable. The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null. Furthermore, constructor-injected components are always returned to the client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns. Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection. Use the DI style that makes the most sense for a particular class. Sometimes, when dealing with third-party classes for which you do not have the source, the choice is made for you. For example, if a third-party class does not expose any setter methods, then constructor injection may be the only available form of DI. Dependency Resolution Process The container performs bean dependency resolution as follows: • The ApplicationContext is created and initialized with configuration metadata that describes all the beans. Configuration metadata can be specified by XML, Java code, or annotations. • For each bean, its dependencies are expressed in the form of properties, constructor arguments, or arguments to the static-factory method (if you use that instead of a normal constructor). These dependencies are provided to the bean, when the bean is actually created. • Each property or constructor argument is an actual definition of the value to set, or a reference to another bean in the container. • Each property or constructor argument that is a value is converted from its specified format to the actual type of that property or constructor argument. By default, Spring can convert a value supplied in string format to all built-in types, such as int, long, String, boolean, and so forth. The Spring container validates the configuration of each bean as the container is created. However, the bean properties themselves are not set until the bean is actually created. Beans that are singleton-scoped and set to be pre-instantiated (the default) are created when the container is created. Scopes are defined in Bean Scopes. Otherwise, the bean is created only when it is requested. Creation of a bean potentially causes a graph of beans to be created, as the bean’s dependencies and its dependencies' dependencies (and so on) are created and assigned. Note that resolution mismatches among those dependencies may show up late — that is, on first creation of the affected bean. Circular dependencies If you use predominantly constructor injection, it is possible to create an unresolvable circular dependency scenario. For example: Class A requires an instance of class B through constructor injection, and class B requires an instance of class A through constructor injection. If you configure beans for classes A and B to be injected into each other, the Spring IoC container detects this circular reference at runtime, and throws a BeanCurrentlyInCreationException. One possible solution is to edit the source code of some classes to be configured by setters rather than constructors. Alternatively, avoid constructor injection and use setter injection only. In other words, although it is not recommended, you can configure circular dependencies with setter injection. Unlike the typical case (with no circular dependencies), a circular dependency between bean A and bean B forces one of the beans to be injected into the other prior to being fully initialized itself (a classic chicken-and-egg scenario). You can generally trust Spring to do the right thing. It detects configuration problems, such as references to non-existent beans and circular dependencies, at container load-time. Spring sets properties and resolves dependencies as late as possible, when the bean is actually created. This means that a Spring container that has loaded correctly can later generate an exception when you request an object if there is a problem creating that object or one of its dependencies — for example, the bean throws an exception as a result of a missing or invalid property. This potentially delayed visibility of some configuration issues is why ApplicationContext implementations by default pre-instantiate singleton beans. At the cost of some upfront time and memory to create these beans before they are actually needed, you discover configuration issues when the ApplicationContext is created, not later. You can still override this default behavior so that singleton beans initialize lazily, rather than being eagerly pre-instantiated. If no circular dependencies exist, when one or more collaborating beans are being injected into a dependent bean, each collaborating bean is totally configured prior to being injected into the dependent bean. This means that, if bean A has a dependency on bean B, the Spring IoC container completely configures bean B prior to invoking the setter method on bean A. In other words, the bean is instantiated (if it is not a pre-instantiated singleton), its dependencies are set, and the relevant lifecycle methods (such as a configured init method or the InitializingBean callback method) are invoked. Examples of Dependency Injection The following example uses XML-based configuration metadata for setter-based DI. A small part of a Spring XML configuration file specifies some bean definitions as follows:               The following example shows the corresponding ExampleBean class: Java public class ExampleBean {   private AnotherBean beanOne;   private YetAnotherBean beanTwo;   private int i;   public void setBeanOne(AnotherBean beanOne) {   this.beanOne = beanOne;   }   public void setBeanTwo(YetAnotherBean beanTwo) {   this.beanTwo = beanTwo;   }   public void setIntegerProperty(int i) {   this.i = i;   } } Kotlin class ExampleBean {   lateinit var beanOne: AnotherBean   lateinit var beanTwo: YetAnotherBean   var i: Int = 0 } In the preceding example, setters are declared to match against the properties specified in the XML file. The following example uses constructor-based DI:               The following example shows the corresponding ExampleBean class: Java public class ExampleBean {   private AnotherBean beanOne;   private YetAnotherBean beanTwo;   private int i;   public ExampleBean(   AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {   this.beanOne = anotherBean;   this.beanTwo = yetAnotherBean;   this.i = i;   } } Kotlin class ExampleBean(   private val beanOne: AnotherBean,   private val beanTwo: YetAnotherBean,   private val i: Int) The constructor arguments specified in the bean definition are used as arguments to the constructor of the ExampleBean. Now consider a variant of this example, where, instead of using a constructor, Spring is told to call a static factory method to return an instance of the object:       The following example shows the corresponding ExampleBean class: Java public class ExampleBean {   // a private constructor   private ExampleBean(...) {   ...   }   // a static factory method; the arguments to this method can be   // considered the dependencies of the bean that is returned,   // regardless of how those arguments are actually used.   public static ExampleBean createInstance (   AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {   ExampleBean eb = new ExampleBean (...);   // some other operations...   return eb;   } } Kotlin class ExampleBean private constructor() {   companion object {   // a static factory method; the arguments to this method can be   // considered the dependencies of the bean that is returned,   // regardless of how those arguments are actually used.   @JvmStatic   fun createInstance(anotherBean: AnotherBean, yetAnotherBean: YetAnotherBean, i: Int): ExampleBean {   val eb = ExampleBean (...)   // some other operations...   return eb   }   } } Arguments to the static factory method are supplied by elements, exactly the same as if a constructor had actually been used. The type of the class being returned by the factory method does not have to be of the same type as the class that contains the static factory method (although, in this example, it is). An instance (non-static) factory method can be used in an essentially identical fashion (aside from the use of the factory-bean attribute instead of the class attribute), so we do not discuss those details here. Dependencies and Configuration in Detail As mentioned in the previous section, you can define bean properties and constructor arguments as references to other managed beans (collaborators) or as values defined inline. Spring’s XML-based configuration metadata supports sub-element types within its and elements for this purpose. Straight Values (Primitives, Strings, and so on) The value attribute of the element specifies a property or constructor argument as a human-readable string representation. Spring’s conversion service is used to convert these values from a String to the actual type of the property or argument. The following example shows various values being set:           The following example uses the p-namespace for even more succinct XML configuration:   The preceding XML is more succinct. However, typos are discovered at runtime rather than design time, unless you use an IDE (such as IntelliJ IDEA or the Spring Tools for Eclipse) that supports automatic property completion when you create bean definitions. Such IDE assistance is highly recommended. You can also configure a java.util.Properties instance, as follows:         jdbc.driver.className=com.mysql.jdbc.Driver   jdbc.url=jdbc:mysql://localhost:3306/mydb     The Spring container converts the text inside the element into a java.util.Properties instance by using the JavaBeans PropertyEditor mechanism. This is a nice shortcut, and is one of a few places where the Spring team do favor the use of the nested element over the value attribute style. The idref element The idref element is simply an error-proof way to pass the id (a string value - not a reference) of another bean in the container to a or element. The following example shows how to use it:       The preceding bean definition snippet is exactly equivalent (at runtime) to the following snippet:   The first form is preferable to the second, because using the idref tag lets the container validate at deployment time that the referenced, named bean actually exists. In the second variation, no validation is performed on the value that is passed to the targetName property of the client bean. Typos are only discovered (with most likely fatal results) when the client bean is actually instantiated. If the client bean is a prototype bean, this typo and the resulting exception may only be discovered long after the container is deployed. The local attribute on the idref element is no longer supported in the 4.0 beans XSD, since it does not provide value over a regular bean reference any more.  Change your existing idref local references to idref bean when upgrading to the 4.0 schema. A common place (at least in versions earlier than Spring 2.0) where the element brings value is in the configuration of AOP interceptors in a ProxyFactoryBean bean definition. Using elements when you specify the interceptor names prevents you from misspelling an interceptor ID. References to Other Beans (Collaborators) The ref element is the final element inside a or definition element. Here, you set the value of the specified property of a bean to be a reference to another bean (a collaborator) managed by the container. The referenced bean is a dependency of the bean whose property is to be set, and it is initialized on demand as needed before the property is set. (If the collaborator is a singleton bean, it may already be initialized by the container.) All references are ultimately a reference to another object. Scoping and validation depend on whether you specify the ID or name of the other object through the bean or parent attribute. Specifying the target bean through the bean attribute of the tag is the most general form and allows creation of a reference to any bean in the same container or parent container, regardless of whether it is in the same XML file. The value of the bean attribute may be the same as the id attribute of the target bean or be the same as one of the values in the name attribute of the target bean. The following example shows how to use a ref element: Specifying the target bean through the parent attribute creates a reference to a bean that is in a parent container of the current container. The value of the parent attribute may be the same as either the id attribute of the target bean or one of the values in the name attribute of the target bean. The target bean must be in a parent container of the current one. You should use this bean reference variant mainly when you have a hierarchy of containers and you want to wrap an existing bean in a parent container with a proxy that has the same name as the parent bean. The following pair of listings shows how to use the parent attribute:           The local attribute on the ref element is no longer supported in the 4.0 beans XSD,  since it does not provide value over a regular bean reference any more. Change your existing ref local references to ref bean when upgrading to the 4.0 schema. Inner Beans A element inside the or elements defines an inner bean, as the following example shows:               An inner bean definition does not require a defined ID or name. If specified, the container does not use such a value as an identifier. The container also ignores the scope flag on creation, because inner beans are always anonymous and are always created with the outer bean. It is not possible to access inner beans independently or to inject them into collaborating beans other than into the enclosing bean. As a corner case, it is possible to receive destruction callbacks from a custom scope — for example, for a request-scoped inner bean contained within a singleton bean. The creation of the inner bean instance is tied to its containing bean, but destruction callbacks let it participate in the request scope’s lifecycle. This is not a common scenario. Inner beans typically simply share their containing bean’s scope. Collections The , , , and elements set the properties and arguments of the Java Collection types List, Set, Map, and Properties, respectively. The following example shows how to use them:         administrator@example.org   support@example.org   development@example.org             a list element followed by a reference                             just some string       The value of a map key or value, or a set value, can also be any of the following elements: bean | ref | idref | list | set | map | props | value | null Collection Merging The Spring container also supports merging collections. An application developer can define a parent , , or element and have child , , or elements inherit and override values from the parent collection. That is, the child collection’s values are the result of merging the elements of the parent and child collections, with the child’s collection elements overriding values specified in the parent collection. This section on merging discusses the parent-child bean mechanism. Readers unfamiliar with parent and child bean definitions may wish to read the relevant section before continuing. The following example demonstrates collection merging:         administrator@example.com   support@example.com                 sales@example.com   support@example.co.uk       Notice the use of the merge=true attribute on the element of the adminEmails property of the child bean definition. When the child bean is resolved and instantiated by the container, the resulting instance has an adminEmails Properties collection that contains the result of merging the child’s adminEmails collection with the parent’s adminEmails collection. The following listing shows the result: administrator=administrator@example.com sales=sales@example.com support=support@example.co.uk The child Properties collection’s value set inherits all property elements from the parent , and the child’s value for the support value overrides the value in the parent collection. This merging behavior applies similarly to the , , and collection types. In the specific case of the element, the semantics associated with the List collection type (that is, the notion of an ordered collection of values) is maintained. The parent’s values precede all of the child list’s values. In the case of the Map, Set, and Properties collection types, no ordering exists. Hence, no ordering semantics are in effect for the collection types that underlie the associated Map, Set, and Properties implementation types that the container uses internally. Limitations of Collection Merging You cannot merge different collection types (such as a Map and a List). If you do attempt to do so, an appropriate Exception is thrown. The merge attribute must be specified on the lower, inherited, child definition. Specifying the merge attribute on a parent collection definition is redundant and does not result in the desired merging. Strongly-typed collection Thanks to Java’s support for generic types, you can use strongly typed collections. That is, it is possible to declare a Collection type such that it can only contain (for example) String elements. If you use Spring to dependency-inject a strongly-typed Collection into a bean, you can take advantage of Spring’s type-conversion support such that the elements of your strongly-typed Collection instances are converted to the appropriate type prior to being added to the Collection. The following Java class and bean definition show how to do so: Java public class SomeClass {   private Map accounts;   public void setAccounts(Map accounts) {   this.accounts = accounts;   } } Kotlin class SomeClass {   lateinit var accounts: Map }                   When the accounts property of the something bean is prepared for injection, the generics information about the element type of the strongly-typed Map is available by reflection. Thus, Spring’s type conversion infrastructure recognizes the various value elements as being of type Float, and the string values (9.99, 2.75, and 3.99) are converted into an actual Float type. Null and Empty String Values Spring treats empty arguments for properties and the like as empty Strings. The following XML- based configuration metadata snippet sets the email property to the empty String value ("").   The preceding example is equivalent to the following Java code: Java exampleBean.setEmail(""); Kotlin exampleBean.email = "" The element handles null values. The following listing shows an example:       The preceding configuration is equivalent to the following Java code: Java exampleBean.setEmail(null); Kotlin exampleBean.email = null XML Shortcut with the p-namespace The p-namespace lets you use the bean element’s attributes (instead of nested elements) to describe your property values collaborating beans, or both. Spring supports extensible configuration formats with namespaces, which are based on an XML Schema definition. The beans configuration format discussed in this chapter is defined in an XML Schema document. However, the p-namespace is not defined in an XSD file and exists only in the core of Spring. The following example shows two XML snippets (the first uses standard XML format and the second uses the p-namespace) that resolve to the same result:         The example shows an attribute in the p-namespace called email in the bean definition. This tells Spring to include a property declaration. As previously mentioned, the p-namespace does not have a schema definition, so you can set the name of the attribute to the property name. This next example includes two more bean definitions that both have a reference to another bean:                 This example includes not only a property value using the p-namespace but also uses a special format to declare property references. Whereas the first bean definition uses to create a reference from bean john to bean jane, the second bean definition uses p:spouse-ref="jane" as an attribute to do the exact same thing. In this case, spouse is the property name, whereas the -ref part indicates that this is not a straight value but rather a reference to another bean. The p-namespace is not as flexible as the standard XML format. For example, the format for declaring property references clashes with properties that end in Ref,  whereas the standard XML format does not. We recommend that you choose your approach carefully and communicate this to your team members to avoid producing XML documents that use all three approaches at the same time. XML Shortcut with the c-namespace Similar to the XML Shortcut with the p-namespace, the c-namespace, introduced in Spring 3.1, allows inlined attributes for configuring the constructor arguments rather then nested constructor- arg elements. The following example uses the c: namespace to do the same thing as the from Constructor-based Dependency Injection:                     The c: namespace uses the same conventions as the p: one (a trailing -ref for bean references) for setting the constructor arguments by their names. Similarly, it needs to be declared in the XML file even though it is not defined in an XSD schema (it exists inside the Spring core). For the rare cases where the constructor argument names are not available (usually if the bytecode was compiled without debugging information), you can use fallback to the argument indexes, as follows: Due to the XML grammar, the index notation requires the presence of the leading _, as XML attribute names cannot start with a number (even though some IDEs  allow it). A corresponding index notation is also available for elements but not commonly used since the plain order of declaration is usually sufficient there. In practice, the constructor resolution mechanism is quite efficient in matching arguments, so unless you really need to, we recommend using the name notation throughout your configuration. Compound Property Names You can use compound or nested property names when you set bean properties, as long as all components of the path except the final property name are not null. Consider the following bean definition:   The something bean has a fred property, which has a bob property, which has a sammy property, and that final sammy property is being set to a value of 123. In order for this to work, the fred property of something and the bob property of fred must not be null after the bean is constructed. Otherwise, a NullPointerException is thrown. Using depends-on If a bean is a dependency of another bean, that usually means that one bean is set as a property of another. Typically you accomplish this with the element in XML-based configuration metadata. However, sometimes dependencies between beans are less direct. An example is when a static initializer in a class needs to be triggered, such as for database driver registration. The depends-on attribute can explicitly force one or more beans to be initialized before the bean using this element is initialized. The following example uses the depends-on attribute to express a dependency on a single bean: To express a dependency on multiple beans, supply a list of bean names as the value of the depends- on attribute (commas, whitespace, and semicolons are valid delimiters):   The depends-on attribute can specify both an initialization-time dependency and, in the case of singleton beans only, a corresponding destruction-time dependency.  Dependent beans that define a depends-on relationship with a given bean are destroyed first, prior to the given bean itself being destroyed. Thus, depends-on can also control shutdown order. Lazy-initialized Beans By default, ApplicationContext implementations eagerly create and configure all singleton beans as part of the initialization process. Generally, this pre-instantiation is desirable, because errors in the configuration or surrounding environment are discovered immediately, as opposed to hours or even days later. When this behavior is not desirable, you can prevent pre-instantiation of a singleton bean by marking the bean definition as being lazy-initialized. A lazy-initialized bean tells the IoC container to create a bean instance when it is first requested, rather than at startup. In XML, this behavior is controlled by the lazy-init attribute on the element, as the following example shows: When the preceding configuration is consumed by an ApplicationContext, the lazy bean is not eagerly pre-instantiated when the ApplicationContext starts, whereas the not.lazy bean is eagerly pre-instantiated. However, when a lazy-initialized bean is a dependency of a singleton bean that is not lazy- initialized, the ApplicationContext creates the lazy-initialized bean at startup, because it must satisfy the singleton’s dependencies. The lazy-initialized bean is injected into a singleton bean elsewhere that is not lazy-initialized. You can also control lazy-initialization at the container level by using the default-lazy-init attribute on the element, as the following example shows:   Autowiring Collaborators The Spring container can autowire relationships between collaborating beans. You can let Spring resolve collaborators (other beans) automatically for your bean by inspecting the contents of the ApplicationContext. Autowiring has the following advantages: • Autowiring can significantly reduce the need to specify properties or constructor arguments. (Other mechanisms such as a bean template discussed elsewhere in this chapter are also valuable in this regard.) • Autowiring can update a configuration as your objects evolve. For example, if you need to add a dependency to a class, that dependency can be satisfied automatically without you needing to modify the configuration. Thus autowiring can be especially useful during development, without negating the option of switching to explicit wiring when the code base becomes more stable. When using XML-based configuration metadata (see Dependency Injection), you can specify the autowire mode for a bean definition with the autowire attribute of the element. The autowiring functionality has four modes. You specify autowiring per bean and can thus choose which ones to autowire. The following table describes the four autowiring modes: Table 2. Autowiring modes Mode Explanation no (Default) No autowiring. Bean references must be defined by ref elements. Changing the default setting is not recommended for larger deployments, because specifying collaborators explicitly gives greater control and clarity. To some extent, it documents the structure of a system. byName Autowiring by property name. Spring looks for a bean with the same name as the property that needs to be autowired. For example, if a bean definition is set to autowire by name and it contains a master property (that is, it has a setMaster(..) method), Spring looks for a bean definition named master and uses it to set the property. byType Lets a property be autowired if exactly one bean of the property type exists in the container. If more than one exists, a fatal exception is thrown, which indicates that you may not use byType autowiring for that bean. If there are no matching beans, nothing happens (the property is not set). constructor Analogous to byType but applies to constructor arguments. If there is not exactly one bean of the constructor argument type in the container, a fatal error is raised. With byType or constructor autowiring mode, you can wire arrays and typed collections. In such cases, all autowire candidates within the container that match the expected type are provided to satisfy the dependency. You can autowire strongly-typed Map instances if the expected key type is String. An autowired Map instance’s values consist of all bean instances that match the expected type, and the Map instance’s keys contain the corresponding bean names. Limitations and Disadvantages of Autowiring Autowiring works best when it is used consistently across a project. If autowiring is not used in general, it might be confusing to developers to use it to wire only one or two bean definitions. Consider the limitations and disadvantages of autowiring: • Explicit dependencies in property and constructor-arg settings always override autowiring. You cannot autowire simple properties such as primitives, Strings, and Classes (and arrays of such simple properties). This limitation is by-design. • Autowiring is less exact than explicit wiring. Although, as noted in the earlier table, Spring is careful to avoid guessing in case of ambiguity that might have unexpected results. The relationships between your Spring-managed objects are no longer documented explicitly. • Wiring information may not be available to tools that may generate documentation from a Spring container. • Multiple bean definitions within the container may match the type specified by the setter method or constructor argument to be autowired. For arrays, collections, or Map instances, this is not necessarily a problem. However, for dependencies that expect a single value, this ambiguity is not arbitrarily resolved. If no unique bean definition is available, an exception is thrown. In the latter scenario, you have several options: • Abandon autowiring in favor of explicit wiring. • Avoid autowiring for a bean definition by setting its autowire-candidate attributes to false, as described in the next section. • Designate a single bean definition as the primary candidate by setting the primary attribute of its element to true. • Implement the more fine-grained control available with annotation-based configuration, as described in Annotation-based Container Configuration. Excluding a Bean from Autowiring On a per-bean basis, you can exclude a bean from autowiring. In Spring’s XML format, set the autowire-candidate attribute of the element to false. The container makes that specific bean definition unavailable to the autowiring infrastructure (including annotation style configurations such as @Autowired). The autowire-candidate attribute is designed to only affect type-based autowiring. It does not affect explicit references by name, which get resolved even if the  specified bean is not marked as an autowire candidate. As a consequence, autowiring by name nevertheless injects a bean if the name matches. You can also limit autowire candidates based on pattern-matching against bean names. The top- level element accepts one or more patterns within its default-autowire-candidates attribute. For example, to limit autowire candidate status to any bean whose name ends with Repository, provide a value of *Repository. To provide multiple patterns, define them in a comma- separated list. An explicit value of true or false for a bean definition’s autowire-candidate attribute always takes precedence. For such beans, the pattern matching rules do not apply. These techniques are useful for beans that you never want to be injected into other beans by autowiring. It does not mean that an excluded bean cannot itself be configured by using autowiring. Rather, the bean itself is not a candidate for autowiring other beans. Method Injection In most application scenarios, most beans in the container are singletons. When a singleton bean needs to collaborate with another singleton bean or a non-singleton bean needs to collaborate with another non-singleton bean, you typically handle the dependency by defining one bean as a property of the other. A problem arises when the bean lifecycles are different. Suppose singleton bean A needs to use non-singleton (prototype) bean B, perhaps on each method invocation on A. The container creates the singleton bean A only once, and thus only gets one opportunity to set the properties. The container cannot provide bean A with a new instance of bean B every time one is needed. A solution is to forego some inversion of control. You can make bean A aware of the container by implementing the ApplicationContextAware interface, and by making a getBean("B") call to the container ask for (a typically new) bean B instance every time bean A needs it. The following example shows this approach: Java // a class that uses a stateful Command-style class to perform some processing package fiona.apple; // Spring-API imports import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class CommandManager implements ApplicationContextAware {   private ApplicationContext applicationContext;   public Object process(Map commandState) {   // grab a new instance of the appropriate Command   Command command = createCommand();   // set the state on the (hopefully brand new) Command instance   command.setState(commandState);   return command.execute();   }   protected Command createCommand() {   // notice the Spring API dependency!   return this.applicationContext.getBean("command", Command.class);   }   public void setApplicationContext(   ApplicationContext applicationContext) throws BeansException {   this.applicationContext = applicationContext;   } } Kotlin // a class that uses a stateful Command-style class to perform some processing package fiona.apple // Spring-API imports import org.springframework.context.ApplicationContext import org.springframework.context.ApplicationContextAware class CommandManager : ApplicationContextAware {   private lateinit var applicationContext: ApplicationContext   fun process(commandState: Map<*, *>): Any {   // grab a new instance of the appropriate Command   val command = createCommand()   // set the state on the (hopefully brand new) Command instance   command.state = commandState   return command.execute()   }   // notice the Spring API dependency!   protected fun createCommand() =   applicationContext.getBean("command", Command::class.java)   override fun setApplicationContext(applicationContext: ApplicationContext) {   this.applicationContext = applicationContext   } } The preceding is not desirable, because the business code is aware of and coupled to the Spring Framework. Method Injection, a somewhat advanced feature of the Spring IoC container, lets you handle this use case cleanly. You can read more about the motivation for Method Injection in this blog entry. Lookup Method Injection Lookup method injection is the ability of the container to override methods on container-managed beans and return the lookup result for another named bean in the container. The lookup typically involves a prototype bean, as in the scenario described in the preceding section. The Spring Framework implements this method injection by using bytecode generation from the CGLIB library to dynamically generate a subclass that overrides the method. • For this dynamic subclassing to work, the class that the Spring bean container subclasses cannot be final, and the method to be overridden cannot be final, either. • Unit-testing a class that has an abstract method requires you to subclass the class yourself and to supply a stub implementation of the abstract method.  • Concrete methods are also necessary for component scanning, which requires concrete classes to pick up. • A further key limitation is that lookup methods do not work with factory methods and in particular not with @Bean methods in configuration classes, since, in that case, the container is not in charge of creating the instance and therefore cannot create a runtime-generated subclass on the fly. In the case of the CommandManager class in the previous code snippet, the Spring container dynamically overrides the implementation of the createCommand() method. The CommandManager class does not have any Spring dependencies, as the reworked example shows: Java package fiona.apple; // no more Spring imports! public abstract class CommandManager {   public Object process(Object commandState) {   // grab a new instance of the appropriate Command interface   Command command = createCommand();   // set the state on the (hopefully brand new) Command instance   command.setState(commandState);   return command.execute();   }   // okay... but where is the implementation of this method?   protected abstract Command createCommand(); } Kotlin package fiona.apple // no more Spring imports! abstract class CommandManager {   fun process(commandState: Any): Any {   // grab a new instance of the appropriate Command interface   val command = createCommand()   // set the state on the (hopefully brand new) Command instance   command.state = commandState   return command.execute()   }   // okay... but where is the implementation of this method?   protected abstract fun createCommand(): Command } In the client class that contains the method to be injected (the CommandManager in this case), the method to be injected requires a signature of the following form: [abstract] theMethodName(no-arguments); If the method is abstract, the dynamically-generated subclass implements the method. Otherwise, the dynamically-generated subclass overrides the concrete method defined in the original class. Consider the following example:     The bean identified as commandManager calls its own createCommand() method whenever it needs a new instance of the myCommand bean. You must be careful to deploy the myCommand bean as a prototype if that is actually what is needed. If it is a singleton, the same instance of the myCommand bean is returned each time. Alternatively, within the annotation-based component model, you can declare a lookup method through the @Lookup annotation, as the following example shows: Java public abstract class CommandManager {   public Object process(Object commandState) {   Command command = createCommand();   command.setState(commandState);   return command.execute();   }   @Lookup("myCommand")   protected abstract Command createCommand(); } Kotlin abstract class CommandManager {   fun process(commandState: Any): Any {   val command = createCommand()   command.state = commandState   return command.execute()   }   @Lookup("myCommand")   protected abstract fun createCommand(): Command } Or, more idiomatically, you can rely on the target bean getting resolved against the declared return type of the lookup method: Java public abstract class CommandManager {   public Object process(Object commandState) {   Command command = createCommand();   command.setState(commandState);   return command.execute();   }   @Lookup   protected abstract Command createCommand(); } Kotlin abstract class CommandManager {   fun process(commandState: Any): Any {   val command = createCommand()   command.state = commandState   return command.execute()   }   @Lookup   protected abstract fun createCommand(): Command } Note that you should typically declare such annotated lookup methods with a concrete stub implementation, in order for them to be compatible with Spring’s component scanning rules where abstract classes get ignored by default. This limitation does not apply to explicitly registered or explicitly imported bean classes. Another way of accessing differently scoped target beans is an ObjectFactory/ Provider injection point. See Scoped Beans as Dependencies.  You may also find the ServiceLocatorFactoryBean (in the org.springframework.beans.factory.config package) to be useful. Arbitrary Method Replacement A less useful form of method injection than lookup method injection is the ability to replace arbitrary methods in a managed bean with another method implementation. You can safely skip the rest of this section until you actually need this functionality. With XML-based configuration metadata, you can use the replaced-method element to replace an existing method implementation with another, for a deployed bean. Consider the following class, which has a method called computeValue that we want to override: Java public class MyValueCalculator {   public String computeValue(String input) {   // some real code...   }   // some other methods... } Kotlin class MyValueCalculator {   fun computeValue(input: String): String {   // some real code...   }   // some other methods... } A class that implements the org.springframework.beans.factory.support.MethodReplacer interface provides the new method definition, as the following example shows: Java /**  * meant to be used to override the existing computeValue(String)  * implementation in MyValueCalculator  */ public class ReplacementComputeValue implements MethodReplacer {   public Object reimplement(Object o, Method m, Object[] args) throws Throwable {   // get the input value, work with it, and return a computed result   String input = (String) args[0];   ...   return ...;   } } Kotlin /**  * meant to be used to override the existing computeValue(String)  * implementation in MyValueCalculator  */ class ReplacementComputeValue : MethodReplacer {   override fun reimplement(obj: Any, method: Method, args: Array): Any {   // get the input value, work with it, and return a computed result   val input = args[0] as String;   ...   return ...;   } } The bean definition to deploy the original class and specify the method override would resemble the following example:       String   You can use one or more elements within the element to indicate the method signature of the method being overridden. The signature for the arguments is necessary only if the method is overloaded and multiple variants exist within the class. For convenience, the type string for an argument may be a substring of the fully qualified type name. For example, the following all match java.lang.String: java.lang.String String Str Because the number of arguments is often enough to distinguish between each possible choice, this shortcut can save a lot of typing, by letting you type only the shortest string that matches an argument type. 2.1.5. Bean Scopes When you create a bean definition, you create a recipe for creating actual instances of the class defined by that bean definition. The idea that a bean definition is a recipe is important, because it means that, as with a class, you can create many object instances from a single recipe. You can control not only the various dependencies and configuration values that are to be plugged into an object that is created from a particular bean definition but also control the scope of the objects created from a particular bean definition. This approach is powerful and flexible, because you can choose the scope of the objects you create through configuration instead of having to bake in the scope of an object at the Java class level. Beans can be defined to be deployed in one of a number of scopes. The Spring Framework supports six scopes, four of which are available only if you use a web-aware ApplicationContext. You can also create a custom scope. The following table describes the supported scopes: Table 3. Bean scopes Scope Description singleton (Default) Scopes a single bean definition to a single object instance for each Spring IoC container. prototype Scopes a single bean definition to any number of object instances. Scope Description request Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext. session Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext. application Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext. websocket Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext. As of Spring 3.0, a thread scope is available but is not registered by default. For  more information, see the documentation for SimpleThreadScope. For instructions on how to register this or any other custom scope, see Using a Custom Scope. The Singleton Scope Only one shared instance of a singleton bean is managed, and all requests for beans with an ID or IDs that match that bean definition result in that one specific bean instance being returned by the Spring container. To put it another way, when you define a bean definition and it is scoped as a singleton, the Spring IoC container creates exactly one instance of the object defined by that bean definition. This single instance is stored in a cache of such singleton beans, and all subsequent requests and references for that named bean return the cached object. The following image shows how the singleton scope works: Spring’s concept of a singleton bean differs from the singleton pattern as defined in the Gang of Four (GoF) patterns book. The GoF singleton hard-codes the scope of an object such that one and only one instance of a particular class is created per ClassLoader. The scope of the Spring singleton is best described as being per-container and per-bean. This means that, if you define one bean for a particular class in a single Spring container, the Spring container creates one and only one instance of the class defined by that bean definition. The singleton scope is the default scope in Spring. To define a bean as a singleton in XML, you can define a bean as shown in the following example: The Prototype Scope The non-singleton prototype scope of bean deployment results in the creation of a new bean instance every time a request for that specific bean is made. That is, the bean is injected into another bean or you request it through a getBean() method call on the container. As a rule, you should use the prototype scope for all stateful beans and the singleton scope for stateless beans. The following diagram illustrates the Spring prototype scope: (A data access object (DAO) is not typically configured as a prototype, because a typical DAO does not hold any conversational state. It was easier for us to reuse the core of the singleton diagram.) The following example defines a bean as a prototype in XML: In contrast to the other scopes, Spring does not manage the complete lifecycle of a prototype bean. The container instantiates, configures, and otherwise assembles a prototype object and hands it to the client, with no further record of that prototype instance. Thus, although initialization lifecycle callback methods are called on all objects regardless of scope, in the case of prototypes, configured destruction lifecycle callbacks are not called. The client code must clean up prototype-scoped objects and release expensive resources that the prototype beans hold. To get the Spring container to release resources held by prototype-scoped beans, try using a custom bean post-processor, which holds a reference to beans that need to be cleaned up. In some respects, the Spring container’s role in regard to a prototype-scoped bean is a replacement for the Java new operator. All lifecycle management past that point must be handled by the client. (For details on the lifecycle of a bean in the Spring container, see Lifecycle Callbacks.) Singleton Beans with Prototype-bean Dependencies When you use singleton-scoped beans with dependencies on prototype beans, be aware that dependencies are resolved at instantiation time. Thus, if you dependency-inject a prototype-scoped bean into a singleton-scoped bean, a new prototype bean is instantiated and then dependency- injected into the singleton bean. The prototype instance is the sole instance that is ever supplied to the singleton-scoped bean. However, suppose you want the singleton-scoped bean to acquire a new instance of the prototype- scoped bean repeatedly at runtime. You cannot dependency-inject a prototype-scoped bean into your singleton bean, because that injection occurs only once, when the Spring container instantiates the singleton bean and resolves and injects its dependencies. If you need a new instance of a prototype bean at runtime more than once, see Method Injection. Request, Session, Application, and WebSocket Scopes The request, session, application, and websocket scopes are available only if you use a web-aware Spring ApplicationContext implementation (such as XmlWebApplicationContext). If you use these scopes with regular Spring IoC containers, such as the ClassPathXmlApplicationContext, an IllegalStateException that complains about an unknown bean scope is thrown. Initial Web Configuration To support the scoping of beans at the request, session, application, and websocket levels (web- scoped beans), some minor initial configuration is required before you define your beans. (This initial setup is not required for the standard scopes: singleton and prototype.) How you accomplish this initial setup depends on your particular Servlet environment. If you access scoped beans within Spring Web MVC, in effect, within a request that is processed by the Spring DispatcherServlet, no special setup is necessary. DispatcherServlet already exposes all relevant state. If you use a Servlet web container, with requests processed outside of Spring’s DispatcherServlet (for example, when using JSF or Struts), you need to register the org.springframework.web.context.request.RequestContextListener ServletRequestListener. This can be done programmatically by using the WebApplicationInitializer interface. Alternatively, add the following declaration to your web application’s web.xml file:   ...       org.springframework.web.context.request.RequestContextListener       ... Alternatively, if there are issues with your listener setup, consider using Spring’s RequestContextFilter. The filter mapping depends on the surrounding web application configuration, so you have to change it as appropriate. The following listing shows the filter part of a web application:   ...     requestContextFilter   org.springframework.web.filter.RequestContextFilter       requestContextFilter   /*     ... DispatcherServlet, RequestContextListener, and RequestContextFilter all do exactly the same thing, namely bind the HTTP request object to the Thread that is servicing that request. This makes beans that are request- and session-scoped available further down the call chain. Request scope Consider the following XML configuration for a bean definition: The Spring container creates a new instance of the LoginAction bean by using the loginAction bean definition for each and every HTTP request. That is, the loginAction bean is scoped at the HTTP request level. You can change the internal state of the instance that is created as much as you want, because other instances created from the same loginAction bean definition do not see these changes in state. They are particular to an individual request. When the request completes processing, the bean that is scoped to the request is discarded. When using annotation-driven components or Java configuration, the @RequestScope annotation can be used to assign a component to the request scope. The following example shows how to do so: Java @RequestScope @Component public class LoginAction {   // ... } Kotlin @RequestScope @Component class LoginAction {   // ... } Session Scope Consider the following XML configuration for a bean definition: The Spring container creates a new instance of the UserPreferences bean by using the userPreferences bean definition for the lifetime of a single HTTP Session. In other words, the userPreferences bean is effectively scoped at the HTTP Session level. As with request-scoped beans, you can change the internal state of the instance that is created as much as you want, knowing that other HTTP Session instances that are also using instances created from the same userPreferences bean definition do not see these changes in state, because they are particular to an individual HTTP Session. When the HTTP Session is eventually discarded, the bean that is scoped to that particular HTTP Session is also discarded. When using annotation-driven components or Java configuration, you can use the @SessionScope annotation to assign a component to the session scope. Java @SessionScope @Component public class UserPreferences {   // ... } Kotlin @SessionScope @Component class UserPreferences {   // ... } Application Scope Consider the following XML configuration for a bean definition: The Spring container creates a new instance of the AppPreferences bean by using the appPreferences bean definition once for the entire web application. That is, the appPreferences bean is scoped at the ServletContext level and stored as a regular ServletContext attribute. This is somewhat similar to a Spring singleton bean but differs in two important ways: It is a singleton per ServletContext, not per Spring ApplicationContext (for which there may be several in any given web application), and it is actually exposed and therefore visible as a ServletContext attribute. When using annotation-driven components or Java configuration, you can use the @ApplicationScope annotation to assign a component to the application scope. The following example shows how to do so: Java @ApplicationScope @Component public class AppPreferences {   // ... } Kotlin @ApplicationScope @Component class AppPreferences {   // ... } WebSocket Scope WebSocket scope is associated with the lifecycle of a WebSocket session and applies to STOMP over WebSocket applications, see WebSocket scope for more details. Scoped Beans as Dependencies The Spring IoC container manages not only the instantiation of your objects (beans), but also the wiring up of collaborators (or dependencies). If you want to inject (for example) an HTTP request- scoped bean into another bean of a longer-lived scope, you may choose to inject an AOP proxy in place of the scoped bean. That is, you need to inject a proxy object that exposes the same public interface as the scoped object but that can also retrieve the real target object from the relevant scope (such as an HTTP request) and delegate method calls onto the real object. You may also use between beans that are scoped as singleton, with the reference then going through an intermediate proxy that is serializable and therefore able to re-obtain the target singleton bean on deserialization. When declaring against a bean of scope prototype, every method call on the shared proxy leads to the creation of a new target instance to which the call is then being forwarded. Also, scoped proxies are not the only way to access beans from shorter scopes in a lifecycle-safe fashion. You may also declare your injection point (that is, the  constructor or setter argument or autowired field) as ObjectFactory, allowing for a getObject() call to retrieve the current instance on demand every time it is needed — without holding on to the instance or storing it separately. As an extended variant, you may declare ObjectProvider which delivers several additional access variants, including getIfAvailable and getIfUnique. The JSR-330 variant of this is called Provider and is used with a Provider declaration and a corresponding get() call for every retrieval attempt. See here for more details on JSR-330 overall. The configuration in the following example is only one line, but it is important to understand the “why” as well as the “how” behind it:         ①             ① The line that defines the proxy. To create such a proxy, you insert a child element into a scoped bean definition (see Choosing the Type of Proxy to Create and XML Schema-based configuration). Why do definitions of beans scoped at the request, session and custom-scope levels require the element? Consider the following singleton bean definition and contrast it with what you need to define for the aforementioned scopes (note that the following userPreferences bean definition as it stands is incomplete):   In the preceding example, the singleton bean (userManager) is injected with a reference to the HTTP Session-scoped bean (userPreferences). The salient point here is that the userManager bean is a singleton: it is instantiated exactly once per container, and its dependencies (in this case only one, the userPreferences bean) are also injected only once. This means that the userManager bean operates only on the exact same userPreferences object (that is, the one with which it was originally injected). This is not the behavior you want when injecting a shorter-lived scoped bean into a longer-lived scoped bean (for example, injecting an HTTP Session-scoped collaborating bean as a dependency into singleton bean). Rather, you need a single userManager object, and, for the lifetime of an HTTP Session, you need a userPreferences object that is specific to the HTTP Session. Thus, the container creates an object that exposes the exact same public interface as the UserPreferences class (ideally an object that is a UserPreferences instance), which can fetch the real UserPreferences object from the scoping mechanism (HTTP request, Session, and so forth). The container injects this proxy object into the userManager bean, which is unaware that this UserPreferences reference is a proxy. In this example, when a UserManager instance invokes a method on the dependency-injected UserPreferences object, it is actually invoking a method on the proxy. The proxy then fetches the real UserPreferences object from (in this case) the HTTP Session and delegates the method invocation onto the retrieved real UserPreferences object. Thus, you need the following (correct and complete) configuration when injecting request- and session-scoped beans into collaborating objects, as the following example shows:     Choosing the Type of Proxy to Create By default, when the Spring container creates a proxy for a bean that is marked up with the element, a CGLIB-based class proxy is created. CGLIB proxies intercept only public method calls! Do not call non-public methods  on such a proxy. They are not delegated to the actual scoped target object. Alternatively, you can configure the Spring container to create standard JDK interface-based proxies for such scoped beans, by specifying false for the value of the proxy-target-class attribute of the element. Using JDK interface-based proxies means that you do not need additional libraries in your application classpath to affect such proxying. However, it also means that the class of the scoped bean must implement at least one interface and that all collaborators into which the scoped bean is injected must reference the bean through one of its interfaces. The following example shows a proxy based on an interface:     For more detailed information about choosing class-based or interface-based proxying, see Proxying Mechanisms. Custom Scopes The bean scoping mechanism is extensible. You can define your own scopes or even redefine existing scopes, although the latter is considered bad practice and you cannot override the built-in singleton and prototype scopes. Creating a Custom Scope To integrate your custom scopes into the Spring container, you need to implement the org.springframework.beans.factory.config.Scope interface, which is described in this section. For an idea of how to implement your own scopes, see the Scope implementations that are supplied with the Spring Framework itself and the Scope javadoc, which explains the methods you need to implement in more detail. The Scope interface has four methods to get objects from the scope, remove them from the scope, and let them be destroyed. The session scope implementation, for example, returns the session-scoped bean (if it does not exist, the method returns a new instance of the bean, after having bound it to the session for future reference). The following method returns the object from the underlying scope: Java Object get(String name, ObjectFactory objectFactory) Kotlin fun get(name: String, objectFactory: ObjectFactory<*>): Any The session scope implementation, for example, removes the session-scoped bean from the underlying session. The object should be returned, but you can return null if the object with the specified name is not found. The following method removes the object from the underlying scope: Java Object remove(String name) Kotlin fun remove(name: String): Any The following method registers a callback that the scope should invoke when it is destroyed or when the specified object in the scope is destroyed: Java void registerDestructionCallback(String name, Runnable destructionCallback) Kotlin fun registerDestructionCallback(name: String, destructionCallback: Runnable) See the javadoc or a Spring scope implementation for more information on destruction callbacks. The following method obtains the conversation identifier for the underlying scope: Java String getConversationId() Kotlin fun getConversationId(): String This identifier is different for each scope. For a session scoped implementation, this identifier can be the session identifier. Using a Custom Scope After you write and test one or more custom Scope implementations, you need to make the Spring container aware of your new scopes. The following method is the central method to register a new Scope with the Spring container: Java void registerScope(String scopeName, Scope scope); Kotlin fun registerScope(scopeName: String, scope: Scope) This method is declared on the ConfigurableBeanFactory interface, which is available through the BeanFactory property on most of the concrete ApplicationContext implementations that ship with Spring. The first argument to the registerScope(..) method is the unique name associated with a scope. Examples of such names in the Spring container itself are singleton and prototype. The second argument to the registerScope(..) method is an actual instance of the custom Scope implementation that you wish to register and use. Suppose that you write your custom Scope implementation, and then register it as shown in the next example. The next example uses SimpleThreadScope, which is included with Spring but is not  registered by default. The instructions would be the same for your own custom Scope implementations. Java Scope threadScope = new SimpleThreadScope(); beanFactory.registerScope("thread", threadScope); Kotlin val threadScope = SimpleThreadScope() beanFactory.registerScope("thread", threadScope) You can then create bean definitions that adhere to the scoping rules of your custom Scope, as follows: With a custom Scope implementation, you are not limited to programmatic registration of the scope. You can also do the Scope registration declaratively, by using the CustomScopeConfigurer class, as the following example shows:                                 When you place within a declaration for a FactoryBean  implementation, it is the factory bean itself that is scoped, not the object returned from getObject(). 2.1.6. Customizing the Nature of a Bean The Spring Framework provides a number of interfaces you can use to customize the nature of a bean. This section groups them as follows: • Lifecycle Callbacks • ApplicationContextAware and BeanNameAware • Other Aware Interfaces Lifecycle Callbacks To interact with the container’s management of the bean lifecycle, you can implement the Spring InitializingBean and DisposableBean interfaces. The container calls afterPropertiesSet() for the former and destroy() for the latter to let the bean perform certain actions upon initialization and destruction of your beans. The JSR-250 @PostConstruct and @PreDestroy annotations are generally considered best practice for receiving lifecycle callbacks in a modern Spring application. Using these annotations means that your beans are not coupled to Spring-specific  interfaces. For details, see Using @PostConstruct and @PreDestroy. If you do not want to use the JSR-250 annotations but you still want to remove coupling, consider init-method and destroy-method bean definition metadata. Internally, the Spring Framework uses BeanPostProcessor implementations to process any callback interfaces it can find and call the appropriate methods. If you need custom features or other lifecycle behavior Spring does not by default offer, you can implement a BeanPostProcessor yourself. For more information, see Container Extension Points. In addition to the initialization and destruction callbacks, Spring-managed objects may also implement the Lifecycle interface so that those objects can participate in the startup and shutdown process, as driven by the container’s own lifecycle. The lifecycle callback interfaces are described in this section. Initialization Callbacks The org.springframework.beans.factory.InitializingBean interface lets a bean perform initialization work after the container has set all necessary properties on the bean. The InitializingBean interface specifies a single method: void afterPropertiesSet() throws Exception; We recommend that you do not use the InitializingBean interface, because it unnecessarily couples the code to Spring. Alternatively, we suggest using the @PostConstruct annotation or specifying a POJO initialization method. In the case of XML-based configuration metadata, you can use the init- method attribute to specify the name of the method that has a void no-argument signature. With Java configuration, you can use the initMethod attribute of @Bean. See Receiving Lifecycle Callbacks. Consider the following example: Java public class ExampleBean {   public void init() {   // do some initialization work   } } Kotlin class ExampleBean {   fun init() {   // do some initialization work   } } The preceding example has almost exactly the same effect as the following example (which consists of two listings): Java public class AnotherExampleBean implements InitializingBean {   @Override   public void afterPropertiesSet() {   // do some initialization work   } } Kotlin class AnotherExampleBean : InitializingBean {   override fun afterPropertiesSet() {   // do some initialization work   } } However, the first of the two preceding examples does not couple the code to Spring. Destruction Callbacks Implementing the org.springframework.beans.factory.DisposableBean interface lets a bean get a callback when the container that contains it is destroyed. The DisposableBean interface specifies a single method: void destroy() throws Exception; We recommend that you do not use the DisposableBean callback interface, because it unnecessarily couples the code to Spring. Alternatively, we suggest using the @PreDestroy annotation or specifying a generic method that is supported by bean definitions. With XML-based configuration metadata, you can use the destroy-method attribute on the . With Java configuration, you can use the destroyMethod attribute of @Bean. See Receiving Lifecycle Callbacks. Consider the following definition: Java public class ExampleBean {   public void cleanup() {   // do some destruction work (like releasing pooled connections)   } } Kotlin class ExampleBean {   fun cleanup() {   // do some destruction work (like releasing pooled connections)   } } The preceding definition has almost exactly the same effect as the following definition: Java public class AnotherExampleBean implements DisposableBean {   @Override   public void destroy() {   // do some destruction work (like releasing pooled connections)   } } Kotlin class AnotherExampleBean : DisposableBean {   override fun destroy() {   // do some destruction work (like releasing pooled connections)   } } However, the first of the two preceding definitions does not couple the code to Spring. You can assign the destroy-method attribute of a element a special (inferred) value, which instructs Spring to automatically detect a public close or shutdown method on the specific bean class. (Any class that implements java.lang.AutoCloseable or java.io.Closeable would therefore match.) You can  also set this special (inferred) value on the default-destroy-method attribute of a element to apply this behavior to an entire set of beans (see Default Initialization and Destroy Methods). Note that this is the default behavior with Java configuration. Default Initialization and Destroy Methods When you write initialization and destroy method callbacks that do not use the Spring-specific InitializingBean and DisposableBean callback interfaces, you typically write methods with names such as init(), initialize(), dispose(), and so on. Ideally, the names of such lifecycle callback methods are standardized across a project so that all developers use the same method names and ensure consistency. You can configure the Spring container to “look” for named initialization and destroy callback method names on every bean. This means that you, as an application developer, can write your application classes and use an initialization callback called init(), without having to configure an init-method="init" attribute with each bean definition. The Spring IoC container calls that method when the bean is created (and in accordance with the standard lifecycle callback contract described previously). This feature also enforces a consistent naming convention for initialization and destroy method callbacks. Suppose that your initialization callback methods are named init() and your destroy callback methods are named destroy(). Your class then resembles the class in the following example: Java public class DefaultBlogService implements BlogService {   private BlogDao blogDao;   public void setBlogDao(BlogDao blogDao) {   this.blogDao = blogDao;   }   // this is (unsurprisingly) the initialization callback method   public void init() {   if (this.blogDao == null) {   throw new IllegalStateException("The [blogDao] property must be set.");   }   } } Kotlin class DefaultBlogService : BlogService {   private var blogDao: BlogDao? = null   // this is (unsurprisingly) the initialization callback method   fun init() {   if (blogDao == null) {   throw IllegalStateException("The [blogDao] property must be set.")   }   } } You could then use that class in a bean resembling the following:       The presence of the default-init-method attribute on the top-level element attribute causes the Spring IoC container to recognize a method called init on the bean class as the initialization method callback. When a bean is created and assembled, if the bean class has such a method, it is invoked at the appropriate time. You can configure destroy method callbacks similarly (in XML, that is) by using the default- destroy-method attribute on the top-level element. Where existing bean classes already have callback methods that are named at variance with the convention, you can override the default by specifying (in XML, that is) the method name by using the init-method and destroy-method attributes of the itself. The Spring container guarantees that a configured initialization callback is called immediately after a bean is supplied with all dependencies. Thus, the initialization callback is called on the raw bean reference, which means that AOP interceptors and so forth are not yet applied to the bean. A target bean is fully created first and then an AOP proxy (for example) with its interceptor chain is applied. If the target bean and the proxy are defined separately, your code can even interact with the raw target bean, bypassing the proxy. Hence, it would be inconsistent to apply the interceptors to the init method, because doing so would couple the lifecycle of the target bean to its proxy or interceptors and leave strange semantics when your code interacts directly with the raw target bean. --- ### Spring Ai Commons/Src/Test/Resources/Bikes.Json (spring-ai-commons/src/test/resources/bikes.json) [ { "name": "E-Adrenaline 8.0 EX1", "shortDescription": "a versatile and comfortable e-MTB designed for adrenaline enthusiasts who want to explore all types of terrain. It features a powerful motor and advanced suspension to provide a smooth and responsive ride, with a variety of customizable settings to fit any rider's needs.", "description": "## Overview\r\nIt's right for you if...\r\nYou want to push your limits on challenging trails and terrain, with the added benefit of an electric assist to help you conquer steep climbs and rough terrain. You also want a bike with a comfortable and customizable fit, loaded with high-quality components and technology.\r\n\r\nThe tech you get\r\nA lightweight, full ADV Mountain Carbon frame with a customizable geometry, including an adjustable head tube and chainstay length. A powerful and efficient motor with a 375Wh battery that can assist up to 28 mph when it's on, and provides a smooth and seamless transition when it's off. A SRAM EX1 8-speed drivetrain, a RockShox Lyrik Ultimate fork, and a RockShox Super Deluxe Ultimate rear shock.\r\n\r\nThe final word\r\nOur E-Adrenaline 8.0 EX1 is the perfect bike for adrenaline enthusiasts who want to explore all types of terrain. It's versatile, comfortable, and loaded with advanced technology to provide a smooth and responsive ride, no matter where your adventures take you.\r\n\r\n\r\n## Features\r\nVersatile and customizable\r\nThe E-Adrenaline 8.0 EX1 features a customizable geometry, including an adjustable head tube and chainstay length, so you can fine-tune your ride to fit your needs and preferences. It also features a variety of customizable settings, including suspension tuning, motor assistance levels, and more.\r\n\r\nPowerful and efficient\r\nThe bike is equipped with a powerful and efficient motor that provides a smooth and seamless transition between human power and electric assist. It can assist up to 28 mph when it's on, and provides zero drag when it's off.\r\n\r\nAdvanced suspension\r\nThe E-Adrenaline 8.0 EX1 features a RockShox Lyrik Ultimate fork and a RockShox Super Deluxe Ultimate rear shock, providing advanced suspension technology to absorb shocks and bumps on any terrain. The suspension is also customizable to fit your riding style and preferences.\r\n\r\n\r\n## Specs\r\nFrameset\r\nFrame ADV Mountain Carbon main frame & stays, adjustable head tube and chainstay length, tapered head tube, Knock Block, Control Freak internal routing, Boost148, 150mm travel\r\nFork RockShox Lyrik Ultimate, DebonAir spring, Charger 2.1 RC2 damper, remote lockout, tapered steerer, 42mm offset, Boost110, 15mm Maxle Stealth, 160mm travel\r\nShock RockShox Super Deluxe Ultimate, DebonAir spring, Thru Shaft 3-position damper, 230x57.5mm\r\n\r\nWheels\r\nWheel front Bontrager Line Elite 30, ADV Mountain Carbon, Tubeless Ready, 6-bolt, Boost110, 15mm thru axle\r\nWheel rear Bontrager Line Elite 30, ADV Mountain Carbon, Tubeless Ready, 54T Rapid Drive, 6-bolt, Shimano MicroSpline freehub, Boost148, 12mm thru axle\r\nSkewer rear Bontrager Switch thru axle, removable lever\r\nTire Bontrager XR5 Team Issue, Tubeless Ready, Inner Strength sidewall, aramid bead, 120tpi, 29x2.50''\r\nTire part Bontrager TLR sealant, 6oz\r\n\r\nDrivetrain\r\nShifter SRAM EX1, 8 speed\r\nRear derailleur SRAM EX1, 8 speed\r\nCrank Bosch Performance CX, magnesium motor body, 250 watt, 75 Nm torque\r\nChainring SRAM EX1, 18T, steel\r\nCassette SRAM EX1, 11-48, 8 speed\r\nChain SRAM EX1, 8 speed\r\n\r\nComponents\r\nSaddle Bontrager Arvada, hollow chromoly rails, 138mm width\r\nSeatpost Bontrager Line Elite Dropper, internal routing, 31.6mm\r\nHandlebar Bontrager Line Pro, ADV Carbon, 35mm, 27.5mm rise, 780mm width\r\nGrips Bontrager XR Trail Elite, alloy lock-on\r\nStem Bontrager Line Pro, 35mm, Knock Block, Blendr compatible, 0 degree, 50mm length\r\nHeadset Knock Block Integrated, 62-degree radius, cartridge bearing, 1-1\/8'' top, 1.5'' bottom\r\nBrake SRAM G2 RSC hydraulic disc, carbon levers\r\nBrake rotor SRAM Centerline, centerlock, round edge, 200mm\r\n\r\nAccessories\r\nE-bike system Bosch Performance CX, magnesium motor body, 250 watt, 75 Nm torque\r\nBattery Bosch PowerTube 625, 625Wh\r\nCharger Bosch 4A standard charger\r\nController Bosch Kiox with Anti-theft solution, Bluetooth connectivity, 1.9'' display\r\nTool Bontrager Switch thru axle, removable lever\r\n\r\nWeight\r\nWeight M - 20.25 kg \/ 44.6 lbs (with TLR sealant, no tubes)\r\nWeight limit This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\r\n\r\n## Sizing & fit\r\n\r\n| Size | Rider Height | Inseam |\r\n|:----:|:------------------------:|:--------------------:|\r\n| S | 155 - 170 cm 5'1\" - 5'7\" | 73 - 80 cm 29\" - 31.5\" |\r\n| M | 163 - 178 cm 5'4\" - 5'10\" | 77 - 83 cm 30.5\" - 32.5\" |\r\n| L | 176 - 191 cm 5'9\" - 6'3\" | 83 - 89 cm 32.5\" - 35\" |\r\n| XL | 188 - 198 cm 6'2\" - 6'6\" | 88 - 93 cm 34.5\" - 36.5\" |\r\n\r\n\r\n## Geometry\r\n\r\nAll measurements provided in cm unless otherwise noted.\r\nSizing table\r\n| Frame size letter | S | M | L | XL |\r\n|---------------------------|-------|-------|-------|-------|\r\n| Actual frame size | 15.8 | 17.8 | 19.8 | 21.8 |\r\n| Wheel size | 29\" | 29\" | 29\" | 29\" |\r\n| A \u2014 Seat tube | 40.0 | 42.5 | 47.5 | 51.0 |\r\n| B \u2014 Seat tube angle | 72.5\u00B0 | 72.8\u00B0 | 73.0\u00B0 | 73.0\u00B0 |\r\n| C \u2014 Head tube length | 9.5 | 10.5 | 11.0 | 11.5 |\r\n| D \u2014 Head angle | 67.8\u00B0 | 67.8\u00B0 | 67.8\u00B0 | 67.8\u00B0 |\r\n| E \u2014 Effective top tube | 59.0 | 62.0 | 65.0 | 68.0 |\r\n| F \u2014 Bottom bracket height | 32.5 | 32.5 | 32.5 | 32.5 |\r\n| G \u2014 Bottom bracket drop | 5.5 | 5.5 | 5.5 | 5.5 |\r\n| H \u2014 Chainstay length | 45.0 | 45.0 | 45.0 | 45.0 |\r\n| I \u2014 Offset | 4.5 | 4.5 | 4.5 | 4.5 |\r\n| J \u2014 Trail | 11.0 | 11.0 | 11.0 | 11.0 |\r\n| K \u2014 Wheelbase | 113.0 | 117.0 | 120.0 | 123.0 |\r\n| L \u2014 Standover | 77.0 | 77.0 | 77.0 | 77.0 |\r\n| M \u2014 Frame reach | 41.0 | 44.5 | 47.5 | 50.0 |\r\n| N \u2014 Frame stack | 61.0 | 62.0 | 62.5 | 63.0 |", "price": 1499.99, "tags": [ "bicycle" ] }, { "name": "Enduro X Pro", "shortDescription": "The Enduro X Pro is the ultimate mountain bike for riders who demand the best. With its full carbon frame and top-of-the-line components, this bike is ready to tackle any trail, from technical downhill descents to grueling uphill climbs.", "text": "## Overview\nIt's right for you if...\nYou're an experienced mountain biker who wants a high-performance bike that can handle any terrain. You want a bike with the best components available, including a full carbon frame, suspension system, and hydraulic disc brakes.\n\nThe tech you get\nOur top-of-the-line full carbon frame with aggressive geometry and a slack head angle for maximum control. It's equipped with a Fox Factory suspension system with 170mm of travel in the front and 160mm in the rear, a Shimano XTR 12-speed drivetrain, and hydraulic disc brakes for maximum stopping power. The bike also features a dropper seatpost for easy adjustments on the fly.\n\nThe final word\nThe Enduro X Pro is the ultimate mountain bike for riders who demand the best. With its full carbon frame, top-of-the-line components, and aggressive geometry, this bike is ready to take on any trail. Whether you're a seasoned pro or just starting out, the Enduro X Pro will help you take your riding to the next level.\n\n## Features\nFull carbon frame\nAggressive geometry with a slack head angle\nFox Factory suspension system with 170mm of travel in the front and 160mm in the rear\nShimano XTR 12-speed drivetrain\nHydraulic disc brakes for maximum stopping power\nDropper seatpost for easy adjustments on the fly\n\n## Specifications\nFrameset\nFrame\tFull carbon frame\nFork\tFox Factory suspension system with 170mm of travel\nRear suspension\tFox Factory suspension system with 160mm of travel\n\nWheels\nWheel size\t27.5\" or 29\"\nTires\tTubeless-ready Maxxis tires\n\nDrivetrain\nShifters\tShimano XTR 12-speed\nFront derailleur\tN/A\nRear derailleur\tShimano XTR\nCrankset\tShimano XTR\nCassette\tShimano XTR 12-speed\nChain\tShimano XTR\n\nComponents\nBrakes\tHydraulic disc brakes\nHandlebar\tAlloy handlebar\nStem\tAlloy stem\nSeatpost\tDropper seatpost\n\nAccessories\nPedals\tNot included\n\nWeight\nWeight\tApproximately 27-29 lbs\n\n## Sizing\n| Size | Rider Height |\n|:----:|:-------------------------:|\n| S | 5'4\" - 5'8\" (162-172cm) |\n| M | 5'8\" - 5'11\" (172-180cm) |\n| L | 5'11\" - 6'3\" (180-191cm) |\n| XL | 6'3\" - 6'6\" (191-198cm) |\n\n## Geometry\n| Size | S | M | L | XL |\n|:----:|:---------------:|:---------------:|:-----------------:|:---------------:|\n| A - Seat tube length | 390mm | 425mm | 460mm | 495mm |\n| B - Effective top tube length | 585mm | 610mm | 635mm | 660mm |\n| C - Head tube angle | 65.5° | 65.5° | 65.5° | 65.5° |\n| D - Seat tube angle | 76° | 76° | 76° | 76° |\n| E - Chainstay length | 435mm | 435mm | 435mm | 435mm |\n| F - Head tube length | 100mm | 110mm | 120mm | 130mm |\n| G - BB drop | 20mm | 20mm | 20mm | 20mm |\n| H - Wheelbase | 1155mm | 1180mm | 1205mm | 1230mm |\n| I - Standover height | 780mm | 800mm | 820mm | 840mm |\n| J - Reach | 425mm | 450mm | 475mm | 500mm |\n| K - Stack | 610mm | 620mm | 630mm | 640mm |", "price": 599.99, "tags": [ "bicycle" ] }, { "name": "Blaze X1", "shortDescription": "Blaze X1 is a high-performance road bike that offers superior speed and agility, making it perfect for competitive racing or fast-paced group rides. The bike features a lightweight carbon frame, aerodynamic tube shapes, a 12-speed Shimano Ultegra drivetrain, and hydraulic disc brakes for precise stopping power. With its sleek design and cutting-edge technology, Blaze X1 is a bike that is built to perform and dominate on any road.", "description": "## Overview\nIt's right for you if...\nYou're a competitive road cyclist or an enthusiast who enjoys fast-paced group rides. You want a bike that is lightweight, agile, and delivers exceptional speed.\n\nThe tech you get\nBlaze X1 features a lightweight carbon frame with a tapered head tube and aerodynamic tube shapes for maximum speed and efficiency. The bike is equipped with a 12-speed Shimano Ultegra drivetrain for smooth and precise shifting, Shimano hydraulic disc brakes for powerful and reliable stopping power, and Bontrager Aeolus Elite 35 carbon wheels for increased speed and agility.\n\nThe final word\nBlaze X1 is a high-performance road bike that is designed to deliver exceptional speed and agility. With its cutting-edge technology and top-of-the-line components, it's a bike that is built to perform and dominate on any road.\n\n## Features\nSpeed and efficiency\nBlaze X1's lightweight carbon frame and aerodynamic tube shapes offer maximum speed and efficiency, allowing you to ride faster and farther with ease.\n\nPrecision stopping power\nShimano hydraulic disc brakes provide precise and reliable stopping power, even in wet or muddy conditions.\n\nAgility and control\nBontrager Aeolus Elite 35 carbon wheels make Blaze X1 incredibly agile and responsive, allowing you to navigate tight turns and corners with ease.\n\nSmooth and precise shifting\nThe 12-speed Shimano Ultegra drivetrain offers smooth and precise shifting, so you can easily find the right gear for any terrain.\n\n## Specifications\nFrameset\nFrame\tADV Carbon, tapered head tube, BB90, direct mount rim brakes, internal cable routing, DuoTrap S compatible, 130x9mm QR\nFork\tADV Carbon, tapered steerer, direct mount rim brakes, internal brake routing, 100x9mm QR\n\nWheels\nWheel front\tBontrager Aeolus Elite 35, ADV Carbon, Tubeless Ready, 35mm rim depth, 100x9mm QR\nWheel rear\tBontrager Aeolus Elite 35, ADV Carbon, Tubeless Ready, 35mm rim depth, Shimano 11-speed freehub, 130x9mm QR\nTire front\tBontrager R3 Hard-Case Lite, aramid bead, 120 tpi, 700x25c\nTire rear\tBontrager R3 Hard-Case Lite, aramid bead, 120 tpi, 700x25c\nMax tire size\t25c Bontrager tires (with at least 4mm of clearance to frame)\n\nDrivetrain\nShifter\tShimano Ultegra R8020, 12 speed\nFront derailleur\tShimano Ultegra R8000, braze-on\nRear derailleur\tShimano Ultegra R8000, short cage, 30T max cog\nCrank\tSize: 50, 52, 54\nShimano Ultegra R8000, 50/34 (compact), 170mm length\nSize: 56, 58, 60, 62\nShimano Ultegra R8000, 50/34 (compact), 172.5mm length\nBottom bracket\tBB90, Shimano press-fit\nCassette\tShimano Ultegra R8000, 11-30, 12 speed\nChain\tShimano Ultegra HG701, 12 speed\n\nComponents\nSaddle\tBontrager Montrose Elite, titanium rails, 138mm width\nSeatpost\tBontrager carbon seatmast cap, 20mm offset\nHandlebar\tBontrager Elite Aero VR-CF, alloy, 31.8mm, internal cable routing, 40cm width\nGrips\tBontrager Supertack Perf tape\nStem\tBontrager Elite, 31.8mm, Blendr-compatible, 7 degree, 80mm length\nBrake Shimano Ultegra hydraulic disc brake\n\nWeight\nWeight\t56 - 8.91 kg / 19.63 lbs (with tubes)\nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 275 pounds (125 kg).\n\n## Sizing\n| Size | Rider height |\n|------|-------------|\n| 50 | 162-166cm |\n| 52 | 165-170cm |\n| 54 | 168-174cm |\n| 56 | 174-180cm |\n| 58 | 179-184cm |\n| 60 | 184-189cm |\n| 62 | 189-196cm |\n\n## Geometry\n| Frame size | 50cm | 52cm | 54cm | 56cm | 58cm | 60cm | 62cm |\n|------------|-------|-------|-------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c | 700c | 700c | 700c |\n| A - Seat tube | 443mm | 460mm | 478mm | 500mm | 520mm | 540mm | 560mm |\n| B - Seat tube angle | 74.1° | 73.9° | 73.7° | 73.4° | 73.2° | 73.0° | 72.8° |\n| C - Head tube length | 100mm | 110mm | 130mm | 150mm | 170mm | 190mm | 210mm |\n| D - Head angle | 71.4° | 72.0° | 72.5° | 73.0° | 73.3° | 73.6° | 73.8° |\n| E - Effective top tube | 522mm | 535mm | 547mm | 562mm | 577mm | 593mm | 610mm |\n| F - Bottom bracket height | 268mm | 268mm | 268mm | 268mm | 268mm | 268mm | 268mm |\n| G - Bottom bracket drop | 69mm | 69mm | 69mm | 69mm | 69mm | 69mm | 69mm |\n| H - Chainstay length | 410mm | 410mm | 410mm | 410mm | 410mm | 410mm | 410mm |\n| I - Offset | 50mm | 50mm | 50mm | 50mm | 50mm | 50mm | 50mm |\n| J - Trail | 65mm | 62mm | 59mm | 56mm | 55mm | 53mm | 52mm |\n| K - Wheelbase | 983mm | 983mm | 990mm | 1005mm | 1019mm | 1036mm | 1055mm |\n| L - Standover | 741mm | 765mm | 787mm | 806mm | 825mm | 847mm | 869mm |", "price": 799.99, "tags": [ "bicycle", "mountain bike" ] }, { "name": "Celerity X5", "shortDescription": "Celerity X5 is a versatile and reliable road bike that is designed for experienced and amateur riders alike. It's designed to provide smooth and comfortable rides over long distances. With an ultra-lightweight and responsive carbon fiber frame, Shimano 105 groupset, hydraulic disc brakes, and 28mm wide tires, this bike ensures efficient power transfer, precise handling, and superior stopping power.", "description": "## Overview\n\nIt's right for you if... \nYou are looking for a high-performance road bike that offers a perfect balance of speed, comfort, and control. You enjoy long-distance rides and need a bike that is designed to handle various road conditions with ease. You also appreciate the latest technology and reliable components that make your riding experience more enjoyable.\n\nThe tech you get \nCelerity X5 is equipped with a full carbon fiber frame that ensures maximum strength and durability while keeping the weight down. It features a Shimano 105 groupset with 11-speed gearing for precise and efficient shifting. Hydraulic disc brakes offer superior stopping power, and 28mm wide tires provide comfort and stability on various road surfaces. Internal cable routing enhances the bike's sleek appearance.\n\nThe final word \nIf you are looking for a high-performance road bike that offers comfort, speed, and control, Celerity X5 is the perfect choice. With its lightweight carbon fiber frame, reliable components, and advanced technology, this bike is designed to help you enjoy long-distance rides with ease.\n\n## Features \n\nLightweight and responsive \nCelerity X5 comes with a full carbon fiber frame that is not only lightweight but also responsive, providing excellent handling and control.\n\nHydraulic disc brakes \nThis bike is equipped with hydraulic disc brakes that provide superior stopping power in all weather conditions, ensuring your safety and confidence on the road.\n\nComfortable rides \nThe 28mm wide tires and carbon seat post provide ample cushioning, ensuring a smooth and comfortable ride over long distances.\n\nSleek appearance \nThe bike's internal cable routing enhances its sleek appearance while also protecting the cables from the elements, ensuring smooth shifting for longer periods.\n\n## Specifications \n\nFrameset \nFrame\tCelerity X5 Full Carbon Fiber Frame, Internal Cable Routing, Tapered Headtube, Press Fit Bottom Bracket, 12x142mm Thru-Axle \nFork\tCelerity X5 Full Carbon Fiber Fork, Internal Brake Routing, 12x100mm Thru-Axle \n\nWheels \nWheelset\tAlexRims CXD7 Wheelset \nTire\tSchwalbe Durano Plus 700x28mm \nInner Tubes\tSchwalbe SV15 700x18-28mm \nSkewers\tCelerity X5 Thru-Axle Skewers \n\nDrivetrain \nShifter\tShimano 105 R7025 Hydraulic Disc Shifters \nFront Derailleur\tShimano 105 R7000 \nRear Derailleur\tShimano 105 R7000 \nCrankset\tShimano 105 R7000 50-34T \nBottom Bracket\tShimano BB72-41B \nCassette\tShimano 105 R7000 11-30T \nChain\tShimano HG601 11-Speed Chain \n\nComponents \nSaddle\tSelle Royal Asphalt Saddle \nSeatpost\tCelerity X5 Carbon Seatpost \nHandlebar\tCelerity X5 Compact Handlebar \nStem\tCelerity X5 Aluminum Stem \nHeadset\tFSA Orbit IS-2 \n\nBrakes \nBrakes\tShimano 105 R7025 Hydraulic Disc Brakes \nRotors\tShimano SM-RT70 160mm Rotors \n\nAccessories \nPedals\tCelerity X5 Road Pedals \n\nWeight \nWeight\t8.2 kg / 18.1 lbs \nWeight Limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 120 kg (265 lbs).\n\n## Sizing \n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| 49 | 155 - 162 cm 5'1\" - 5'4\" | 71 - 76 cm 28\" - 30\" |\n| 52 | 162 - 170 cm 5'4\" - 5'7\" | 74 - 79 cm 29\" - 31\" |\n| 54 | 170 - 178 cm 5'7\" - 5'10\" | 77 - 83 cm 30\" - 32\" |\n| 56 | 178 - 185 cm 5'10\" - 6'1\" | 82 - 88 cm 32\" - 34\" |\n| 58 | 185 - 193 cm 6'1\" - 6'4\" | 86 - 92 cm 34\" - 36\" |\n| 61 | 193 - 200 cm 6'4\" - 6'7\" | 90 - 95 cm 35\" - 37\" |\n\n## Geometry \n| Frame size number | 49 cm | 52 cm | 54 cm | 56 cm | 58 cm | 61 cm |\n|---------------------------------------|-------|-------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c | 700c | 700c |\n| A — Seat tube | 47.5 | 50.0 | 52.0 | 54.0 | 56.0 | 58.5 |\n| B — Seat tube angle | 75.0° | 74.5° | 74.0° | 73.5° | 73.0° | 72.5° |\n| C — Head tube length | 12.0 | 14.5 | 16.5 | 18.5 | 20.5 | 23.5 |\n| D — Head angle | 70.0° | 71.0° | 71.5° | 72.0° | 72.5° | 72.5° |\n| E — Effective top tube | 52.5 | 53.5 | 54.5 | 56.0 | 57.5 | 59.5 |\n| G — Bottom bracket drop | 7.0 | 7.0 | 7.0 | 7.0 | 7.0 | 7.0 |\n| H — Chainstay length | 41.5 | 41.5 | 41.5 | 41.5 | 41.5 | 41.5 |\n| K — Wheelbase | 98.4 | 98.9 | 99.8 | 100.8 | 101.7 | 103.6 |\n| L — Standover | 72.0 | 74.0 | 76.0 | 78.0 | 80.0 | 82.0 |\n| M — Frame reach | 36.2 | 36.8 | 37.3 | 38.1 | 38.6 | 39.4 |\n| N — Frame stack | 52.0 | 54.3 | 56.2 | 58.1 | 59.8 | 62.4 |\n| Saddle rail height min | 67.0 | 69.5 | 71.5 | 74.0 | 76.0 | 78.0 |\n| Saddle rail height max | 75.0 | 77.5 | 79.5 | 82.0 | 84.0 | 86.0 |", "price": 399.99, "tags": [ "bicycle", "city bike" ] }, { "name": "Velocity V8", "shortDescription": "Velocity V8 is a high-performance road bike that is designed to deliver speed, agility, and control on the road. With its lightweight aluminum frame, carbon fiber fork, Shimano Tiagra groupset, and hydraulic disc brakes, this bike is perfect for experienced riders who are looking for a fast and responsive bike that can handle various road conditions.", "description": "## Overview\n\nIt's right for you if... \nYou are an experienced rider who is looking for a high-performance road bike that is lightweight, agile, and responsive. You want a bike that can handle long-distance rides, steep climbs, and fast descents with ease. You also appreciate the latest technology and reliable components that make your riding experience more enjoyable.\n\nThe tech you get \nVelocity V8 features a lightweight aluminum frame with a carbon fiber fork that ensures a comfortable ride without sacrificing stiffness and power transfer. It comes with a Shimano Tiagra groupset with 10-speed gearing for precise and efficient shifting. Hydraulic disc brakes offer superior stopping power in all weather conditions, while 28mm wide tires provide comfort and stability on various road surfaces. Internal cable routing enhances the bike's sleek appearance.\n\nThe final word \nIf you are looking for a high-performance road bike that is lightweight, fast, and responsive, Velocity V8 is the perfect choice. With its lightweight aluminum frame, reliable components, and advanced technology, this bike is designed to help you enjoy fast and comfortable rides on the road.\n\n## Features \n\nLightweight and responsive \nVelocity V8 comes with a lightweight aluminum frame that is not only lightweight but also responsive, providing excellent handling and control.\n\nHydraulic disc brakes \nThis bike is equipped with hydraulic disc brakes that provide superior stopping power in all weather conditions, ensuring your safety and confidence on the road.\n\nComfortable rides \nThe 28mm wide tires and carbon fork provide ample cushioning, ensuring a smooth and comfortable ride over long distances.\n\nSleek appearance \nThe bike's internal cable routing enhances its sleek appearance while also protecting the cables from the elements, ensuring smooth shifting for longer periods.\n\n## Specifications \n\nFrameset \nFrame\tVelocity V8 Aluminum Frame, Internal Cable Routing, Tapered Headtube, Press Fit Bottom Bracket, 12x142mm Thru-Axle \nFork\tVelocity V8 Carbon Fiber Fork, Internal Brake Routing, 12x100mm Thru-Axle \n\nWheels \nWheelset\tAlexRims CXD7 Wheelset \nTire\tSchwalbe Durano Plus 700x28mm \nInner Tubes\tSchwalbe SV15 700x18-28mm \nSkewers\tVelocity V8 Thru-Axle Skewers \n\nDrivetrain \nShifter\tShimano Tiagra Hydraulic Disc Shifters \nFront Derailleur\tShimano Tiagra \nRear Derailleur\tShimano Tiagra \nCrankset\tShimano Tiagra 50-34T \nBottom Bracket\tShimano BB-RS500-PB \nCassette\tShimano Tiagra 11-32T \nChain\tShimano HG54 10-Speed Chain \n\nComponents \nSaddle\tVelocity V8 Saddle \nSeatpost\tVelocity V8 Aluminum Seatpost \nHandlebar\tVelocity V8 Compact Handlebar \nStem\tVelocity V8 Aluminum Stem \nHeadset\tFSA Orbit IS-2 \n\nBrakes \nBrakes\tShimano Tiagra Hydraulic Disc Brakes \nRotors\tShimano SM-RT64 160mm Rotors \n\nAccessories \nPedals\tVelocity V8 Road Pedals \n\nWeight \nWeight\t9.4 kg / 20.7 lbs \nWeight Limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 120 kg (265 lbs).\n\n## Sizing \n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| 49 | 155 - 162 cm 5'1\" - 5'4\" | 71 - 76 cm 28\" - 30\" |\n| 52 | 162 - 170 cm 5'4\" - 5'7\" | 74 - 79 cm 29\" - 31\" |\n| 54 | 170 - 178 cm 5'7\" - 5'10\" | 77 - 83 cm 30\" - 32\" |\n| 56 | 178 - 185 cm 5'10\" - 6'1\" | 82 - 88 cm 32\" - 34\" |\n| 58 | 185 - 193 cm 6'1\" - 6'4\" | 86 - 92 cm 34\" - 36\" |\n| 61 | 193 - 200 cm 6'4\" - 6'7\" | 90 - 95 cm 35\" - 37\" |\n\n## Geometry \n| Frame size number | 49 cm | 52 cm | 54 cm | 56 cm | 58 cm | 61 cm |\n|---------------------------------------|-------|-------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c | 700c | 700c |\n| A — Seat tube | 47.5 | 50.0 | 52.0 | 54.0 | 56.0 | 58.5 |\n| B — Seat tube angle | 75.0° | 74.5° | 74.0° | 73.5° | 73.0° | 72.5° |\n| C — Head tube length | 12.0 | 14.5 | 16.5 | 18.5 | 20.5 | 23.5 |\n| D — Head angle | 70.0° | 71.0° | 71.5° | 72.0° | 72.5° | 72.5° |\n| E — Effective top tube | 52.5 | 53.5 | 54.5 | 56.0 | 57.5 | 59.5 |\n| G — Bottom bracket drop | 7.0 | 7.0 | 7.0 | 7.0 | 7.0 | 7.0 |\n| H — Chainstay length | 41.5 | 41.5 | 41.5 | 41.5 | 41.5 | 41.5 |\n| K — Wheelbase | 98.4 | 98.9 | 99.8 | 100.8 | 101.7 | 103.6 |\n| L — Standover | 72.0 | 74.0 | 76.0 | 78.0 | 80.0 | 82.0 |\n| M — Frame reach | 36.2 | 36.8 | 37.3 | 38.1 | 38.6 | 39.4 |\n| N — Frame stack | 52.0 | 54.3 | 56.2 | 58.1 | 59.8 | 62.4 |\n| Saddle rail height min | 67.0 | 69.5 | 71.5 | 74.0 | 76.0 | 78.0 |\n| Saddle rail height max | 75.0 | 77.5 | 79.5 | 82.0 | 84.0 | 86.0 |", "price": 1899.99, "tags": [ "bicycle", "electric bike" ] }, { "name": "VeloCore X9 eMTB", "shortDescription": "The VeloCore X9 eMTB is a light, agile and versatile electric mountain bike designed for adventure and performance. Its purpose-built frame and premium components offer an exhilarating ride experience on both technical terrain and smooth singletrack.", "description": "## Overview\nIt's right for you if...\nYou love exploring new trails and testing your limits on challenging terrain. You want an electric mountain bike that offers power when you need it, without sacrificing performance or agility. You're looking for a high-quality bike with top-notch components and a sleek design.\n\nThe tech you get\nA lightweight, full carbon frame with custom geometry, a 140mm RockShox Pike Ultimate fork with Charger 2.1 damper, and a Fox Float DPS Performance shock. A Shimano STEPS E8000 motor and 504Wh battery that provide up to 62 miles of range and 20 mph assistance. A Shimano XT 12-speed drivetrain, Shimano SLX brakes, and DT Swiss wheels.\n\nThe final word\nThe VeloCore X9 eMTB delivers power and agility in equal measure. It's a versatile and capable electric mountain bike that can handle any trail with ease. With premium components, a custom carbon frame, and a sleek design, this bike is built for adventure.\n\n## Features\nAgile and responsive\n\nThe VeloCore X9 eMTB is designed to be nimble and responsive on the trail. Its custom carbon frame offers a perfect balance of stiffness and compliance, while the suspension system provides smooth and stable performance on technical terrain.\n\nPowerful and efficient\n\nThe Shimano STEPS E8000 motor and 504Wh battery provide up to 62 miles of range and 20 mph assistance. The motor delivers smooth and powerful performance, while the battery offers reliable and consistent power for long rides.\n\nCustomizable ride experience\n\nThe VeloCore X9 eMTB comes with an intuitive and customizable Shimano STEPS display that allows you to adjust the level of assistance, monitor your speed and battery life, and customize your ride experience to suit your needs.\n\nPremium components\n\nThe VeloCore X9 eMTB is equipped with high-end components, including a Shimano XT 12-speed drivetrain, Shimano SLX brakes, and DT Swiss wheels. These components offer reliable and precise performance, allowing you to push your limits with confidence.\n\n## Specs\nFrameset\nFrame\tVeloCore carbon fiber frame, Boost, tapered head tube, internal cable routing, 140mm travel\nFork\tRockShox Pike Ultimate, Charger 2.1 damper, DebonAir spring, 15x110mm Boost Maxle Ultimate, 46mm offset, 140mm travel\nShock\tFox Float DPS Performance, EVOL, 3-position adjust, Kashima Coat, 210x50mm\n\nWheels\nWheel front\tDT Swiss XM1700 Spline, 30mm internal width, 15x110mm Boost axle\nWheel rear\tDT Swiss XM1700 Spline, 30mm internal width, Shimano Microspline driver, 12x148mm Boost axle\nTire front\tMaxxis Minion DHF, 29x2.5\", EXO+ casing, tubeless ready\nTire rear\tMaxxis Minion DHR II, 29x2.4\", EXO+ casing, tubeless ready\n\nDrivetrain\nShifter\tShimano XT M8100, 12-speed\nRear derailleur\tShimano XT M8100, Shadow Plus, long cage, 51T max cog\nCrankset\tShimano STEPS E8000, 165mm length, 34T chainring\nCassette\tShimano XT M8100, 10-51T, 12-speed\nChain\tShimano CN-M8100, 12-speed\nPedals\tNot included\n\nComponents\nSaddle\tBontrager Arvada, hollow chromoly rails\nSeatpost\tDrop Line, internal routing, 31.6mm (15.5: 100mm, 17.5 & 18.5: 125mm, 19.5 & 21.5: 150mm)\nHandlebar\tBontrager Line Pro, ADV Carbon, 35mm, 27.5mm rise, 780mm width\nStem\tBontrager Line Pro, 35mm, Knock Block, 0 degree, 50mm length\nGrips\tBontrager XR Trail Elite, alloy lock-on\nHeadset\tIntegrated, sealed cartridge bearing, 1-1/8\" top, 1.5\" bottom\nBrakeset\tShimano SLX M7120, 4-piston hydraulic disc\n\nAccessories\nBattery\tShimano STEPS BT-E8010, 504Wh\nCharger\tShimano STEPS EC-E8004, 4A\nController\tShimano STEPS E8000 display\nBike weight\tM - 22.5 kg / 49.6 lbs (with tubes)\n\n## Sizing & fit\n\n| Size | Rider Height |\n|:----:|:------------------------:|\n| S | 162 - 170 cm 5'4\" - 5'7\" |\n| M | 170 - 178 cm 5'7\" - 5'10\"|\n| L | 178 - 186 cm 5'10\" - 6'1\"|\n| XL | 186 - 196 cm 6'1\" - 6'5\" |\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\n\n| Frame size | S | M | L | XL |\n|---------------------------|-------|-------|-------|-------|\n| A — Seat tube | 40.6 | 43.2 | 47.0 | 51.0 |\n| B — Seat tube angle | 75.0° | 75.0° | 75.0° | 75.0° |\n| C — Head tube length | 9.6 | 10.6 | 11.6 | 12.6 |\n| D — Head angle | 66.5° | 66.5° | 66.5° | 66.5° |\n| E — Effective top tube | 60.4 | 62.6 | 64.8 | 66.9 |\n| F — Bottom bracket height | 33.2 | 33.2 | 33.2 | 33.2 |\n| G — Bottom bracket drop | 3.0 | 3.0 | 3.0 | 3.0 |\n| H — Chainstay length | 45.5 | 45.5 | 45.5 | 45.5 |\n| I — Offset | 4.6 | 4.6 | 4.6 | 4.6 |\n| J — Trail | 11.9 | 11.9 | 11.9 | 11.9 |\n| K — Wheelbase | 117.0 | 119.3 | 121.6 | 123.9 |\n| L — Standover | 75.9 | 75.9 | 78.6 | 78.6 |\n| M — Frame reach | 43.6 | 45.6 | 47.6 | 49.6 |\n| N — Frame stack | 60.5 | 61.5 | 62.4 | 63.4 |", "price": 1299.99, "tags": [ "bicycle", "touring bike" ] }, { "name": "Zephyr 8.8 GX Eagle AXS Gen 3", "shortDescription": "Zephyr 8.8 GX Eagle AXS is a light and nimble full-suspension mountain bike. It's designed to handle technical terrain with ease and has a smooth and efficient ride feel. The sleek and powerful Bosch Performance Line CX motor and removable Powertube battery provide a boost to your pedaling and give you long-lasting riding time. The bike also features high-end components and advanced technology for an ultimate mountain biking experience.", "description": "## Overview\nIt's right for you if...\nYou're an avid mountain biker looking for a high-performance e-MTB that can tackle challenging trails. You want a bike with a powerful motor, efficient suspension, and advanced technology to enhance your riding experience. You also need a bike that's reliable and durable for long-lasting use.\n\nThe tech you get\nA lightweight, full carbon frame with 150mm of rear travel and a 160mm RockShox Pike Ultimate fork with Charger 2.1 RCT3 damper, remote lockout, and DebonAir spring. A Bosch Performance Line CX motor and removable Powertube 625Wh battery that can assist up to 20mph when it's on and gives zero drag when it's off, plus an easy-to-use handlebar-mounted Bosch Purion controller. A SRAM GX Eagle AXS wireless electronic drivetrain, a RockShox Reverb Stealth dropper, and DT Swiss HX1501 Spline One wheels.\n\nThe final word\nZephyr 8.8 GX Eagle AXS is a high-performance e-MTB that's designed to handle technical terrain with ease. With a powerful Bosch motor and long-lasting battery, you can conquer challenging climbs and enjoy long rides. The bike also features high-end components and advanced technology for an ultimate mountain biking experience.\n\n## Features\nPowerful motor\n\nThe Bosch Performance Line CX motor provides a boost to your pedaling and can assist up to 20mph. It has four power modes and a walk-assist function for easy navigation on steep climbs. The motor is also reliable and durable for long-lasting use.\n\nEfficient suspension\n\nZephyr 8.8 has a 150mm of rear travel and a 160mm RockShox Pike Ultimate fork with Charger 2.1 RCT3 damper, remote lockout, and DebonAir spring. The suspension is efficient and responsive, allowing you to handle technical terrain with ease.\n\nRemovable battery\n\nThe Powertube 625Wh battery is removable for easy charging and storage. It provides long-lasting riding time and can be replaced with a spare battery for even longer rides. The battery is also durable and weather-resistant for all-season riding.\n\nAdvanced technology\n\nZephyr 8.8 is equipped with advanced technology, including a Bosch Purion controller for easy motor control, a SRAM GX Eagle AXS wireless electronic drivetrain for precise shifting, and a RockShox Reverb Stealth dropper for adjustable saddle height. The bike also has DT Swiss HX1501 Spline One wheels for reliable performance on any terrain.\n\nCarbon frame\n\nThe full carbon frame is lightweight and durable, providing a smooth and efficient ride. It's also designed with a tapered head tube, internal cable routing, and Boost148 spacing for enhanced stiffness and responsiveness.\n\n## Specs\nFrameset\nFrame\tCarbon main frame & stays, tapered head tube, internal routing, Boost148, 150mm travel\nFork\tRockShox Pike Ultimate, Charger 2.1 RCT3 damper, DebonAir spring, remote lockout, tapered steerer, Boost110, 15mm Maxle Stealth, 160mm travel\nShock\tRockShox Deluxe RT3, DebonAir spring, 205mm x 57.5mm\nMax compatible fork travel\t170mm\n\nWheels\nWheel front\tDT Swiss HX1501 Spline One, Centerlock, 30mm inner width, 110x15mm Boost\nWheel rear\tDT Swiss HX1501 Spline One, Centerlock, 30mm inner width, SRAM XD driver, 148x12mm Boost\nTire\tBontrager XR4 Team Issue, Tubeless Ready, Inner Strength sidewall, aramid bead, 120tpi, 29x2.40''\nMax tire size\t29x2.60\"\n\nDrivetrain\nShifter\tSRAM GX Eagle AXS, wireless, 12 speed\nRear derailleur\tSRAM GX Eagle AXS\nCrank\tBosch Gen 4, 32T\nChainring\tSRAM X-Sync 2, 32T, direct-mount\nCassette\tSRAM PG-1275 Eagle, 10-52, 12 speed\nChain\tSRAM GX Eagle, 12 speed\n\nComponents\nSaddle\tBontrager Arvada, hollow titanium rails, 138mm width\nSeatpost\tRockShox Reverb Stealth, 31.6mm, internal routing, 150mm (S), 170mm (M/L), 200mm (XL)\nHandlebar\tBontrager Line Pro, ADV Carbon, 35mm, 27.5mm rise, 780mm width\nGrips\tBontrager XR Trail Elite, alloy lock-on\nStem\tBontrager Line Pro, Knock Block, 35mm, 0 degree, 50mm length\nHeadset\tIntegrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom\nBrake\tSRAM Code RSC hydraulic disc, 200mm (front), 180mm (rear)\nBrake rotor\tSRAM CenterLine, centerlock, round edge, 200mm (front), 180mm (rear)\n\nAccessories\nE-bike system\tBosch Performance Line CX\nBattery\tBosch Powertube 625Wh\nCharger\tBosch 4A compact charger\nController\tBosch Purion\nTool\tBontrager multi-tool, integrated storage bag\n\nWeight\nWeight\tM - 24.08 kg / 53.07 lbs (with TLR sealant, no tubes)\nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n\n## Sizing & fit\n\n| Size | Rider Height | Inseam |\n|:----:|:------------------------:|:--------------------:|\n| S | 153 - 162 cm 5'0\" - 5'4\" | 67 - 74 cm 26\" - 29\" |\n| M | 161 - 172 cm 5'3\" - 5'8\" | 74 - 79 cm 29\" - 31\" |\n| L | 171 - 180 cm 5'7\" - 5'11\" | 79 - 84 cm 31\" - 33\" |\n| XL | 179 - 188 cm 5'10\" - 6'2\" | 84 - 89 cm 33\" - 35\" |\n\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\nSizing table\n| Frame size letter | S | M | L | XL |\n|---------------------------|-------|-------|-------|-------|\n| Actual frame size | 15.5 | 17.5 | 19.5 | 21.5 |\n| Wheel size | 29\" | 29\" | 29\" | 29\" |\n| A — Seat tube | 39.4 | 41.9 | 44.5 | 47.6 |\n| B — Seat tube angle | 76.1° | 76.1° | 76.1° | 76.1° |\n| C — Head tube length | 9.6 | 10.5 | 11.5 | 12.5 |\n| D — Head angle | 65.5° | 65.5° | 65.5° | 65.5° |\n| E — Effective top tube | 58.6 | 61.3 | 64.0 | 66.7 |\n| F — Bottom bracket height | 34.0 | 34.0 | 34.0 | 34.0 |\n| G — Bottom bracket drop | 1.0 | 1.0 | 1.0 | 1.0 |\n| H — Chainstay length | 45.0 | 45.0 | 45.0 | 45.0 |\n| I — Offset | 4.6 | 4.6 | 4.6 | 4.6 |\n| J — Trail | 10.5 | 10.5 | 10.5 | 10.5 |\n| K — Wheelbase | 119.5 | 122.3 | 125.0 | 127.8 |\n| L — Standover | 72.7 | 74.7 | 77.6 | 81.0 |\n|", "price": 1499.99, "tags": [ "bicycle", "electric bike", "city bike" ] }, { "name": "Velo 99 XR1 AXS", "shortDescription": "Velo 99 XR1 AXS is a next-generation bike designed for fast-paced adventure seekers and speed enthusiasts. Built for high-performance racing, the bike boasts state-of-the-art technology and premium components. It is the ultimate bike for riders who want to push their limits and get their adrenaline pumping.", "description": "## Overview\nIt's right for you if...\nYou are a passionate cyclist looking for a bike that can keep up with your speed, agility, and endurance. You are an adventurer who loves to explore new terrains and challenge yourself on the toughest courses. You want a bike that is lightweight, durable, and packed with the latest technology.\n\nThe tech you get\nA lightweight, full carbon frame with advanced aerodynamics and integrated cable routing for a clean look. A high-performance SRAM XX1 Eagle AXS wireless electronic drivetrain, featuring a 12-speed cassette and a 32T chainring. A RockShox SID Ultimate fork with a remote lockout, 120mm travel, and Charger Race Day damper. A high-end SRAM G2 Ultimate hydraulic disc brake with carbon levers. A FOX Transfer SL dropper post for quick and easy height adjustments. DT Swiss XRC 1501 carbon wheels for superior speed and handling.\n\nThe final word\nVelo 99 XR1 AXS is a premium racing bike that can help you achieve your goals and reach new heights. It is designed for speed, agility, and performance, and it is packed with the latest technology and premium components. If you are a serious cyclist who wants the best, this is the bike for you.\n\n## Features\nAerodynamic design\n\nThe Velo 99 XR1 AXS features a state-of-the-art frame design that reduces drag and improves speed. It has an aerodynamic seatpost, integrated cable routing, and a sleek, streamlined look that sets it apart from other bikes.\n\nWireless electronic drivetrain\n\nThe SRAM XX1 Eagle AXS drivetrain features a wireless electronic system that provides precise, instant shifting and unmatched efficiency. It eliminates the need for cables and makes the bike lighter and faster.\n\nHigh-performance suspension\n\nThe RockShox SID Ultimate fork and Charger Race Day damper provide 120mm of smooth, responsive suspension that can handle any terrain. The fork also has a remote lockout for quick adjustments on the fly.\n\nSuperior braking power\n\nThe SRAM G2 Ultimate hydraulic disc brake system delivers unmatched stopping power and control. It has carbon levers for a lightweight, ergonomic design and precision control.\n\nCarbon wheels\n\nThe DT Swiss XRC 1501 carbon wheels are ultra-lightweight, yet incredibly strong and durable. They provide superior speed and handling, making the bike more agile and responsive.\n\n## Specs\nFrameset\nFrame\tFull carbon frame, integrated cable routing, aerodynamic design, Boost148\nFork\tRockShox SID Ultimate, Charger Race Day damper, remote lockout, tapered steerer, Boost110, 15mm Maxle Stealth, 120mm travel\n\nWheels\nWheel front\tDT Swiss XRC 1501 carbon wheel, Boost110, 15mm thru axle\nWheel rear\tDT Swiss XRC 1501 carbon wheel, SRAM XD driver, Boost148, 12mm thru axle\nTire\tSchwalbe Racing Ray, Performance Line, Addix, 29x2.25\"\nTire part\tSchwalbe Doc Blue Professional, 500ml\nMax tire size\t29x2.3\"\n\nDrivetrain\nShifter\tSRAM Eagle AXS, wireless, 12-speed\nRear derailleur\tSRAM XX1 Eagle AXS\nCrank\tSRAM XX1 Eagle, 32T, carbon\nChainring\tSRAM X-SYNC, 32T, alloy\nCassette\tSRAM Eagle XG-1299, 10-52, 12-speed\nChain\tSRAM XX1 Eagle, 12-speed\nMax chainring size\t1x: 32T\n\nComponents\nSaddle\tBontrager Montrose Elite, carbon rails, 138mm width\nSeatpost\tFOX Transfer SL, 125mm travel, internal routing, 31.6mm\nHandlebar\tBontrager Kovee Pro, ADV Carbon, 35mm, 5mm rise, 720mm width\nGrips\tBontrager XR Endurance Elite\nStem\tBontrager Kovee Pro, 35mm, Blendr compatible, 7 degree, 60mm length\nHeadset\tIntegrated, cartridge bearing, 1-1/8\" top, 1.5\" bottom\nBrake\tSRAM G2 Ultimate hydraulic disc, carbon levers, 180mm rotors\n\nAccessories\nBike computer\tBontrager Trip 300\nTool\tBontrager Flatline Pro pedal wrench, T25 Torx\n\n\n## Sizing & fit\n\n| Size | Rider Height | Inseam |\n|:----:|:------------------------:|:--------------------:|\n| S | 158 - 168 cm 5'2\" - 5'6\" | 74 - 78 cm 29\" - 31\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" | 78 - 82 cm 31\" - 32\" |\n| L | 173 - 183 cm 5'8\" - 6'0\" | 82 - 86 cm 32\" - 34\" |\n| XL | 180 - 193 cm 5'11\" - 6'4\" | 86 - 90 cm 34\" - 35\" |\n\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\nSizing table\n| Frame size letter | S | M | L | XL |\n|---------------------------|-------|-------|-------|-------|\n| Actual frame size | 15.5 | 17.5 | 19.5 | 21.5 |\n| Wheel size | 29\" | 29\" | 29\" | 29\" |\n| A — Seat tube | 39.9 | 43.0 | 47.0 | 51.0 |\n| B — Seat tube angle | 74.5° | 74.5° | 74.5° | 74.5° |\n| C — Head tube length | 9.0 | 10.0 | 11.0 | 12.0 |\n| D — Head angle | 68.0° | 68.0° | 68.0° | 68.0° |\n| E — Effective top tube | 57.8 | 59.7 | 61.6 | 63.6 |\n| F — Bottom bracket height | 33.0 | 33.0 | 33.0 | 33.0 |\n| G — Bottom bracket drop | 5.0 | 5.0 | 5.0 | 5.0 |\n| H — Chainstay length | 43.0 | 43.0 | 43.0 | 43.0 |\n| I — Offset | 4.2 | 4.2 | 4.2 | 4.2 |\n| J — Trail | 9.7 | 9.7 | 9.7 | 9.7 |\n| K — Wheelbase | 112.5 | 114.5 | 116.5 | 118.6 |\n| L — Standover | 75.9 | 77.8 | 81.5 | 84.2 |\n| M — Frame reach | 41.6 | 43.4 | 45.2 | 47.1 |\n| N — Frame stack | 58.2 | 58.9 | 59.3 | 59.9 |", "price": 1099.99, "tags": [ "bicycle", "mountain bike" ] }, { "name": "AURORA 11S E-MTB", "shortDescription": "The AURORA 11S is a powerful and stylish electric mountain bike designed to take you on thrilling off-road adventures. With its sturdy frame and premium components, this bike is built to handle any terrain. It features a high-performance motor, long-lasting battery, and advanced suspension system that guarantee a smooth and comfortable ride.", "description": "## Overview\nIt's right for you if...\nYou want a top-of-the-line e-MTB that is both powerful and stylish. You also want a bike that can handle any terrain, from steep climbs to rocky descents. With its advanced features and premium components, the AURORA 11S is designed for serious off-road riders who demand the best.\n\nThe tech you get\nA sturdy aluminum frame with advanced suspension system that provides 120mm of travel. A 750W brushless motor that delivers up to 28mph, and a 48V/14Ah lithium-ion battery that provides up to 60 miles of range on a single charge. An advanced 11-speed Shimano drivetrain with hydraulic disc brakes for precise shifting and reliable stopping power. \n\nThe final word\nThe AURORA 11S is a top-of-the-line e-MTB that delivers exceptional performance and style. Whether you're tackling steep climbs or hitting rocky descents, this bike is built to handle any terrain with ease. With its advanced features and premium components, the AURORA 11S is the perfect choice for serious off-road riders who demand the best.\n\n## Features\nPowerful and efficient\n\nThe AURORA 11S is equipped with a high-performance 750W brushless motor that delivers up to 28mph. The motor is powered by a long-lasting 48V/14Ah lithium-ion battery that provides up to 60 miles of range on a single charge.\n\nAdvanced suspension system\n\nThe bike's advanced suspension system provides 120mm of travel, ensuring a smooth and comfortable ride on any terrain. The front suspension is a Suntour XCR32 Air fork, while the rear suspension is a KS-281 hydraulic shock absorber.\n\nPremium components\n\nThe AURORA 11S features an advanced 11-speed Shimano drivetrain with hydraulic disc brakes. The bike is also equipped with a Tektro HD-E725 hydraulic disc brake system that provides reliable stopping power.\n\nSleek and stylish design\n\nWith its sleek and stylish design, the AURORA 11S is sure to turn heads on the trail. The bike's sturdy aluminum frame is available in a range of colors, including black, blue, and red.\n\n## Specs\nFrameset\nFrame Material: Aluminum\nFrame Size: S, M, L\nFork: Suntour XCR32 Air, 120mm Travel\nShock Absorber: KS-281 Hydraulic Shock Absorber\n\nWheels\nWheel Size: 27.5 inches\nTires: Kenda K1151 Nevegal, 27.5x2.35\nRims: Alloy Double Wall\nSpokes: 32H, Stainless Steel\n\nDrivetrain\nShifters: Shimano SL-M7000\nRear Derailleur: Shimano RD-M8000\nCrankset: Prowheel 42T, Alloy Crank Arm\nCassette: Shimano CS-M7000, 11-42T\nChain: KMC X11EPT\n\nBrakes\nBrake System: Tektro HD-E725 Hydraulic Disc Brake\nBrake Rotors: 180mm Front, 160mm Rear\n\nE-bike system\nMotor: 750W Brushless\nBattery: 48V/14Ah Lithium-Ion\nCharger: 48V/3A Smart Charger\nController: Intelligent Sinusoidal Wave\n\nWeight\nWeight: 59.5 lbs\n\n## Sizing & fit\n| Size | Rider Height | Standover Height |\n|------|-------------|-----------------|\n| S | 5'2\"-5'6\" | 28.5\" |\n| M | 5'7\"-6'0\" | 29.5\" |\n| L | 6'0\"-6'4\" | 30.5\" |\n\n## Geometry\nAll measurements provided in cm.\nSizing table\n| Frame size letter | S | M | L |\n|-------------------|-----|-----|-----|\n| Wheel Size | 27.5\"| 27.5\"| 27.5\"|\n| Seat tube length | 44.5| 48.5| 52.5|\n| Head tube angle | 68° | 68° | 68° |\n| Seat tube angle | 74.5°| 74.5°| 74.5°|\n| Effective top tube | 57.5| 59.5| 61.5|\n| Head tube length | 12.0| 12.0| 13.0|\n| Chainstay length | 45.5| 45.5| 45.5|\n| Bottom bracket height | 30.0| 30.0| 30.0|\n| Wheelbase | 115.0|116.5|118.5|", "price": 1999.99, "tags": [ "bicycle", "road bike" ] }, { "name": "VeloTech V9.5 AXS Gen 3", "shortDescription": "VeloTech V9.5 AXS is a sleek and fast carbon bike that combines high-end tech with a comfortable ride. It's designed to provide the ultimate experience for the most serious riders. The bike comes with a lightweight and powerful motor that can be activated when needed, and you get a spec filled with premium parts.", "description": "## Overview\nIt's right for you if...\nYou want a bike that is fast, efficient, and delivers an adrenaline-filled experience. You are looking for a bike that is built with cutting-edge technology, and you want a ride that is both comfortable and exciting.\n\nThe tech you get\nA lightweight and durable full carbon frame with a fork that has 100mm of travel. The bike comes with a powerful motor that can deliver up to 20 mph of assistance. The drivetrain is a wireless electronic system that is precise and reliable. The bike is also equipped with hydraulic disc brakes, tubeless-ready wheels, and comfortable grips.\n\nThe final word\nThe VeloTech V9.5 AXS is a high-end bike that delivers an incredible experience for serious riders. It combines the latest technology with a comfortable ride, making it perfect for long rides, tough climbs, and fast descents.\n\n## Features\nFast and efficient\nThe VeloTech V9.5 AXS comes with a powerful motor that can provide up to 20 mph of assistance. The motor is lightweight and efficient, providing a boost when you need it without adding bulk. The bike's battery is removable, allowing you to ride without assistance when you don't need it.\n\nSmart software for the trail\nThe VeloTech V9.5 AXS is equipped with intelligent software that delivers a smooth and responsive ride. The software allows the motor to respond immediately as you start to pedal, delivering more power over a wider cadence range. You can also customize your user settings to suit your preferences.\n\nComfortable ride\nThe VeloTech V9.5 AXS is designed to provide a comfortable ride, even on long rides. The bike's fork has 100mm of travel, providing ample cushioning for rough terrain. The bike's grips are also designed to provide a comfortable and secure grip, even on the most challenging rides.\n\n## Specs\nFrameset\nFrame\tCarbon fiber frame with internal cable routing and Boost148\nFork\t100mm of travel with remote lockout\nShock\tN/A\n\nWheels\nWheel front\tCarbon fiber tubeless-ready wheel\nWheel rear\tCarbon fiber tubeless-ready wheel\nSkewer rear\t12mm thru-axle\nTire\tTubeless-ready tire\nTire part\tTubeless sealant\n\nDrivetrain\nShifter\tWireless electronic shifter\nRear derailleur\tWireless electronic derailleur\nCrank\tCarbon fiber crankset with chainring\nCrank arm\tCarbon fiber crank arm\nChainring\tAlloy chainring\nCassette\t12-speed cassette\nChain\t12-speed chain\n\nComponents\nSaddle\tCarbon fiber saddle\nSeatpost\tCarbon fiber seatpost\nHandlebar\tCarbon fiber handlebar\nGrips\tComfortable and secure grips\nStem\tCarbon fiber stem\nHeadset\tCarbon fiber headset\nBrake\tHydraulic disc brakes\nBrake rotor\tDisc brake rotor\n\nAccessories\nE-bike system\tPowerful motor with removable battery\nBattery\tLithium-ion battery\nCharger\tFast charging adapter\nController\tHandlebar-mounted controller\nTool\tBasic toolkit\n\nWeight\nWeight\tM - 17.5 kg / 38.5 lbs (with tubeless sealant)\n\nWeight limit\nThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing & fit\n| Size | Rider Height | Inseam |\n|:----:|:------------------------:|:--------------------:|\n| S | 160 - 170 cm 5'3\" - 5'7\" | 74 - 79 cm 29\" - 31\" |\n| M | 170 - 180 cm 5'7\" - 5'11\" | 79 - 84 cm 31\" - 33\" |\n| L | 180 - 190 cm 5'11\" - 6'3\" | 84 - 89 cm 33\" - 35\" |\n| XL | 190 - 200 cm 6'3\" - 6'7\" | 89 - 94 cm 35\" - 37\" |\n\n## Geometry\nAll measurements provided in cm unless otherwise noted.\nSizing table\n| Frame size letter | S | M | L | XL |\n|---------------------------|-------|-------|-------|-------|\n| Actual frame size | 50.0 | 53.3 | 55.6 | 58.8 |\n| Wheel size | 29\" | 29\" | 29\" | 29\" |\n| A — Seat tube | 39.4 | 43.2 | 48.3 | 53.3 |\n| B — Seat tube angle | 72.3° | 72.6° | 72.8° | 72.8° |\n| C — Head tube length | 9.0 | 10.0 | 10.5 | 11.0 |\n| D — Head angle | 67.5° | 67.5° | 67.5° | 67.5° |\n| E — Effective top tube | 58.0 | 61.7 | 64.8 | 67.0 |\n| F — Bottom bracket height | 32.3 | 32.3 | 32.3 | 32.3 |\n| G — Bottom bracket drop | 5.0 | 5.0 | 5.0 | 5.0 |\n| H — Chainstay length | 44.7 | 44.7 | 44.7 | 44.7 |\n| I — Offset | 4.2 | 4.2 | 4.2 | 4.2 |\n| J — Trail | 10.9 | 10.9 | 10.9 | 10.9 |\n| K — Wheelbase | 112.6 | 116.5 | 119.7 | 121.9 |\n| L — Standover | 76.8 | 76.8 | 76.8 | 76.8 |\n| M — Frame reach | 40.5 | 44.0 | 47.0 | 49.0 |\n| N — Frame stack | 60.9 | 61.8 | 62.2 | 62.7 |", "price": 1699.99, "tags": [ "bicycle", "electric bike", "city bike" ] }, { "name": "Axiom D8 E-Mountain Bike", "shortDescription": "The Axiom D8 is an electrifying mountain bike that is built for adventure. It boasts a light aluminum frame, a powerful motor and the latest tech to tackle the toughest of terrains. The D8 provides assistance without adding bulk to the bike, giving you the flexibility to ride like a traditional mountain bike or have an extra push when you need it.", "description": "## Overview \nIt's right for you if... \nYou're looking for an electric mountain bike that can handle a wide variety of terrain, from flowing singletrack to technical descents. You also want a bike that offers a powerful motor that provides assistance without adding bulk to the bike. The D8 is designed to take you anywhere, quickly and comfortably.\n\nThe tech you get \nA lightweight aluminum frame with 140mm of travel, a Suntour fork with hydraulic lockout, and a reliable and powerful Bafang M400 mid-motor that provides a boost up to 20 mph. The bike features a Shimano Deore drivetrain, hydraulic disc brakes, and a dropper seat post. With the latest tech on-board, the D8 is designed to take you to new heights.\n\nThe final word \nThe Axiom D8 is an outstanding electric mountain bike that is designed for adventure. It's built with the latest tech and provides the flexibility to ride like a traditional mountain bike or have an extra push when you need it. Whether you're a beginner or an experienced rider, the D8 is the perfect companion for your next adventure.\n\n## Features \nBuilt for Adventure \n\nThe D8 features a lightweight aluminum frame that is built to withstand rugged terrain. It comes equipped with 140mm of travel and a Suntour fork that can handle even the toughest of trails. With this bike, you're ready to take on anything the mountain can throw at you.\n\nPowerful Motor \n\nThe Bafang M400 mid-motor provides reliable and powerful assistance without adding bulk to the bike. You can quickly and easily switch between the different assistance levels to find the perfect balance between range and power.\n\nShimano Deore Drivetrain \n\nThe Shimano Deore drivetrain is reliable and offers smooth shifting on any terrain. You can easily adjust the gears to match your riding style and maximize your performance on the mountain.\n\nDropper Seat Post \n\nThe dropper seat post allows you to easily adjust your seat height on the fly, so you can maintain the perfect position for any terrain. With the flick of a switch, you can quickly and easily lower or raise your seat to match the terrain.\n\nHydraulic Disc Brakes \n\nThe D8 features powerful hydraulic disc brakes that offer reliable stopping power in any weather condition. You can ride with confidence knowing that you have the brakes to stop on a dime.\n\n## Specs \nFrameset \nFrame\tAluminum frame with 140mm of travel \nFork\tSuntour fork with hydraulic lockout, 140mm of travel \nShock\tN/A \nMax compatible fork travel\t140mm \n \nWheels \nWheel front\tAlloy wheel \nWheel rear\tAlloy wheel \nSkewer rear\tThru axle \nTire\t29\" x 2.35\" \nTire part\tN/A \nMax tire size\t29\" x 2.6\" \n \nDrivetrain \nShifter\tShimano Deore \nRear derailleur\tShimano Deore \nCrank\tBafang M400 \nCrank arm\tN/A \nChainring\tN/A \nCassette\tShimano Deore \nChain\tShimano Deore \nMax chainring size\tN/A \n \nComponents \nSaddle\tAxiom D8 saddle \nSeatpost\tDropper seat post \nHandlebar\tAxiom D8 handlebar \nGrips\tAxiom D8 grips \nStem\tAxiom D8 stem \nHeadset\tAxiom D8 headset \nBrake\tHydraulic disc brakes \nBrake rotor\t180mm \n\nAccessories \nE-bike system\tBafang M400 mid-motor \nBattery\tLithium-ion battery, 500Wh \nCharger\tLithium-ion charger \nController\tBafang M400 controller \nTool\tN/A \n \nWeight \nWeight\tM - 22 kg / 48.5 lbs \nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 136 kg (300 lbs). \n \n \n## Sizing & fit \n \n| Size | Rider Height | Inseam | \n|:----:|:------------------------:|:--------------------:| \n| S | 152 - 165 cm 5'0\" - 5'5\" | 70 - 76 cm 27\" - 30\" | \n| M | 165 - 178 cm 5'5\" - 5'10\" | 76 - 81 cm 30\" - 32\" | \n| L | 178 - 185 cm 5'10\" - 6'1\" | 81 - 86 cm 32\" - 34\" | \n| XL | 185 - 193 cm 6'1\" - 6'4\" | 86 - 91 cm 34\" - 36\" | \n \n \n## Geometry \n \nAll measurements provided in cm unless otherwise noted. \nSizing table \n| Frame size letter | S | M | L | XL | \n|---------------------------|-------|-------|-------|-------| \n| Actual frame size | 41.9 | 46.5 | 50.8 | 55.9 | \n| Wheel size | 29\" | 29\" | 29\" | 29\" | \n| A — Seat tube | 42.0 | 46.5 | 51.0 | 56.0 | \n| B — Seat tube angle | 74.0° | 74.0° | 74.0° | 74.0° | \n| C — Head tube length | 11.0 | 12.0 | 13.0 | 15.0 | \n| D — Head angle | 68.0° | 68.0° | 68.0° | 68.0° | \n| E — Effective top tube | 57.0 | 60.0 | 62.0 | 65.0 | \n| F — Bottom bracket height | 33.0 | 33.0 | 33.0 | 33.0 | \n| G — Bottom bracket drop | 3.0 | 3.0 | 3.0 | 3.0 | \n| H — Chainstay length | 46.0 | 46.0 | 46.0 | 46.0 | \n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 | \n| J — Trail | 10.9 | 10.9 | 10.9 | 10.9 | \n| K — Wheelbase | 113.0 | 116.0 | 117.5 | 120.5 | \n| L — Standover | 73.5 | 75.5 | 76.5 | 79.5 | \n| M — Frame reach | 41.0 | 43.5 | 45.0 | 47.5 | \n| N — Frame stack | 60.5 | 61.5 | 62.5 | 64.5 |", "price": 1399.99, "tags": [ "bicycle", "electric bike", "mountain bike" ] }, { "name": "Velocity X1", "shortDescription": "Velocity X1 is a high-performance road bike designed for speed enthusiasts. It features a lightweight yet durable frame, aerodynamic design, and top-quality components, making it the perfect choice for those who want to take their cycling experience to the next level.", "description": "## Overview\nIt's right for you if...\nYou're an experienced cyclist looking for a bike that can keep up with your need for speed. You want a bike that's lightweight, aerodynamic, and built to perform, whether you're training for a race or just pushing yourself to go faster.\n\nThe tech you get\nA lightweight aluminum frame with a carbon fork, Shimano Ultegra groupset with a wide range of gearing, hydraulic disc brakes, aerodynamic carbon wheels, and a vibration-absorbing handlebar with ergonomic grips.\n\nThe final word\nVelocity X1 is the ultimate road bike for speed enthusiasts. Its lightweight frame, aerodynamic design, and top-quality components make it the perfect choice for those who want to take their cycling experience to the next level.\n\n\n## Features\n\nAerodynamic design\nVelocity X1 is built with an aerodynamic design to help you go faster with less effort. It features a sleek profile, hidden cables, and a carbon fork that cuts through the wind, reducing drag and increasing speed.\n\nHydraulic disc brakes\nVelocity X1 comes equipped with hydraulic disc brakes, providing excellent stopping power in all weather conditions. They're also low maintenance, with minimal adjustments needed over time.\n\nCarbon wheels\nThe Velocity X1's aerodynamic carbon wheels provide excellent speed and responsiveness, helping you achieve your fastest times yet. They're also lightweight, reducing overall bike weight and making acceleration and handling even easier.\n\nShimano Ultegra groupset\nThe Shimano Ultegra groupset provides smooth shifting and reliable performance, ensuring you get the most out of every ride. With a wide range of gearing options, it's ideal for tackling any terrain, from steep climbs to fast descents.\n\n\n## Specifications\nFrameset\nFrame with Fork\tAluminium frame, internal cable routing, 135x9mm QR\nFork\tCarbon, hidden cable routing, 100x9mm QR\n\nWheels\nWheel front\tCarbon, 30mm deep rim, 23mm width, 100x9mm QR\nWheel rear\tCarbon, 30mm deep rim, 23mm width, 135x9mm QR\nSkewer front\t100x9mm QR\nSkewer rear\t135x9mm QR\nTire\tContinental Grand Prix 5000, 700x25mm, folding bead\nMax tire size\t700x28mm without fenders\n\nDrivetrain\nShifter\tShimano Ultegra R8020, 11 speed\nRear derailleur\tShimano Ultegra R8000, 11 speed\n*Crank\tSize: S, M\nShimano Ultegra R8000, 50/34T, 170mm length\nSize: L, XL\nShimano Ultegra R8000, 50/34T, 175mm length\nBottom bracket\tShimano BB-RS500-PB, PressFit\nCassette\tShimano Ultegra R8000, 11-30T, 11 speed\nChain\tShimano Ultegra HG701, 11 speed\nPedal\tNot included\nMax chainring size\t50/34T\n\nComponents\nSaddle\tBontrager Montrose Comp, steel rails, 138mm width\nSeatpost\tBontrager Comp, 6061 alloy, 27.2mm, 8mm offset, 330mm length\n*Handlebar\tSize: S, M, L\nBontrager Elite Aero VR-CF, alloy, 31.8mm, 93mm reach, 123mm drop, 400mm width\nSize: XL\nBontrager Elite Aero VR-CF, alloy, 31.8mm, 93mm reach, 123mm drop, 420mm width\nGrips\tBontrager Supertack Perf tape\n*Stem\tSize: S, M, L\nBontrager Elite Blendr, 31.8mm clamp, 7 degree, 90mm length\nSize: XL\nBontrager Elite Blendr, 31.8mm clamp, 7 degree, 100mm length\nBrake\tShimano Ultegra R8070 hydraulic disc, flat mount\nBrake rotor\tShimano RT800, centerlock, 160mm\nRotor size\tMax brake rotor sizes: 160mm front & rear\n\nWeight\nWeight\tM - 8.15 kg / 17.97 lbs\nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 275 pounds (125 kg).\n\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| S | 162 - 170 cm 5'4\" - 5'7\" | 74 - 78 cm 29\" - 31\" |\n| M | 170 - 178 cm 5'7\" - 5'10\" | 77 - 82 cm 30\" - 32\" |\n| L | 178 - 186 cm 5'10\" - 6'1\" | 82 - 86 cm 32\" - 34\" |\n| XL | 186 - 196 cm 6'1\" - 6'5\" | 87 - 92 cm 34\" - 36\" |\n\n\n## Geometry\n| Frame size letter | S | M | L | XL |\n|---------------------------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 50.0 | 52.0 | 54.0 | 56.0 |\n| B — Seat tube angle | 74.0° | 73.5° | 73.0° | 72.5° |\n| C — Head tube length | 13.0 | 15.0 | 17.0 | 19.0 |\n| D — Head angle | 71.0° | 72.0° | 72.0° | 72.5° |\n| E — Effective top tube | 53.7 | 55.0 | 56.5 | 58.0 |\n| F — Bottom bracket height | 27.5 | 27.5 | 27.5 | 27.5 |\n| G — Bottom bracket drop | 7.3 | 7.3 | 7.3 | 7.3 |\n| H — Chainstay length | 41.0 | 41.0 | 41.0 | 41.0 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 6.0 | 6.0 | 6.0 | 5.8 |\n| K — Wheelbase | 98.2 | 99.1 | 100.1 | 101.0 |\n| L — Standover | 75.2 | 78.2 | 81.1 | 84.1 |\n| M — Frame reach | 37.5 | 38.3 | 39.1 | 39.9 |\n| N — Frame stack | 53.3 | 55.4 | 57.4 | 59.5 |", "price": 1799.99, "tags": [ "bicycle", "touring bike" ] }, { "name": "Velocity V9", "shortDescription": "Velocity V9 is a high-performance hybrid bike that combines speed and comfort for riders who demand the best of both worlds. The lightweight aluminum frame, along with the carbon fork and seat post, provide optimal stiffness and absorption to tackle any terrain. A 2x Shimano Deore drivetrain, hydraulic disc brakes, and 700c wheels with high-quality tires make it a versatile ride for commuters, fitness riders, and weekend adventurers alike.", "description": "## Overview\nIt's right for you if...\nYou want a fast, versatile bike that can handle anything from commuting to weekend adventures. You value comfort as much as speed and performance. You want a reliable and durable bike that will last for years to come.\n\nThe tech you get\nA lightweight aluminum frame with a carbon fork and seat post, a 2x Shimano Deore drivetrain with a wide range of gearing, hydraulic disc brakes, and 700c wheels with high-quality tires. The Velocity V9 is designed for riders who demand both performance and comfort in one package.\n\nThe final word\nThe Velocity V9 is the perfect bike for riders who want speed and performance without sacrificing comfort. The lightweight aluminum frame and carbon components provide optimal stiffness and absorption, while the 2x Shimano Deore drivetrain and hydraulic disc brakes ensure precise shifting and stopping power. Whether you're commuting, hitting the trails, or training for your next race, the Velocity V9 has everything you need to achieve your goals.\n\n## Features\n\n2x drivetrain\nA 2x drivetrain means more versatility and a wider range of gearing options. Whether you're climbing hills or sprinting on the flats, the Velocity V9 has the perfect gear for any situation.\n\nCarbon components\nThe Velocity V9 features a carbon fork and seat post to provide optimal stiffness and absorption. This means you can ride faster and more comfortably over any terrain.\n\nHydraulic disc brakes\nHydraulic disc brakes provide unparalleled stopping power and modulation in any weather condition. You'll feel confident and in control no matter where you ride.\n\n## Specifications\nFrameset\nFrame with Fork\tAluminum frame with carbon fork and seat post, internal cable routing, fender mounts, 135x5mm ThruSkew\nFork\tCarbon fork, hidden fender mounts, flat mount disc, 5x100mm thru-skew\n\nWheels\nWheel front\tDouble wall aluminum rims, 700c, quick release hub\nWheel rear\tDouble wall aluminum rims, 700c, quick release hub\nTire\tKenda Kwick Tendril, puncture resistant, reflective sidewall, 700x32c\nMax tire size\t700x35c without fenders, 700x32c with fenders\n\nDrivetrain\nShifter\tShimano Deore, 10 speed\nFront derailleur\tShimano Deore\nRear derailleur\tShimano Deore\nCrank\tShimano Deore, 46-30T, 170mm (S/M), 175mm (L/XL)\nBottom bracket\tShimano BB52, 68mm, threaded\nCassette\tShimano Deore, 11-36T, 10 speed\nChain\tShimano HG54, 10 speed\nPedal\tWellgo alloy platform\n\nComponents\nSaddle\tVelo VL-2158, steel rails\nSeatpost\tCarbon seat post, 27.2mm\nHandlebar\tAluminum, 31.8mm clamp, 15mm rise, 680mm width\nGrips\tVelo ergonomic grips\nStem\tAluminum, 31.8mm clamp, 7 degree, 90mm length\nBrake\tShimano hydraulic disc, MT200 lever, MT200 caliper\nBrake rotor\tShimano RT56, centerlock, 160mm\nRotor size\tMax brake rotor sizes: 160mm front & rear\n\nWeight\nWeight\tM - 11.5 kg / 25.35 lbs\nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| S | 155 - 165 cm 5'1\" - 5'5\" | 72 - 78 cm 28\" - 31\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n| XL | 186 - 197 cm 6'1\" - 6'6\" | 87 - 93 cm 34\" - 37\" |\n\n## Geometry\n| Frame size | S | M | L | XL |\n|--------------------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 44.0 | 48.0 | 52.0 | 56.0 |\n| B — Seat tube angle | 74.5° | 74.0° | 73.5° | 73.0° |\n| C — Head tube length | 14.5 | 16.0 | 18.0 | 20.0 |\n| D — Head angle | 71.0° | 71.0° | 71.5° | 71.5° |\n| E — Effective top tube | 56.5 | 57.5 | 58.5 | 59.5 |\n| F — Bottom bracket height | 27.0 | 27.0 | 27.0 | 27.0 |\n| G — Bottom bracket drop | 7.0 | 7.0 | 7.0 | 7.0 |\n| H — Chainstay length | 43.0 | 43.0 | 43.0 | 43.0 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 7.0 | 7.0 | 6.6 | 6.6 |\n| K — Wheelbase | 105.4 | 106.3 | 107.2 | 108.2 |\n| L — Standover | 73.2 | 77.1 | 81.2 | 85.1 |\n| M — Frame reach | 39.0 | 39.8 | 40.4 | 41.3 |\n| N — Frame stack | 57.0 | 58.5 | 60.0 | 61.5 |", "price": 2199.99, "tags": [ "bicycle", "electric bike", "mountain bike" ] }, { "name": "Aero Pro X", "shortDescription": "Aero Pro X is a high-end racing bike designed for serious cyclists who demand speed, agility, and superior performance. The lightweight carbon frame and fork, combined with the aerodynamic design, provide optimal stiffness and efficiency to maximize your speed. The bike features a 2x Shimano Ultegra drivetrain, hydraulic disc brakes, and 700c wheels with high-quality tires. Whether you're competing in a triathlon or climbing steep hills, Aero Pro X delivers exceptional performance and precision handling.", "description": "## Overview\nIt's right for you if...\nYou are a competitive cyclist looking for a bike that is designed for racing. You want a bike that delivers exceptional speed, agility, and precision handling. You demand superior performance and reliability from your equipment.\n\nThe tech you get\nA lightweight carbon frame with an aerodynamic design, a carbon fork with hidden fender mounts, a 2x Shimano Ultegra drivetrain with a wide range of gearing, hydraulic disc brakes, and 700c wheels with high-quality tires. Aero Pro X is designed for serious cyclists who demand nothing but the best.\n\nThe final word\nAero Pro X is the ultimate racing bike for serious cyclists. The lightweight carbon frame and aerodynamic design deliver maximum speed and efficiency, while the 2x Shimano Ultegra drivetrain and hydraulic disc brakes ensure precise shifting and stopping power. Whether you're competing in a triathlon or a criterium race, Aero Pro X delivers the performance you need to win.\n\n## Features\n\nAerodynamic design\nThe Aero Pro X features an aerodynamic design that reduces drag and maximizes efficiency. The bike is optimized for speed and agility, so you can ride faster and farther with less effort.\n\nHydraulic disc brakes\nHydraulic disc brakes provide unrivaled stopping power and modulation in any weather condition. You'll feel confident and in control no matter where you ride.\n\nCarbon components\nThe Aero Pro X features a carbon fork with hidden fender mounts to provide optimal stiffness and absorption. This means you can ride faster and more comfortably over any terrain.\n\n## Specifications\nFrameset\nFrame with Fork\tCarbon frame with an aerodynamic design, internal cable routing, 3s chain keeper, 142x12mm thru-axle\nFork\tCarbon fork with hidden fender mounts, flat mount disc, 100x12mm thru-axle\n\nWheels\nWheel front\tDouble wall carbon rims, 700c, thru-axle hub\nWheel rear\tDouble wall carbon rims, 700c, thru-axle hub\nTire\tContinental Grand Prix 5000, folding bead, 700x25c\nMax tire size\t700x28c without fenders, 700x25c with fenders\n\nDrivetrain\nShifter\tShimano Ultegra, 11 speed\nFront derailleur\tShimano Ultegra\nRear derailleur\tShimano Ultegra\nCrank\tShimano Ultegra, 52-36T, 170mm (S), 172.5mm (M), 175mm (L/XL)\nBottom bracket\tShimano BB72, 68mm, PressFit\nCassette\tShimano Ultegra, 11-30T, 11 speed\nChain\tShimano HG701, 11 speed\nPedal\tNot included\n\nComponents\nSaddle\tBontrager Montrose Elite, carbon rails, 138mm width\nSeatpost\tCarbon seat post, 27.2mm, 20mm offset\nHandlebar\tBontrager XXX Aero, carbon, 31.8mm clamp, 75mm reach, 125mm drop\nGrips\tBontrager Supertack Perf tape\nStem\tBontrager Pro, 31.8mm clamp, 7 degree, 90mm length\nBrake\tShimano hydraulic disc, Ultegra lever, Ultegra caliper\nBrake rotor\tShimano RT800, centerlock, 160mm\nRotor size\tMax brake rotor sizes: 160mm front & rear\n\nWeight\nWeight\tM - 8.36 kg / 18.42 lbs\nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 275 pounds (125 kg).\n\n## Sizing\n| Size | Rider Height |\n|:----:|:-------------------------:|\n| S | 155 - 165 cm 5'1\" - 5'5\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" |\n| XL | 186 - 197 cm 6'1\" - 6'6\" |\n\n## Geometry\n| Frame size | S | M | L | XL |\n|--------------------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 50.6 | 52.4 | 54.3 | 56.2 |\n| B — Seat tube angle | 75.5° | 74.5° | 73.5° | 72.5° |\n| C — Head tube length | 12.0 | 14.0 | 16.0 | 18.0 |\n| D — Head angle | 72.5° | 73.0° | 73.5° | 74.0° |\n| E — Effective top tube | 53.8 | 55.4 | 57.0 | 58.6 |\n| F — Bottom bracket height | 26.5 | 26.5 | 26.5 | 26.5 |\n| G — Bottom bracket drop | 7.0 | 7.0 | 7.0 | 7.0 |\n| H — Chainstay length | 41.0 | 41.0 | 41.0 | 41.0 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 6.0 | 6.0 | 6.0 | 6.0 |\n| K — Wheelbase | 97.1 | 98.7 | 100.2 | 101.8 |\n| L — Standover | 73.8 | 76.2 | 78.5 | 80.8 |\n| M — Frame reach | 38.8 | 39.5 | 40.2 | 40.9 |\n| N — Frame stack | 52.8 | 54.7 | 56.6 | 58.5 |", "price": 1599.99, "tags": [ "bicycle", "road bike" ] }, { "name": "Voltex+ Ultra Lowstep", "shortDescription": "Voltex+ Ultra Lowstep is a high-performance electric hybrid bike designed for riders who seek speed, comfort, and reliability during their everyday rides. Equipped with a powerful and efficient Voltex Drive Pro motor and a fully-integrated 600Wh battery, this e-bike allows you to cover longer distances on a single charge. The Voltex+ Ultra Lowstep comes with premium components that prioritize comfort and safety, such as a suspension seatpost, wide and stable tires, and integrated lights.", "description": "## Overview\n\nIt's right for you if...\nYou want an e-bike that provides a boost for faster rides and effortless usage. Durability is crucial, and you need a bike with one of the most powerful and efficient motors.\n\nThe tech you get\nA lightweight Delta Carbon Fiber frame with an ultra-lowstep design, a Voltex Drive Pro (350W, 75Nm) motor capable of maintaining speeds up to 30 mph, an extended range 600Wh battery integrated into the frame, and a Voltex Control Panel. Additionally, it features a 12-speed Shimano drivetrain, hydraulic disc brakes for optimal all-weather stopping power, a suspension seatpost, wide puncture-resistant tires for added stability, ergonomic grips, a kickstand, lights, and a cargo rack.\n\nThe final word\nThis bike offers enhanced enjoyment and ease of use on long commutes, leisure rides, and adventures. With its extended-range battery, powerful Voltex motor, user-friendly controller, and a seatpost that smooths out road vibrations, it guarantees an exceptional riding experience.\n\n## Features\n\nUltra-fast assistance\n\nExperience speeds up to 30 mph with the cutting-edge Voltex Drive Pro motor, allowing you to breeze through errands, commutes, and joyrides.\n\n## Specs\n\nFrameset\n- Frame: Delta Carbon Fiber, Removable Integrated Battery (RIB), sleek welds, rack & fender mounts, internal routing, kickstand mount, 135x5mm QR\n- Fork: Voltex Alloy, threaded steel steerer, rack mounts, post mount disc, 460mm axle-to-crown, ThruSkew 5mm QR\n- Max compatible fork travel: 50mm\n\nWheels\n- Hub front: Formula DC-20, alloy, 6-bolt, 5x100mm QR\n- Skewer front: 132x5mm QR, ThruSkew\n- Hub rear: Formula DC-22, alloy, 6-bolt, Shimano 8/9/10 freehub, 135x5mm QR\n- Skewer rear: 153x5mm bolt-on\n- Rim: Voltex Connection, double-wall, 32-hole, 20 mm width, Schrader valve\n- Tire: Voltex E6 Hard-Case Lite, reflective, wire bead, 60tpi, 700x50c\n- Max tire size: 700x50mm with or without fenders\n\nDrivetrain\n- Shifter: Shimano Deore XT M8100, 12-speed\n- Rear derailleur: Shimano Deore XT M8100, long cage\n- Crank: Voltex alloy, 170mm length\n- Chainring: FSA, 44T, aluminum with guard\n- Cassette: Shimano Deore XT M8100, 10-51, 12-speed\n- Chain: KMC E12 Turbo\n- Pedal: Voltex Urban pedals\n\nComponents\n- Saddle: Voltex Boulevard\n- Seatpost: Alloy, suspension, 31.6mm, 300mm length\n- Handlebar: Voltex alloy, 31.8mm, comfort sweep, 620mm width (XS, S, M), 660mm width (L)\n- Grips: Voltex Satellite Elite, alloy lock-on\n- Stem: Voltex alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 85mm length (XS, S), 105mm length (M, L)\n- Headset: VP sealed cartridge, 1-1/8'', threaded\n- Brake: Shimano MT520 hydraulic disc\n- Brake rotor: Shimano RT56, 6-bolt, 180mm (XS, S, M, L), 160mm (XS, S, M, L)\n\nAccessories\n- Battery: Voltex PowerTube 600Wh\n- Charger: Voltex compact 2A, 100-240V\n- Computer: Voltex Control Panel\n- Motor: Voltex Drive Pro, 75Nm, 30mph\n- Light: Voltex Solo for e-bike, taillight (XS, S, M, L), Voltex MR8, 180 lumen, 60 lux, LED, headlight (XS, S, M, L)\n- Kickstand: Adjustable length rear mount alloy kickstand\n- Cargo rack: Voltex-compatible alloy rear rack, maximum load 25 kg / 55 lbs\n- Fender: Voltex wide (XS, S, M, L), Voltex plastic (XS, S, M, L)\n\nWeight\n- Weight: M - 20.50 kg / 45.19 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 330 pounds (150 kg).\n\n## Sizing\n\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| XS | 147 - 155 cm 4'10\" - 5'1\" | 69 - 73 cm 27\" - 29\" |\n| S | 155 - 165 cm 5'1\" - 5'5\" | 72 - 78 cm 28\" - 31\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\n\nSizing table\n\n| Frame size number | 40 cm | 45 cm | 50 cm | 55 cm |\n|---------------------------|-------|-------|-------|-------|\n| Frame size letter | XS | S | M | L |\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 38.0 | 43.0 | 48.0 | 53.0 |\n| B — Seat tube angle | 70.5° | 70.5° | 70.5° | 70.5° |\n| C — Head tube length | 15.0 | 15.0 | 17.0 | 19.0 |\n| D — Head angle | 69.2° | 69.2° | 69.2° | 69.2° |\n| E — Effective top tube | 57.2 | 57.7 | 58.8 | 60.0 |\n| F — Bottom bracket height | 30.3 | 30.3 | 30.3 | 30.3 |\n| G — Bottom bracket drop | 6.0 | 6.0 | 6.0 | 6.0 |\n| H — Chainstay length | 48.5 | 48.5 | 48.5 | 48.5 |\n| I — Offset | 5.0 | 5.0 | 5.0 | 5.0 |\n| J — Trail | 9.0 | 9.0 | 9.0 | 9.0 |\n| K — Wheelbase | 111.8 | 112.3 | 113.6 | 114.8 |\n| L — Standover | 42.3 | 42.3 | 42.3 | 42.3 |\n| M — Frame reach | 36.0 | 38.0 | 38.0 | 38.0 |\n| N — Frame stack | 62.0 | 62.0 | 63.9 | 65.8 |\n| Stem length | 8.0 | 8.5 | 8.5 | 10.5 |\n\nPlease note that the specifications and features listed above are subject to change and may vary based on different models and versions of the Voltex+ Ultra Lowstep bike.", "price": 2999.99, "tags": [ "bicycle", "road bike", "professional" ] }, { "name": "SwiftRide Hybrid", "shortDescription": "SwiftRide Hybrid is a versatile and efficient bike designed for riders who want a smooth and enjoyable ride on various terrains. It incorporates advanced technology and high-quality components to provide a comfortable and reliable cycling experience.", "description": "## Overview\n\nIt's right for you if...\nYou are looking for a bike that combines the benefits of an electric bike with the versatility of a hybrid. You value durability, speed, and ease of use.\n\nThe tech you get\nThe SwiftRide Hybrid features a lightweight and durable aluminum frame, making it easy to handle and maneuver. It is equipped with a powerful electric motor that offers a speedy assist, helping you reach speeds of up to 25 mph. The bike comes with a removable and fully-integrated 500Wh battery, providing a long-range capacity for extended rides. It also includes a 10-speed Shimano drivetrain, hydraulic disc brakes for precise stopping power, wide puncture-resistant tires for stability, and integrated lights for enhanced visibility.\n\nThe final word\nThe SwiftRide Hybrid is designed for riders who want a bike that can handle daily commutes, recreational rides, and adventures. With its efficient motor, intuitive controls, and comfortable features, it offers an enjoyable and hassle-free riding experience.\n\n## Features\n\nEfficient electric assist\nExperience the thrill of effortless riding with the powerful electric motor that provides a speedy assist, making your everyday rides faster and more enjoyable.\n\n## Specs\n\nFrameset\n- Frame: Lightweight Aluminum, Removable Integrated Battery (RIB), rack & fender mounts, internal routing, 135x5mm QR\n- Fork: SwiftRide Alloy, threaded steel steerer, rack mounts, post mount disc, 460mm axle-to-crown, ThruSkew 5mm QR\n- Max compatible fork travel: 50mm\n\nWheels\n- Hub front: Formula DC-20, alloy, 6-bolt, 5x100mm QR\n- Skewer front: 132x5mm QR, ThruSkew\n- Hub rear: Formula DC-22, alloy, 6-bolt, Shimano 8/9/10 freehub, 135x5mm QR\n- Skewer rear: 153x5mm bolt-on\n- Rim: SwiftRide Connection, double-wall, 32-hole, 20 mm width, Schrader valve\n- Tire: SwiftRide E6 Hard-Case Lite, reflective, wire bead, 60tpi, 700x50c\n- Max tire size: 700x50mm with or without fenders\n\nDrivetrain\n- Shifter: Shimano Deore M4100, 10 speed\n- Rear derailleur: Shimano Deore M5120, long cage\n- Crank: ProWheel alloy, 170mm length\n- Chainring: FSA, 42T, steel w/guard\n- Cassette: Shimano Deore M4100, 11-42, 10 speed\n- Chain: KMC E10\n- Pedal: SwiftRide City pedals\n\nComponents\n- Saddle: SwiftRide Boulevard\n- Seatpost: Alloy, suspension, 31.6mm, 300mm length\n- Handlebar:\n - Size: XS, S, M - SwiftRide alloy, 31.8mm, comfort sweep, 620mm width\n - Size: L - SwiftRide alloy, 31.8mm, comfort sweep, 660mm width\n- Grips: SwiftRide Satellite Elite, alloy lock-on\n- Stem:\n - Size: XS, S - SwiftRide alloy quill, 31.8mm clamp, adjustable rise, 85mm length\n - Size: M, L - SwiftRide alloy quill, 31.8mm clamp, adjustable rise, 105mm length\n- Headset: VP sealed cartridge, 1-1/8'', threaded\n- Brake: Shimano MT200 hydraulic disc\n- Brake rotor:\n - Size: XS, S, M, L - Shimano RT26, 6-bolt, 180mm\n - Size: XS, S, M, L - Shimano RT26, 6-bolt, 160mm\n\nAccessories\n- Battery: SwiftRide PowerTube 500Wh\n- Charger: SwiftRide compact 2A, 100-240V\n- Computer: SwiftRide Purion\n- Motor: SwiftRide Performance Line Sport, 65Nm, 25mph\n- Light:\n - Size: XS, S, M, L - SwiftRide SOLO for e-bike, taillight\n - Size: XS, S, M, L - SwiftRide MR8, 180 lumen, 60 lux, LED, headlight\n- Kickstand: Adjustable length rear mount alloy kickstand\n- Cargo rack: SwiftRide-compatible alloy rear rack, maximum load 25 kg / 55 lbs\n- Fender:\n - Size: XS, S, M, L - SwiftRide wide\n - Size: XS, S, M, L - SwiftRide plastic\n\nWeight\n- Weight: M - 22.30 kg / 49.17 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| XS | 147 - 155 cm (4'10\" - 5'1\") | 69 - 73 cm (27\" - 29\") |\n| S | 155 - 165 cm (5'1\" - 5'5\") | 72 - 78 cm (28\" - 31\") |\n| M | 165 - 175 cm (5'5\" - 5'9\") | 77 - 83 cm (30\" - 33\") |\n| L | 175 - 186 cm (5'9\" - 6'1\") | 82 - 88 cm (32\" - 35\") |\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\n\nSizing table\n| Frame size number | 40 cm | 45 cm | 50 cm | 55 cm |\n|---------------------------|-------|-------|-------|-------|\n| Frame size letter | XS | S | M | L |\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 39.0 | 44.0 | 50.0 | 55.0 |\n| B — Seat tube angle | 71.0° | 71.0° | 71.0° | 71.0° |\n| C — Head tube length | 16.0 | 16.0 | 18.0 | 20.0 |\n| D — Head angle | 68.2° | 68.2° | 68.2° | 68.2° |\n| E — Effective top tube | 58.2 | 58.7 | 59.8 | 61.0 |\n| F — Bottom bracket height | 29.4 | 29.4 | 29.4 | 29.4 |\n| G — Bottom bracket drop | 6.5 | 6.5 | 6.5 | 6.5 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 9.5 | 9.5 | 9.5 | 9.5 |\n| K — Wheelbase | 112.2 | 112.7 | 114.0 | 115.2 |\n| L — Standover | 43.3 | 43.3 | 43.3 | 43.3 |\n| M — Frame reach | 36.5 | 38.5 | 38.5 | 38.5 |\n| N — Frame stack | 63.0 | 63.0 | 64.9 | 66.8 |\n| Stem length | 8.5 | 9.0 | 9.0 | 11.0 |", "price": 3999.99, "tags": [ "bicycle", "mountain bike", "professional" ] }, { "name": "RoadRunner E-Speed Lowstep", "shortDescription": "RoadRunner E-Speed Lowstep is a high-performance electric hybrid designed for riders seeking speed and excitement on their daily rides. It is equipped with a powerful and reliable ThunderBolt drive unit that offers exceptional acceleration. The bike features a fully-integrated 500Wh battery, allowing riders to cover longer distances on a single charge. With its comfortable and safe components, including a suspension seatpost, wide and stable tires, and integrated lights, the RoadRunner E-Speed Lowstep ensures a smooth and enjoyable ride.", "description": "## Overview\n\nIt's right for you if...\nYou're looking for an e-bike that provides an extra boost to reach your destination quickly and effortlessly. You prioritize durability and want a bike with one of the fastest motors available.\n\nThe tech you get\nA lightweight and sturdy ThunderBolt aluminum frame with a lowstep geometry. The bike is equipped with a ThunderBolt Performance Sport (250W, 65Nm) drive unit capable of reaching speeds up to 28 mph. It features a long-range 500Wh battery fully integrated into the frame and a ThunderBolt controller. Additionally, the bike has a 10-speed Shimano drivetrain, hydraulic disc brakes for reliable stopping power in all weather conditions, a suspension seatpost, wide puncture-resistant tires for stability, ergonomic grips, a kickstand, lights, and a rack and fenders.\n\nThe final word\nThe RoadRunner E-Speed Lowstep is designed to provide enjoyment and ease of use on longer commutes, recreational rides, and adventurous journeys. Its long-range battery, fast ThunderBolt motor, intuitive controller, and road-smoothing suspension seatpost make it the perfect choice for riders seeking both comfort and speed.\n\n## Features\n\nSuper speedy assist\n\nThe ThunderBolt Performance Sport drive unit allows you to accelerate up to 28mph, making errands, commutes, and joyrides a breeze.\n\n## Specs\n\nFrameset\n- Frame: ThunderBolt Smooth Aluminum, Removable Integrated Battery (RIB), sleek welds, rack & fender mounts, internal routing, kickstand mount, 135x5mm QR\n- Fork: RoadRunner Alloy, threaded steel steerer, rack mounts, post mount disc, 460mm axle-to-crown, ThruSkew 5mm QR\n- Max compatible fork travel: 50mm\n\nWheels\n- Hub front: ThunderBolt DC-20, alloy, 6-bolt, 5x100mm QR\n- Skewer front: 132x5mm QR, ThruSkew\n- Hub rear: ThunderBolt DC-22, alloy, 6-bolt, Shimano 8/9/10 freehub, 135x5mm QR\n- Skewer rear: 153x5mm bolt-on\n- Rim: ThunderBolt Connection, double-wall, 32-hole, 20 mm width, Schrader valve\n- Tire: ThunderBolt E6 Hard-Case Lite, reflective, wire bead, 60tpi, 700x50c\n- Max tire size: 700x50mm with or without fenders\n\nDrivetrain\n- Shifter: Shimano Deore M4100, 10 speed\n- Rear derailleur: Shimano Deore M5120, long cage\n- Crank: ProWheel alloy, 170mm length\n- Chainring: FSA, 42T, steel w/guard\n- Cassette: Shimano Deore M4100, 11-42, 10 speed\n- Chain: KMC E10\n- Pedal: RoadRunner City pedals\n\nComponents\n- Saddle: RoadRunner Boulevard\n- Seatpost: Alloy, suspension, 31.6mm, 300mm length\n- Handlebar:\n - Size: XS, S, M - RoadRunner alloy, 31.8mm, comfort sweep, 620mm width\n - Size: L - RoadRunner alloy, 31.8mm, comfort sweep, 660mm width\n- Grips: RoadRunner Satellite Elite, alloy lock-on\n- Stem:\n - Size: XS, S - RoadRunner alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 85mm length\n - Size: M, L - RoadRunner alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 105mm length\n- Headset: VP sealed cartridge, 1-1/8'', threaded\n- Brake: Shimano MT200 hydraulic disc\n- Brake rotor:\n - Size: XS, S, M, L - Shimano RT26, 6-bolt, 180mm\n - Size: XS, S, M, L - Shimano RT26, 6-bolt, 160mm\n\nAccessories\n- Battery: ThunderBolt PowerTube 500Wh\n- Charger: ThunderBolt compact 2A, 100-240V\n- Computer: ThunderBolt Purion\n- Motor: ThunderBolt Performance Line Sport, 65Nm, 28mph\n- Light:\n - Size: XS, S, M, L - ThunderBolt SOLO for e-bike, taillight\n - Size: XS, S, M, L - ThunderBolt MR8, 180 lumen, 60 lux, LED, headlight\n- Kickstand: Adjustable length rear mount alloy kickstand\n- Cargo rack: MIK-compatible alloy rear rack, maximum load 25 kg / 55 lbs\n- Fender:\n - Size: XS, S, M, L - RoadRunner wide\n - Size: XS, S, M, L - RoadRunner plastic\n\nWeight\n- Weight: M - 22.30 kg / 49.17 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| XS | 147 - 155 cm 4'10\" - 5'1\" | 69 - 73 cm 27\" - 29\" |\n| S | 155 - 165 cm 5'1\" - 5'5\" | 72 - 78 cm 28\" - 31\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\n\nSizing table\n| Frame size number | 40 cm | 45 cm | 50 cm | 55 cm |\n|---------------------------|-------|-------|-------|-------|\n| Frame size letter | XS | S | M | L |\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 39.0 | 44.0 | 50.0 | 55.0 |\n| B — Seat tube angle | 71.0° | 71.0° | 71.0° | 71.0° |\n| C — Head tube length | 16.0 | 16.0 | 18.0 | 20.0 |\n| D — Head angle | 68.2° | 68.2° | 68.2° | 68.2° |\n| E — Effective top tube | 58.2 | 58.7 | 59.8 | 61.0 |\n| F — Bottom bracket height | 29.4 | 29.4 | 29.4 | 29.4 |\n| G — Bottom bracket drop | 6.5 | 6.5 | 6.5 | 6.5 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 9.5 | 9.5 | 9.5 | 9.5 |\n| K — Wheelbase | 112.2 | 112.7 | 114.0 | 115.2 |\n| L — Standover | 43.3 | 43.3 | 43.3 | 43.3 |\n| M — Frame reach | 36.5 | 38.5 | 38.5 | 38.5 |\n| N — Frame stack | 63.0 | 63.0 | 64.9 | 66.8 |\n| Stem length | 8.5 | 9.0 | 9.0 | 11.0 |", "price": 4999.99, "tags": [ "bicycle", "road bike", "professional" ] }, { "name": "Hyperdrive Turbo X1", "shortDescription": "Hyperdrive Turbo X1 is a high-performance electric bike designed for riders seeking an exhilarating experience on their daily rides. It features a powerful and efficient Hyperdrive Sport drive unit and a sleek, integrated 500Wh battery for extended range. This e-bike is equipped with top-of-the-line components prioritizing comfort and safety, including a suspension seatpost, wide and stable tires, and integrated lights.", "description": "## Overview\n\nIt's right for you if...\nYou crave the thrill of an e-bike that can accelerate rapidly, reaching high speeds effortlessly. You value durability and are looking for a bike that is equipped with one of the fastest motors available.\n\nThe tech you get\nA lightweight Hyper Alloy frame with a lowstep geometry, a Hyperdrive Sport (300W, 70Nm) drive unit capable of maintaining speeds up to 30 mph, a long-range 500Wh battery seamlessly integrated into the frame, and an intuitive Hyper Control controller. Additionally, it features a 10-speed Shimano drivetrain, hydraulic disc brakes for reliable stopping power in all weather conditions, a suspension seatpost, wide puncture-resistant tires for enhanced stability, ergonomic grips, a kickstand, lights, and a rack and fenders.\n\nThe final word\nThis bike is designed for riders seeking enjoyment and convenience on longer commutes, recreational rides, and thrilling adventures. With its long-range battery, high-speed motor, user-friendly controller, and smooth-riding suspension seatpost, the Hyperdrive Turbo X1 guarantees an exceptional e-biking experience.\n\n## Features\n\nHyperboost Acceleration\nExperience adrenaline-inducing rides with the powerful Hyperdrive Sport drive unit that enables quick acceleration and effortless cruising through errands, commutes, and joyrides.\n\n## Specs\n\nFrameset\nFrame\tHyper Alloy, Removable Integrated Battery (RIB), seamless welds, rack & fender mounts, internal routing, kickstand mount, 135x5mm QR\nFork\tHyper Alloy, threaded steel steerer, rack mounts, post mount disc, 460mm axle-to-crown, ThruSkew 5mm QR\nMax compatible fork travel\t50mm\n\nWheels\nHub front\tFormula DC-20, alloy, 6-bolt, 5x100mm QR\nSkewer front\t132x5mm QR, ThruSkew\nHub rear\tFormula DC-22, alloy, 6-bolt, Shimano 8/9/10 freehub, 135x5mm QR\nSkewer rear\t153x5mm bolt-on\nRim\tHyper Connection, double-wall, 32-hole, 20 mm width, Schrader valve\nTire\tHyper E6 Hard-Case Lite, reflective, wire bead, 60tpi, 700x50c\nMax tire size\t700x50mm with or without fenders\n\nDrivetrain\nShifter\tShimano Deore M4100, 10 speed\nRear derailleur\tShimano Deore M5120, long cage\nCrank\tProWheel alloy, 170mm length\nChainring\tFSA, 42T, steel w/guard\nCassette\tShimano Deore M4100, 11-42, 10 speed\nChain\tKMC E10\nPedal\tHyper City pedals\n\nComponents\nSaddle\tHyper Boulevard\nSeatpost\tAlloy, suspension, 31.6mm, 300mm length\n*Handlebar\tSize: XS, S, M\nHyper alloy, 31.8mm, comfort sweep, 620mm width\nSize: L\nHyper alloy, 31.8mm, comfort sweep, 660mm width\nGrips\tHyper Satellite Elite, alloy lock-on\n*Stem\tSize: XS, S\nHyper alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 85mm length\nSize: M, L\nHyper alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 105mm length\nHeadset\tVP sealed cartridge, 1-1/8'', threaded\nBrake\tShimano MT200 hydraulic disc\n*Brake rotor\tSize: XS, S, M, L\nShimano RT26, 6-bolt,180mm\nSize: XS, S, M, L\nShimano RT26, 6-bolt,160mm\n\nAccessories\nBattery\tHyper PowerTube 500Wh\nCharger\tHyper compact 2A, 100-240V\nComputer\tHyper Control\nMotor\tHyperdrive Sport, 70Nm, 30mph\n*Light\tSize: XS, S, M, L\nSpanninga SOLO for e-bike, taillight\nSize: XS, S, M, L\nHerrmans MR8, 180 lumen, 60 lux, LED, headlight\nKickstand\tAdjustable length rear mount alloy kickstand\nCargo rack\tMIK-compatible alloy rear rack, maximum load 25 kg / 55 lbs\n*Fender\tSize: XS, S, M, L\nSKS wide\nSize: XS, S, M, L\nSKS plastic\n\nWeight\nWeight\tM - 22.30 kg / 49.17 lbs\nWeight limit\tThis bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| XS | 147 - 155 cm 4'10\" - 5'1\" | 69 - 73 cm 27\" - 29\" |\n| S | 155 - 165 cm 5'1\" - 5'5\" | 72 - 78 cm 28\" - 31\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\n\n| Frame size number | 40 cm | 45 cm | 50 cm | 55 cm |\n|---------------------------|-------|-------|-------|-------|\n| Frame size letter | XS | S | M | L |\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 39.0 | 44.0 | 50.0 | 55.0 |\n| B — Seat tube angle | 71.0° | 71.0° | 71.0° | 71.0° |\n| C — Head tube length | 16.0 | 16.0 | 18.0 | 20.0 |\n| D — Head angle | 68.2° | 68.2° | 68.2° | 68.2° |\n| E — Effective top tube | 58.2 | 58.7 | 59.8 | 61.0 |\n| F — Bottom bracket height | 29.4 | 29.4 | 29.4 | 29.4 |\n| G — Bottom bracket drop | 6.5 | 6.5 | 6.5 | 6.5 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 9.5 | 9.5 | 9.5 | 9.5 |\n| K — Wheelbase | 112.2 | 112.7 | 114.0 | 115.2 |\n| L — Standover | 43.3 | 43.3 | 43.3 | 43.3 |\n| M — Frame reach | 36.5 | 38.5 | 38.5 | 38.5 |\n| N — Frame stack | 63.0 | 63.0 | 64.9 | 66.8 |\n| Stem length | 8.5 | 9.0 | 9.0 | 11.0 |", "price": 1999.99, "tags": [ "bicycle", "city bike", "professional" ] }, { "name": "Horizon+ Evo Lowstep", "shortDescription": "The Horizon+ Evo Lowstep is a versatile electric hybrid bike designed for riders seeking a thrilling and efficient riding experience on a variety of terrains. With its powerful Bosch Performance Line Sport drive unit and integrated 500Wh battery, this e-bike enables riders to cover long distances with ease. Equipped with features prioritizing comfort and safety, such as a suspension seatpost, stable tires, and integrated lights, the Horizon+ Evo Lowstep is a reliable companion for everyday rides.", "description": "## Overview\n\nIt's right for you if...\nYou desire the convenience and speed of an e-bike to enhance your riding, and you want an intuitive and durable bicycle. You prioritize having one of the fastest motors developed by Bosch.\n\nThe tech you get\nA lightweight Alpha Smooth Aluminum frame with a lowstep geometry, a Bosch Performance Line Sport (250W, 65Nm) drive unit capable of sustaining speeds up to 28 mph, a fully encased 500Wh battery integrated into the frame, and a Bosch Purion controller. Additionally, it features a 10-speed Shimano drivetrain, hydraulic disc brakes for reliable stopping power in all weather conditions, a suspension seatpost, wide puncture-resistant tires for improved stability, ergonomic grips, a kickstand, lights, and a rack and fenders.\n\nThe final word\nThe Horizon+ Evo Lowstep offers an enjoyable and user-friendly riding experience for longer commutes, recreational rides, and adventures. It boasts an extended range battery, a high-performance Bosch motor, an intuitive controller, and a suspension seatpost for a smooth ride on various road surfaces.\n\n## Features\n\nSuper speedy assist\nExperience effortless cruising through errands, commutes, and joyrides with the new Bosch Performance Sport drive unit, allowing acceleration of up to 28 mph.\n\n## Specs\n\nFrameset\n- Frame: Alpha Platinum Aluminum, Removable Integrated Battery (RIB), smooth welds, rack & fender mounts, internal routing, kickstand mount, 135x5mm QR\n- Fork: Horizon Alloy, threaded steel steerer, rack mounts, post mount disc, 460mm axle-to-crown, ThruSkew 5mm QR\n- Max compatible fork travel: 50mm\n\nWheels\n- Front Hub: Formula DC-20, alloy, 6-bolt, 5x100mm QR\n- Front Skewer: 132x5mm QR, ThruSkew\n- Rear Hub: Formula DC-22, alloy, 6-bolt, Shimano 8/9/10 freehub, 135x5mm QR\n- Rear Skewer: 153x5mm bolt-on\n- Rim: Bontrager Connection, double-wall, 32-hole, 20mm width, Schrader valve\n- Tire: Bontrager E6 Hard-Case Lite, reflective, wire bead, 60tpi, 700x50c\n- Max tire size: 700x50mm with or without fenders\n\nDrivetrain\n- Shifter: Shimano Deore M4100, 10-speed\n- Rear Derailleur: Shimano Deore M5120, long cage\n- Crank: ProWheel alloy, 170mm length\n- Chainring: FSA, 42T, steel w/guard\n- Cassette: Shimano Deore M4100, 11-42, 10-speed\n- Chain: KMC E10\n- Pedal: Bontrager City pedals\n\nComponents\n- Saddle: Bontrager Boulevard\n- Seatpost: Alloy, suspension, 31.6mm, 300mm length\n- Handlebar:\n - Size: XS, S, M - Bontrager alloy, 31.8mm, comfort sweep, 620mm width\n - Size: L - Bontrager alloy, 31.8mm, comfort sweep, 660mm width\n- Grips: Bontrager Satellite Elite, alloy lock-on\n- Stem:\n - Size: XS, S - Bontrager alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 85mm length\n - Size: M, L - Bontrager alloy quill, 31.8mm clamp, adjustable rise, Blendr compatible, 105mm length\n- Headset: VP sealed cartridge, 1-1/8\", threaded\n- Brake: Shimano MT200 hydraulic disc\n- Brake rotor:\n - Size: XS, S, M, L - Shimano RT26, 6-bolt, 180mm\n - Size: XS, S, M, L - Shimano RT26, 6-bolt, 160mm\n\nAccessories\n- Battery: Bosch PowerTube 500Wh\n- Charger: Bosch compact 2A, 100-240V\n- Computer: Bosch Purion\n- Motor: Bosch Performance Line Sport, 65Nm, 28mph\n- Light:\n - Size: XS, S, M, L - Spanninga SOLO for e-bike, taillight\n - Size: XS, S, M, L - Herrmans MR8, 180 lumen, 60 lux, LED, headlight\n- Kickstand: Adjustable length rear mount alloy kickstand\n- Cargo rack: MIK-compatible alloy rear rack, maximum load 25 kg / 55 lbs\n- Fender:\n - Size: XS, S, M, L - SKS wide\n - Size: XS, S, M, L - SKS plastic\n\nWeight\n- Weight: M - 22.30 kg / 49.17 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| XS | 147 - 155 cm 4'10\" - 5'1\" | 69 - 73 cm 27\" - 29\" |\n| S | 155 - 165 cm 5'1\" - 5'5\" | 72 - 78 cm 28\" - 31\" |\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n\n## Geometry\n\nAll measurements provided in cm unless otherwise noted.\nSizing table\n| Frame size number | 40 cm | 45 cm | 50 cm | 55 cm |\n|---------------------------|-------|-------|-------|-------|\n| Frame size letter | XS | S | M | L |\n| Wheel size | 700c | 700c | 700c | 700c |\n| A — Seat tube | 39.0 | 44.0 | 50.0 | 55.0 |\n| B — Seat tube angle | 71.0° | 71.0° | 71.0° | 71.0° |\n| C — Head tube length | 16.0 | 16.0 | 18.0 | 20.0 |\n| D — Head angle | 68.2° | 68.2° | 68.2° | 68.2° |\n| E — Effective top tube | 58.2 | 58.7 | 59.8 | 61.0 |\n| F — Bottom bracket height | 29.4 | 29.4 | 29.4 | 29.4 |\n| G — Bottom bracket drop | 6.5 | 6.5 | 6.5 | 6.5 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 |\n| J — Trail | 9.5 | 9.5 | 9.5 | 9.5 |\n| K — Wheelbase | 112.2 | 112.7 | 114.0 | 115.2 |\n| L — Standover | 43.3 | 43.3 | 43.3 | 43.3 |\n| M — Frame reach | 36.5 | 38.5 | 38.5 | 38.5 |\n| N — Frame stack | 63.0 | 63.0 | 64.9 | 66.8 |\n| Stem length | 8.5 | 9.0 | 9.0 | 11.0 |", "price": 4499.99, "tags": [ "bicycle", "road bike", "professional" ] }, { "name": "FastRider X1", "shortDescription": "FastRider X1 is a high-performance e-bike designed for riders seeking speed and long-distance capabilities. Equipped with a powerful motor and a high-capacity battery, the FastRider X1 is perfect for daily commuters and e-bike enthusiasts. It boasts a sleek and functional design, making it a great alternative to car transportation. The bike also features a smartphone controller for easy navigation and entertainment options.", "description": "## Overview\nIt's right for you if...\nYou're looking for an e-bike that offers both speed and endurance. The FastRider X1 comes with a high-performance motor and a long-lasting battery, making it ideal for long-distance rides.\n\nThe tech you get\nThe FastRider X1 features a state-of-the-art motor and a spacious battery, ensuring a fast and efficient ride.\n\nThe final word\nWith the powerful motor and long-range battery, the FastRider X1 allows you to cover more distance at higher speeds.\n\n## Features\nConnect Your Ride with the FastRider App\nDownload the FastRider app and transform your smartphone into an on-board computer. Easily dock and charge your phone with the smartphone controller, and use the thumb pad on your handlebar to make calls, listen to music, get turn-by-turn directions, and more. The app also allows you to connect with fitness and health apps, syncing your routes and ride data.\n\nGoodbye, Car. Hello, Extended Range!\nWith the option to add the Range Boost feature, you can attach a second long-range battery to your FastRider X1, doubling the distance and time between charges. This enhancement allows you to ride longer, commute farther, and take on more adventurous routes.\n\nWhat is the range?\nTo estimate the distance you can travel on a single charge, use our range calculator tool. It automatically fills in the variables for this specific bike model and assumes an average rider, but you can adjust the settings to get the most accurate estimate for your needs.\n\n## Specifications\nFrameset\n- Frame: High-performance hydroformed alloy, Removable Integrated Battery, Range Boost-compatible, internal cable routing, Motor Armour, post-mount disc, 135x5 mm QR\n- Fork: FastRider rigid alloy fork, 1-1/8'' steel steerer, 100x15mm thru axle, post mount disc brake\n- Max compatible fork travel: 63mm\n\nWheels\n- Front Hub: FastRider sealed bearing, 32-hole 15mm alloy thru-axle\n- Front Skewer: FastRider Switch thru axle, removable lever\n- Rear Hub: FastRider alloy, sealed bearing, 6-bolt, 135x5mm QR\n- Rear Skewer: 148x5mm bolt-on\n- Rim: FastRider MD35, tubeless compatible, 32-hole, 35mm width, Presta valve\n- Spokes: Size: M, L, XL - 14g stainless steel, black\n- Tire: FastRider E6 Hard-Case Lite, reflective strip, 27.5x2.40''\n- Max tire size: 27.5x2.40\"\n\nDrivetrain\n- Shifter: Shimano Deore M4100, 10 speed\n- Rear derailleur: Size: M, L, XL - Shimano Deore M5120, long cage\n- Crank: Size: M - FastRider alloy, 170mm length / Size: L, XL - FastRider alloy, 175mm length\n- Chainring: FastRider 46T narrow/wide alloy, w/alloy guard\n- Cassette: Size: M, L, XL - Shimano Deore M4100, 11-42, 10 speed\n- Chain: Size: M, L, XL - KMC E10 / Size: M, L, XL - KMC X10e\n- Pedal: Size: M, L, XL - FastRider City pedals / Size: M, L, XL - Wellgo C157, boron axle, plastic body / Size: M, L, XL - slip-proof aluminum pedals with reflectors\n- Max chainring size: 1x: 48T\n\nComponents\n- Saddle: FastRider Commuter Comp\n- Seatpost: FastRider Comp, 6061 alloy, 31.6mm, 8mm offset, 330mm length\n- Handlebar: Size: M - FastRider alloy, 31.8mm, 15mm rise, 600mm width / Size: L, XL - FastRider alloy, 31.8mm, 15mm rise, 660mm width\n- Grips: FastRider Satellite Elite, alloy lock-on\n- Stem: Size: M - FastRider alloy, 31.8mm, Blendr compatible, 7-degree, 70mm length / Size: L - FastRider alloy, 31.8mm, Blendr compatible, 7-degree, 90mm length / Size: XL - FastRider alloy, 31.8mm, Blendr compatible, 7-degree, 100mm length\n- Headset: Size: M, L, XL - FSA IS-2 alloy, integrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom / Size: M, L, XL - FSA Integrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom\n- Brake: Shimano MT520 4-piston hydraulic disc, post-mount, 180mm rotor\n- Brake rotor: Shimano RT56, 6-bolt, 180mm\n- Rotor size: Max brake rotor sizes: 180mm front & rear\n\nAccessories\n- Battery: FastRider PowerTube 625Wh\n- Charger: FastRider standard 4A, 100-240V\n- Motor: FastRider Performance Speed, 85 Nm, 28 mph / 45 kph\n- Light: Size: M, L, XL - FastRider taillight, 50 lumens / Size: M, L, XL - FastRider headlight, 500 lumens\n- Kickstand: Size: M, L, XL - Rear mount, alloy / Size: M, L, XL - Adjustable length alloy kickstand\n- Cargo rack: FastRider integrated rear rack, aluminum\n- Fender: FastRider custom aluminum\n\nWeight\n- Weight: M - 25.54 kg / 56.3 lbs\n\nWeight limit\n- This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:------------------------:|:--------------------:|\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n| XL | 186 - 197 cm 6'1\" - 6'6\" | 87 - 93 cm 34\" - 37\" |\n\n## Geometry\n| Frame size letter | M | L | XL |\n|---------------------------|-------|-------|-------|\n| Wheel size | 27.5\" | 27.5\" | 27.5\" |\n| A — Seat tube | 44.6 | 49.1 | 53.4 |\n| B — Seat tube angle | 73.0° | 73.0° | 73.0° |\n| C — Head tube length | 16.5 | 19.5 | 23.0 |\n| D — Head angle | 69.5° | 70.0° | 70.5° |\n| E — Effective top tube | 59.5 | 60.7 | 62.2 |\n| F — Bottom bracket height | 29.5 | 29.5 | 29.5 |\n| G — Bottom bracket drop | 6.0 | 6.0 | 6.0 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.4 | 4.4 | 4.4 |\n| J — Trail | 8.6 | 8.1 | 7.9 |\n| K — Wheelbase | 114.6 | 115.0 | 116.4 |\n| L — Standover | 79.5 | 83.7 | 87.9 |\n| M — Frame reach | 40.5 | 40.8 | 41.2 |\n| N — Frame stack | 62.3 | 65.2 | 68.8 |", "price": 5499.99, "tags": [ "bicycle", "mountain bike", "professional" ] }, { "name": "SonicRide 8S", "shortDescription": "SonicRide 8S is a high-performance e-bike designed for riders who crave speed and long-distance capabilities. The advanced SonicDrive motor provides powerful assistance up to 28 mph, combined with a durable and long-lasting battery for extended rides. With its sleek design and thoughtful features, the SonicRide 8S is perfect for those who prefer the freedom of riding a bike over driving a car. Plus, it comes equipped with a smartphone controller for easy navigation, music, and more.", "description": "## Overview\nIt's right for you if...\nYou want a fast and efficient e-bike that can take you long distances. The SonicRide 8S features a hydroformed aluminum frame with a concealed 625Wh battery, a high-powered SonicDrive motor, and a Smartphone Controller. It also includes essential accessories such as lights, fenders, and a rear rack.\n\nThe tech you get\nThe SonicRide 8S is equipped with the fastest SonicDrive motor, ensuring exhilarating rides at high speeds. The long-range battery is perfect for commuters and riders looking to explore new horizons.\n\nThe final word\nWith the SonicDrive motor and long-lasting battery, you can enjoy extended rides at higher speeds.\n\n## Features\n\nConnect Your Ride with SonicRide App\nDownload the SonicRide app and transform your phone into an onboard computer. Simply attach it to the Smartphone Controller for docking and charging. Use the thumb pad on your handlebar to control calls, music, directions, and more. The Bluetooth® wireless technology allows you to connect with fitness and health apps, syncing your routes and ride data.\n\nSay Goodbye to Limited Range with Range Boost!\nExperience the convenience of Range Boost, an additional long-range 500Wh battery that seamlessly attaches to your bike's down tube. This upgrade allows you to double your distance and time between charges, enabling longer commutes and more adventurous rides. Range Boost is compatible with select SonicRide electric bike models.\n\nWhat is the range?\nFor an accurate estimate of how far you can ride on a single charge, use SonicRide's range calculator. We have pre-filled the variables for this specific bike model and the average rider, but you can adjust them to obtain the most accurate estimate.\n\n## Specifications\nFrameset\n- Frame: High-performance hydroformed alloy, Removable Integrated Battery, Range Boost-compatible, internal cable routing, Motor Armour, post-mount disc, 135x5 mm QR\n- Fork: SonicRide rigid alloy fork, 1-1/8'' steel steerer, 100x15mm thru axle, post mount disc brake\n- Max compatible fork travel: 63mm\n\nWheels\n- Front Hub: SonicRide sealed bearing, 32-hole 15mm alloy thru-axle\n- Front Skewer: SonicRide Switch thru axle, removable lever\n- Rear Hub: SonicRide alloy, sealed bearing, 6-bolt, 135x5mm QR\n- Rear Skewer: 148x5mm bolt-on\n- Rim: SonicRide MD35, tubeless compatible, 32-hole, 35mm width, Presta valve\n- Spokes: Size: M, L, XL - 14g stainless steel, black\n- Tire: SonicRide E6 Hard-Case Lite, reflective strip, 27.5x2.40''\n- Max tire size: 27.5x2.40\"\n\nDrivetrain\n- Shifter: Shimano Deore M4100, 10 speed\n- Rear Derailleur: Size: M, L, XL - Shimano Deore M5120, long cage\n- Crank: Size: M - SonicRide alloy, 170mm length; Size: L, XL - SonicRide alloy, 175mm length\n- Chainring: SonicRide 46T narrow/wide alloy, with alloy guard\n- Cassette: Size: M, L, XL - Shimano Deore M4100, 11-42, 10 speed\n- Chain: Size: M, L, XL - KMC E10; Size: M, L, XL - KMC X10e\n- Pedal: Size: M, L, XL - SonicRide City pedals; Size: M, L, XL - Wellgo C157, boron axle, plastic body; Size: M, L, XL - slip-proof aluminum pedals with reflectors\n- Max chainring size: 1x: 48T\n\nComponents\n- Saddle: SonicRide Commuter Comp\n- Seatpost: SonicRide Comp, 6061 alloy, 31.6mm, 8mm offset, 330mm length\n- Handlebar: Size: M - SonicRide alloy, 31.8mm, 15mm rise, 600mm width; Size: L, XL - SonicRide alloy, 31.8mm, 15mm rise, 660mm width\n- Grips: SonicRide Satellite Elite, alloy lock-on\n- Stem: Size: M - SonicRide alloy, 31.8mm, Blendr compatible, 7-degree, 70mm length; Size: L - SonicRide alloy, 31.8mm, Blendr compatible, 7-degree, 90mm length; Size: XL - SonicRide alloy, 31.8mm, Blendr compatible, 7-degree, 100mm length\n- Headset: Size: M, L, XL - SonicRide IS-2 alloy, integrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom; Size: M, L, XL - SonicRide Integrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom\n- Brake: Shimano MT520 4-piston hydraulic disc, post-mount, 180mm rotor\n- Brake rotor: Shimano RT56, 6-bolt, 180mm\n- Rotor size: Max brake rotor sizes: 180mm front & rear\n\nAccessories\n- Battery: SonicRide PowerTube 625Wh\n- Charger: SonicRide standard 4A, 100-240V\n- Motor: SonicRide Performance Speed, 85 Nm, 28 mph / 45 kph\n- Light: Size: M, L, XL - SonicRide Lync taillight, 50 lumens; Size: M, L, XL - SonicRide Lync headlight, 500 lumens\n- Kickstand: Size: M, L, XL - Rear mount, alloy; Size: M, L, XL - Adjustable length alloy kickstand\n- Cargo rack: SonicRide integrated rear rack, aluminum\n- Fender: SonicRide custom aluminum\n\nWeight\n- Weight: M - 25.54 kg / 56.3 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:------------------------:|:--------------------:|\n| M | 165 - 175 cm / 5'5\" - 5'9\" | 77 - 83 cm / 30\" - 33\" |\n| L | 175 - 186 cm / 5'9\" - 6'1\" | 82 - 88 cm / 32\" - 35\" |\n| XL | 186 - 197 cm / 6'1\" - 6'6\" | 87 - 93 cm / 34\" - 37\" |\n\n## Geometry\n| Frame size letter | M | L | XL |\n|---------------------------|-------|-------|-------|\n| Wheel size | 27.5\" | 27.5\" | 27.5\" |\n| A — Seat tube | 44.6 | 49.1 | 53.4 |\n| B — Seat tube angle | 73.0° | 73.0° | 73.0° |\n| C — Head tube length | 16.5 | 19.5 | 23.0 |\n| D — Head angle | 69.5° | 70.0° | 70.5° |\n| E — Effective top tube | 59.5 | 60.7 | 62.2 |\n| F — Bottom bracket height | 29.5 | 29.5 | 29.5 |\n| G — Bottom bracket drop | 6.0 | 6.0 | 6.0 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.4 | 4.4 | 4.4 |\n| J — Trail | 8.6 | 8.1 | 7.9 |\n| K — Wheelbase | 114.6 | 115.0 | 116.4 |\n| L — Standover | 79.5 | 83.7 | 87.9 |\n| M — Frame reach | 40.5 | 40.8 | 41.2 |", "price": 5999.99, "tags": [ "bicycle", "road bike", "professional" ] }, { "name": "SwiftVolt Pro", "shortDescription": "SwiftVolt Pro is a high-performance e-bike designed for riders seeking a thrilling and fast riding experience. Equipped with a powerful SwiftDrive motor that provides assistance up to 30 mph and a long-lasting battery, this bike is perfect for long-distance commuting and passionate e-bike enthusiasts. The sleek and innovative design features cater specifically to individuals who prioritize cycling over driving. Additionally, the bike is seamlessly integrated with your smartphone, allowing you to use it for navigation, music, and more.", "description": "## Overview\nThis bike is ideal for you if:\n- You desire a sleek and modern hydroformed aluminum frame that houses a 700Wh battery.\n- You want to maintain high speeds of up to 30 mph with the assistance of the SwiftDrive motor.\n- You appreciate the convenience of using your smartphone as a controller, which can be docked and charged on the handlebar.\n\n## Features\n\nConnect with SwiftSync App\nBy downloading the SwiftSync app, your smartphone becomes an interactive on-board computer. Attach it to the handlebar-mounted controller for easy access and charging. With the thumb pad, you can make calls, listen to music, receive turn-by-turn directions, and connect with fitness and health apps to track your routes and ride data via Bluetooth® wireless technology.\n\nEnhanced Range with BoostMax\nBoostMax offers the capability to attach a second 700Wh Swift battery to the downtube of your bike, effectively doubling the distance and time between charges. This allows for extended rides, longer commutes, and more significant adventures. BoostMax is compatible with select Swift electric bike models.\n\nRange Estimation\nFor an estimate of how far you can ride on a single charge, consult the Swift range calculator. The variables are automatically populated based on this bike model and the average rider, but you can modify them to obtain the most accurate estimate.\n\n## Specifications\nFrameset\n- Frame: Lightweight hydroformed alloy, Removable Integrated Battery, BoostMax-compatible, internal cable routing, post-mount disc, 135x5 mm QR\n- Fork: SwiftVolt rigid alloy fork, 1-1/8'' steel steerer, 100x15mm thru-axle, post-mount disc brake\n- Max compatible fork travel: 63mm\n\nWheels\n- Front Hub: Swift sealed bearing, 32-hole 15mm alloy thru-axle\n- Front Skewer: Swift Switch thru-axle, removable lever\n- Rear Hub: Swift alloy, sealed bearing, 6-bolt, 135x5mm QR\n- Rear Skewer: 148x5mm bolt-on\n- Rim: SwiftRim, tubeless compatible, 32-hole, 35mm width, Presta valve\n- Spokes: 14g stainless steel, black\n- Tire: Swift E6 Hard-Case Lite, reflective strip, 27.5x2.40''\n- Max tire size: 27.5x2.40\"\n\nDrivetrain\n- Shifter: Shimano Deore M4100, 10 speed\n- Rear Derailleur: Shimano Deore M5120, long cage\n- Crank: Swift alloy, 170mm length\n- Chainring: Swift 46T narrow/wide alloy, w/alloy guard\n- Cassette: Shimano Deore M4100, 11-42, 10 speed\n- Chain: KMC E10\n- Pedal: Swift City pedals\n- Max chainring size: 1x: 48T\n\nComponents\n- Saddle: Swift Commuter Comp\n- Seatpost: Swift Comp, 6061 alloy, 31.6mm, 8mm offset, 330mm length\n- Handlebar: Swift alloy, 31.8mm, 15mm rise, 600mm width (M), 660mm width (L, XL)\n- Grips: Swift Satellite Elite, alloy lock-on\n- Stem: Swift alloy, 31.8mm, Blendr compatible, 7 degree, 70mm length (M), 90mm length (L), 100mm length (XL)\n- Headset: FSA IS-2 alloy, integrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom\n- Brakes: Shimano MT520 4-piston hydraulic disc, post-mount, 180mm rotor\n- Brake Rotor: Shimano RT56, 6-bolt, 180mm\n- Rotor size: Max 180mm front & rear\n\nAccessories\n- Battery: Swift PowerTube 700Wh\n- Charger: Swift standard 4A, 100-240V\n- Motor: SwiftDrive, 90 Nm, 30 mph / 48 kph\n- Light: Swift Lync taillight, 50 lumens (M, L, XL), Swift Lync headlight, 500 lumens (M, L, XL)\n- Kickstand: Rear mount, alloy (M, L, XL), Adjustable length alloy kickstand (M, L, XL)\n- Cargo rack: SwiftVolt integrated rear rack, aluminum\n- Fender: Swift custom aluminum\n\nWeight\n- Weight: M - 25.54 kg / 56.3 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:---------------------:|:-------------:|\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n| XL | 186 - 197 cm 6'1\" - 6'6\" | 87 - 93 cm 34\" - 37\" |\n\n## Geometry\n| Frame size letter | M | L | XL |\n|---------------------------|-------|-------|-------|\n| Wheel size | 27.5\" | 27.5\" | 27.5\" |\n| A — Seat tube | 44.6 | 49.1 | 53.4 |\n| B — Seat tube angle | 73.0° | 73.0° | 73.0° |\n| C — Head tube length | 16.5 | 19.5 | 23.0 |\n| D — Head angle | 69.5° | 70.0° | 70.5° |\n| E — Effective top tube | 59.5 | 60.7 | 62.2 |\n| F — Bottom bracket height | 29.5 | 29.5 | 29.5 |\n| G — Bottom bracket drop | 6.0 | 6.0 | 6.0 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.4 | 4.4 | 4.4 |\n| J — Trail | 8.6 | 8.1 | 7.9 |\n| K — Wheelbase | 114.6 | 115.0 | 116.4 |\n| L — Standover | 79.5 | 83.7 | 87.9 |\n| M — Frame reach | 40.5 | 40.8 | 41.2 |\n| N — Frame stack | 62.3 | 65.2 | 68.8 |", "price": 2499.99, "tags": [ "bicycle", "city bike", "professional" ] }, { "name": "AgileEon 9X", "shortDescription": "AgileEon 9X is a high-performance e-bike designed for riders seeking speed and endurance. Equipped with a robust motor and an extended battery life, this bike is perfect for long-distance commuters and avid e-bike enthusiasts. It boasts innovative features tailored for individuals who prioritize cycling over driving. Additionally, the bike integrates seamlessly with your smartphone, allowing you to access navigation, music, and more.", "description": "## Overview\nIt's right for you if...\nYou crave speed and want to cover long distances efficiently. The AgileEon 9X features a sleek hydroformed aluminum frame that houses a powerful motor, along with a large-capacity battery for extended rides. It comes equipped with a 10-speed drivetrain, front and rear lighting, fenders, and a rear rack.\n\nThe tech you get\nDesigned for those constantly on the move, this bike includes a state-of-the-art motor and a high-capacity battery, making it an excellent choice for lengthy commutes.\n\nThe final word\nWith the AgileEon 9X, you can push your boundaries and explore new horizons thanks to its powerful motor and long-lasting battery.\n\n## Features\n\nConnect Your Ride with RideMate App\nMake use of the RideMate app to transform your smartphone into an onboard computer. Simply attach it to the RideMate controller to dock and charge, then utilize the thumb pad on your handlebar to make calls, listen to music, receive turn-by-turn directions, and more. The bike also supports Bluetooth® wireless technology, enabling seamless connectivity with fitness and health apps for route syncing and ride data.\n\nGoodbye, car. Hello, Extended Range!\nEnhance your riding experience with the Extended Range option, which allows for the attachment of an additional high-capacity 500Wh battery to your bike's downtube. This doubles the distance and time between charges, enabling longer rides, extended commutes, and more significant adventures. The Extended Range feature is compatible with select AgileEon electric bike models.\n\nWhat is the range?\nTo determine how far you can ride on a single charge, you can utilize the range calculator provided by AgileEon. We have pre-filled the variables for this specific model and an average rider, but adjustments can be made for a more accurate estimation.\n\n## Specifications\nFrameset\nFrame: High-performance hydroformed alloy, Removable Integrated Battery, Extended Range-compatible, internal cable routing, Motor Armor, post-mount disc, 135x5 mm QR\nFork: AgileEon rigid alloy fork, 1-1/8'' steel steerer, 100x15mm thru-axle, post-mount disc brake\nMax compatible fork travel: 63mm\n\nWheels\nFront Hub: AgileEon sealed bearing, 32-hole 15mm alloy thru-axle\nFront Skewer: AgileEon Switch thru-axle, removable lever\nRear Hub: AgileEon alloy, sealed bearing, 6-bolt, 135x5mm QR\nRear Skewer: 148x5mm bolt-on\nRim: AgileEon MD35, tubeless compatible, 32-hole, 35mm width, Presta valve\nSpokes:\n- Size: M, L, XL: 14g stainless steel, black\nTire: AgileEon E6 Hard-Case Lite, reflective strip, 27.5x2.40''\nMax tire size: 27.5x2.40\"\n\nDrivetrain\nShifter: Shimano Deore M4100, 10-speed\nRear derailleur:\n- Size: M, L, XL: Shimano Deore M5120, long cage\nCrank:\n- Size: M: AgileEon alloy, 170mm length\n- Size: L, XL: AgileEon alloy, 175mm length\nChainring: AgileEon 46T narrow/wide alloy, with alloy guard\nCassette:\n- Size: M, L, XL: Shimano Deore M4100, 11-42, 10-speed\nChain:\n- Size: M, L, XL: KMC E10\nPedal:\n- Size: M, L, XL: AgileEon City pedals\nMax chainring size: 1x: 48T\n\nComponents\nSaddle: AgileEon Commuter Comp\nSeatpost: AgileEon Comp, 6061 alloy, 31.6mm, 8mm offset, 330mm length\nHandlebar:\n- Size: M: AgileEon alloy, 31.8mm, 15mm rise, 600mm width\n- Size: L, XL: AgileEon alloy, 31.8mm, 15mm rise, 660mm width\nGrips: AgileEon Satellite Elite, alloy lock-on\nStem:\n- Size: M: AgileEon alloy, 31.8mm, Blendr compatible, 7-degree, 70mm length\n- Size: L: AgileEon alloy, 31.8mm, Blendr compatible, 7-degree, 90mm length\n- Size: XL: AgileEon alloy, 31.8mm, Blendr compatible, 7-degree, 100mm length\nHeadset:\n- Size: M, L, XL: AgileEon IS-2 alloy, integrated, sealed cartridge bearing, 1-1/8'' top, 1.5'' bottom\nBrake: Shimano MT520 4-piston hydraulic disc, post-mount, 180mm rotor\nBrake rotor: Shimano RT56, 6-bolt, 180mm\nRotor size: Max brake rotor sizes: 180mm front & rear\n\nAccessories\nBattery: AgileEon PowerTube 625Wh\nCharger: AgileEon standard 4A, 100-240V\nMotor: AgileEon Performance Speed, 85 Nm, 28 mph / 45 kph\nLight:\n- Size: M, L, XL: AgileEon taillight, 50 lumens\n- Size: M, L, XL: AgileEon headlight, 500 lumens\nKickstand:\n- Size: M, L, XL: Rear mount, alloy\n- Size: M, L, XL: Adjustable length alloy kickstand\nCargo rack: AgileEon integrated rear rack, aluminum\nFender: AgileEon custom aluminum\n\nWeight\nWeight: M - 25.54 kg / 56.3 lbs\nWeight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 300 pounds (136 kg).\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:------------------------:|:--------------------:|\n| M | 165 - 175 cm 5'5\" - 5'9\" | 77 - 83 cm 30\" - 33\" |\n| L | 175 - 186 cm 5'9\" - 6'1\" | 82 - 88 cm 32\" - 35\" |\n| XL | 186 - 197 cm 6'1\" - 6'6\" | 87 - 93 cm 34\" - 37\" |\n\n## Geometry\n| Frame size letter | M | L | XL |\n|---------------------------|-------|-------|-------|\n| Wheel size | 27.5\" | 27.5\" | 27.5\" |\n| A — Seat tube | 44.6 | 49.1 | 53.4 |\n| B — Seat tube angle | 73.0° | 73.0° | 73.0° |\n| C — Head tube length | 16.5 | 19.5 | 23.0 |\n| D — Head angle | 69.5° | 70.0° | 70.5° |\n| E — Effective top tube | 59.5 | 60.7 | 62.2 |\n| F — Bottom bracket height | 29.5 | 29.5 | 29.5 |\n| G — Bottom bracket drop | 6.0 | 6.0 | 6.0 |\n| H — Chainstay length | 48.7 | 48.7 | 48.7 |\n| I — Offset | 4.4 | 4.4 | 4.4 |\n| J — Trail | 8.6 | 8.1 | 7.9 |\n| K — Wheelbase | 114.6 | 115.0 | 116.4 |\n| L — Standover | 79.5 | 83.7 | 87.9 |\n| M — Frame reach | 40.5 | 40.8 | 41.2 |\n| N — Frame stack | 62.3 | 65.2 | 68.8 |", "price": 3499.99, "tags": [ "bicycle", "road bike", "professional" ] }, { "name": "Stealth R1X Pro", "shortDescription": "Stealth R1X Pro is a high-performance carbon road bike designed for riders who crave speed and exceptional handling. With its aerodynamic tube shaping, disc brakes, and lightweight carbon wheels, the Stealth R1X Pro offers unparalleled performance for competitive road cycling.", "description": "## Overview\nIt's right for you if...\nYou're a competitive cyclist looking for a road bike that offers superior performance in terms of speed, handling, and aerodynamics. You want a complete package that includes lightweight carbon wheels, without the need for future upgrades.\n\nThe tech you get\nThe Stealth R1X Pro features a lightweight and aerodynamic carbon frame, an advanced carbon fork, high-performance Shimano Ultegra 11-speed drivetrain, and powerful Ultegra disc brakes. The bike also comes equipped with cutting-edge Bontrager Aeolus Elite 35 carbon wheels.\n\nThe final word\nThe Stealth R1X Pro stands out with its combination of a fast and aerodynamic frame, high-end drivetrain, and top-of-the-line carbon wheels. Whether you're racing on local roads, participating in pro stage races, or engaging in hill climbing competitions, this bike is a formidable choice that delivers an exceptional riding experience.\n\n## Features\nSleek and aerodynamic design\nThe Stealth R1X Pro's aero tube shapes maximize speed and performance, making it faster on climbs and flats alike. The bike also features a streamlined Aeolus RSL bar/stem for improved front-end aerodynamics.\n\nDesigned for all riders\nThe Stealth R1X Pro is designed to provide an outstanding fit for riders of all genders, body types, riding styles, and abilities. It comes equipped with size-specific components to ensure a comfortable and efficient riding position for competitive riders.\n\n## Specifications\nFrameset\n- Frame: Ultralight carbon frame constructed with high-performance 500 Series ADV Carbon. It features Ride Tuned performance tube optimization, a tapered head tube, internal routing, DuoTrap S compatibility, flat mount disc brake mounts, and a 142x12mm thru axle.\n- Fork: Full carbon fork (Émonda SL) with a tapered carbon steerer, internal brake routing, flat mount disc brake mounts, and a 12x100mm thru axle.\n- Frame fit: H1.5 Race geometry.\n\nWheels\n- Front wheel: Bontrager Aeolus Elite 35 carbon wheel with a 35mm rim depth, ADV Carbon construction, Tubeless Ready compatibility, and a 100x12mm thru axle.\n- Rear wheel: Bontrager Aeolus Elite 35 carbon wheel with a 35mm rim depth, ADV Carbon construction, Tubeless Ready compatibility, Shimano 11/12-speed freehub, and a 142x12mm thru axle.\n- Front skewer: Bontrager Switch thru axle with a removable lever.\n- Rear skewer: Bontrager Switch thru axle with a removable lever.\n- Tire: Bontrager R2 Hard-Case Lite with an aramid bead, 60 tpi, and a size of 700x25c.\n- Maximum tire size: 28mm.\n\nDrivetrain\n- Shifter:\n - Size 47, 50, 52: Shimano Ultegra R8025 with short-reach levers, 11-speed.\n - Size 54, 56, 58, 60, 62: Shimano Ultegra R8020, 11-speed.\n- Front derailleur: Shimano Ultegra R8000, braze-on.\n- Rear derailleur: Shimano Ultegra R8000, short cage, with a maximum cog size of 30T.\n- Crank:\n - Size 47: Shimano Ultegra R8000 with 52/36 chainrings and a 165mm length.\n - Size 50, 52: Shimano Ultegra R8000 with 52/36 chainrings and a 170mm length.\n - Size 54, 56, 58: Shimano Ultegra R8000 with 52/36 chainrings and a 172.5mm length.\n - Size 60, 62: Shimano Ultegra R8000 with 52/36 chainrings and a 175mm length.\n- Bottom bracket: Praxis T47 threaded bottom bracket with internal bearings.\n- Cassette: Shimano Ultegra R8000, 11-30, 11-speed.\n- Chain: Shimano Ultegra HG701, 11-speed.\n- Maximum chainring size: 1x - 50T, 2x - 53/39.\n\nComponents\n- Saddle: Bontrager Aeolus Comp with steel rails and a width of 145mm.\n- Seatpost:\n - Size 47, 50, 52, 54: Bontrager carbon seatmast cap with a 20mm offset and a short length.\n - Size 56, 58, 60, 62: Bontrager carbon seatmast cap with a 20mm offset and a tall length.\n- Handlebar:\n - Size 47, 50: Bontrager Elite VR-C alloy handlebar with a 31.8mm clamp, 100mm reach, 124mm drop, and a width of 38cm.\n - Size 52: Bontrager Elite VR-C alloy handlebar with a 31.8mm clamp, 100mm reach, 124mm drop, and a width of 40cm.\n - Size 54, 56, 58: Bontrager Elite VR-C alloy handlebar with a 31.8mm clamp, 100mm reach, 124mm drop, and a width of 42cm.\n - Size 60, 62: Bontrager Elite VR-C alloy handlebar with a 31.8mm clamp, 100mm reach, 124mm drop, and a width of 44cm.\n- Handlebar tape: Bontrager Supertack Perf tape.\n- Stem:\n - Size 47: Bontrager Pro alloy stem with a 31.8mm clamp, Blendr compatibility, 7-degree rise, and a length of 70mm.\n - Size 50: Bontrager Pro alloy stem with a 31.8mm clamp, Blendr compatibility, 7-degree rise, and a length of 80mm.\n - Size 52, 54: Bontrager Pro alloy stem with a 31.8mm clamp, Blendr compatibility, 7-degree rise, and a length of 90mm.\n - Size 56: Bontrager Pro alloy stem with a 31.8mm clamp, Blendr compatibility, 7-degree rise, and a length of 100mm.\n - Size 58, 60, 62: Bontrager Pro alloy stem with a 31.8mm clamp, Blendr compatibility, 7-degree rise, and a length of 110mm.\n- Brake: Shimano Ultegra hydraulic disc brakes with flat mount calipers.\n- Brake rotor: Shimano RT800 with centerlock mounting, 160mm diameter.\n\nWeight\n- Weight: 8.03 kg (17.71 lbs) for the 56cm frame.\n- Weight limit: The bike has a maximum total weight limit (combined weight of the bicycle, rider, and cargo) of 275 pounds (125 kg).\n\n## Sizing\nPlease refer to the table below for the corresponding Stealth R1X Pro frame sizes, recommended rider height range, and inseam measurements:\n\n| Size | Rider Height | Inseam |\n|:----:|:---------------------:|:--------------:|\n| 47 | 152 - 158 cm (5'0\") | 71 - 75 cm |\n| 50 | 158 - 163 cm (5'2\") | 74 - 77 cm |\n| 52 | 163 - 168 cm (5'4\") | 76 - 79 cm |\n| 54 | 168 - 174 cm (5'6\") | 78 - 82 cm |\n| 56 | 174 - 180 cm (5'9\") | 81 - 85 cm |\n| 58 | 180 - 185 cm (5'11\") | 84 - 87 cm |\n| 60 | 185 - 190 cm (6'1\") | 86 - 90 cm |\n| 62 | 190 - 195 cm (6'3\") | 89 - 92 cm |\n\n## Geometry\nThe table below provides the geometry measurements for each frame size of the Stealth R1X Pro:\n\n| Frame size number | 47 cm | 50 cm | 52 cm | 54 cm | 56 cm | 58 cm | 60 cm | 62 cm |\n|-------------------------------|-------|-------|-------|-------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c | 700c | 700c | 700c | 700c |\n| A — Seat tube | 42.4 | 45.3 | 48.3 | 49.6 | 52.5 | 55.3 | 57.3 | 59.3 |\n| B — Seat tube angle | 74.6° | 74.6° | 74.2° | 73.7° | 73.3° | 73.0° | 72.8° | 72.5° |\n| C — Head tube length | 10.0 | 11.1 | 12.1 | 13.1 | 15.1 | 17.1 | 19.1 | 21.1 |\n| D — Head angle | 72.1° | 72.1° | 72.8° | 73.0° | 73.5° | 73.8° | 73.9° | 73.9° |\n| E — Effective top tube | 51.2 | 52.1 | 53.4 | 54.3 | 55.9 | 57.4 | 58.6 | 59.8 |\n| G — Bottom bracket drop | 7.2 | 7.2 | 7.2 | 7.0 | 7.0 | 6.8 | 6.8 | 6.8 |\n| H — Chainstay length | 41.0 | 41.0 | 41.0 | 41.0 | 41.0 | 41.1 | 41.1 | 41.2 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 | 4.0 | 4.0 | 4.0 | 4.0 |\n| J — Trail | 6.8 | 6.2 | 5.8 | 5.6 | 5.8 | 5.7 | 5.6 | 5.6 |\n| K — Wheelbase | 97.2 | 97.4 | 97.7 | 98.1 | 98.3 | 99.2 | 100.1 | 101.0 |\n| L — Standover | 69.2 | 71.1 | 73.2 | 74.4 | 76.8 | 79.3 | 81.1 | 82.9 |\n| M — Frame reach | 37.3 | 37.8 | 38.3 | 38.6 | 39.1 | 39.6 | 39.9 | 40.3 |\n| N — Frame stack | 50.7 | 52.1 | 53.3 | 54.1 | 56.3 | 58.1 | 60.1 | 62.0 |\n| Saddle rail height min (short mast) | 55.5 | 58.5 | 61.5 | 64.0 | 67.0 | 69.0 | 71.0 | 73.0 |\n| Saddle rail height max (short mast) | 61.5 | 64.5 | 67.5 | 70.0 | 73.0 | 75.0 | 77.0 | 79.0 |\n| Saddle rail height min (tall mast) | 59.0 | 62.0 | 65.0 | 67.5 | 70.5 | 72.5 | 74.5 | 76.5 |\n| Saddle rail height max (tall mast) | 65.0 | 68.0 | 71.0 | 73.5 | 76.5 | 78.5 | 80.5 | 82.5 |", "price": 2999.99, "tags": [ "bicycle", "mountain bike", "professional" ] }, { "name": "Avant SLR 6 Disc Pro", "shortDescription": "Avant SLR 6 Disc Pro is a high-performance carbon road bike designed for riders who prioritize speed and handling. With its aero tube shaping, disc brakes, and lightweight carbon wheels, it offers the perfect balance of speed and control.", "description": "## Overview\nIt's right for you if...\nYou're a rider who values exceptional performance on fast group rides and races, and you want a complete package that includes lightweight carbon wheels. The Avant SLR 6 Disc Pro is designed to provide the speed and aerodynamics you need to excel on any road.\n\nThe tech you get\nThe Avant SLR 6 Disc Pro features a lightweight 500 Series ADV Carbon frame and fork, Bontrager Aeolus Elite 35 carbon wheels, a full Shimano Ultegra 11-speed drivetrain, and powerful Ultegra disc brakes.\n\nThe final word\nThe standout feature of this bike is the combination of its aero frame, high-performance drivetrain, and top-quality carbon wheels. Whether you're racing, tackling challenging climbs, or participating in professional stage races, the Avant SLR 6 Disc Pro is a worthy choice that will enhance your performance.\n\n## Features\nAll-new aero design\nThe Avant SLR 6 Disc Pro features innovative aero tube shapes that provide an advantage in all riding conditions, whether it's climbing or riding on flat roads. Additionally, it is equipped with a sleek new Aeolus RSL bar/stem that enhances front-end aero performance.\n\nAwesome bikes for everyone\nThe Avant SLR 6 Disc Pro is designed with the belief that every rider, regardless of gender, body type, riding style, or ability, deserves a great bike. It is equipped with size-specific components that ensure a perfect fit for competitive riders of all genders.\n\n## Specifications\nFrameset\n- Frame: Ultralight 500 Series ADV Carbon, Ride Tuned performance tube optimization, tapered head tube, internal routing, DuoTrap S compatible, flat mount disc, 142x12mm thru axle\n- Fork: Avant SL full carbon, tapered carbon steerer, internal brake routing, flat mount disc, 12x100mm thru axle\n- Frame fit: H1.5 Race\n\nWheels\n- Front wheel: Bontrager Aeolus Elite 35, ADV Carbon, Tubeless Ready, 35mm rim depth, 100x12mm thru axle\n- Rear wheel: Bontrager Aeolus Elite 35, ADV Carbon, Tubeless Ready, 35mm rim depth, Shimano 11/12-speed freehub, 142x12mm thru axle\n- Front skewer: Bontrager Switch thru axle, removable lever\n- Rear skewer: Bontrager Switch thru axle, removable lever\n- Tire: Bontrager R2 Hard-Case Lite, aramid bead, 60 tpi, 700x25c\n- Max tire size: 28mm\n\nDrivetrain\n- Shifter: \n - Size 47, 50, 52: Shimano Ultegra R8025, short-reach lever, 11-speed\n - Size 54, 56, 58, 60, 62: Shimano Ultegra R8020, 11-speed\n- Front derailleur: Shimano Ultegra R8000, braze-on\n- Rear derailleur: Shimano Ultegra R8000, short cage, 30T max cog\n- Crank: \n - Size 47: Shimano Ultegra R8000, 52/36, 165mm length\n - Size 50, 52: Shimano Ultegra R8000, 52/36, 170mm length\n - Size 54, 56, 58: Shimano Ultegra R8000, 52/36, 172.5mm length\n - Size 60, 62: Shimano Ultegra R8000, 52/36, 175mm length\n- Bottom bracket: Praxis, T47 threaded, internal bearing\n- Cassette: Shimano Ultegra R8000, 11-30, 11-speed\n- Chain: Shimano Ultegra HG701, 11-speed\n- Max chainring size: 1x: 50T, 2x: 53/39\n\nComponents\n- Saddle: Bontrager Aeolus Comp, steel rails, 145mm width\n- Seatpost: \n - Size 47, 50, 52, 54: Bontrager carbon seatmast cap, 20mm offset, short length\n - Size 56, 58, 60, 62: Bontrager carbon seatmast cap, 20mm offset, tall length\n- Handlebar: \n - Size 47, 50: Bontrager Elite VR-C, alloy, 31.8mm, 100mm reach, 124mm drop, 38cm width\n - Size 52: Bontrager Elite VR-C, alloy, 31.8mm, 100mm reach, 124mm drop, 40cm width\n - Size 54, 56, 58: Bontrager Elite VR-C, alloy, 31.8mm, 100mm reach, 124mm drop, 42cm width\n - Size 60, 62: Bontrager Elite VR-C, alloy, 31.8mm, 100mm reach, 124mm drop, 44cm width\n- Handlebar tape: Bontrager Supertack Perf tape\n- Stem: \n - Size 47: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 70mm length\n - Size 50: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 80mm length\n - Size 52, 54: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 90mm length\n - Size 56: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 100mm length\n - Size 58, 60, 62: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 110mm length\n- Brake: Shimano Ultegra hydraulic disc, flat mount\n- Brake rotor: Shimano RT800, centerlock, 160mm\n\nWeight\n- Weight: 56 - 8.03 kg / 17.71 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 275 pounds (125 kg).\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| 47 | 152 - 158 cm 5'0\" - 5'2\" | 71 - 75 cm 28\" - 30\" |\n| 50 | 158 - 163 cm 5'2\" - 5'4\" | 74 - 77 cm 29\" - 30\" |\n| 52 | 163 - 168 cm 5'4\" - 5'6\" | 76 - 79 cm 30\" - 31\" |\n| 54 | 168 - 174 cm 5'6\" - 5'9\" | 78 - 82 cm 31\" - 32\" |\n| 56 | 174 - 180 cm 5'9\" - 5'11\" | 81 - 85 cm 32\" - 33\" |\n| 58 | 180 - 185 cm 5'11\" - 6'1\" | 84 - 87 cm 33\" - 34\" |\n| 60 | 185 - 190 cm 6'1\" - 6'3\" | 86 - 90 cm 34\" - 35\" |\n| 62 | 190 - 195 cm 6'3\" - 6'5\" | 89 - 92 cm 35\" - 36\" |\n\n## Geometry\n| Frame size number | 47 cm | 50 cm | 52 cm | 54 cm | 56 cm | 58 cm | 60 cm | 62 cm |\n|---------------------------------------|-------|-------|-------|-------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c | 700c | 700c | 700c | 700c |\n| A — Seat tube | 42.4 | 45.3 | 48.3 | 49.6 | 52.5 | 55.3 | 57.3 | 59.3 |\n| B — Seat tube angle | 74.6° | 74.6° | 74.2° | 73.7° | 73.3° | 73.0° | 72.8° | 72.5° |\n| C — Head tube length | 10.0 | 11.1 | 12.1 | 13.1 | 15.1 | 17.1 | 19.1 | 21.1 |\n| D — Head angle | 72.1° | 72.1° | 72.8° | 73.0° | 73.5° | 73.8° | 73.9° | 73.9° |\n| E — Effective top tube | 51.2 | 52.1 | 53.4 | 54.3 | 55.9 | 57.4 | 58.6 | 59.8 |\n| G — Bottom bracket drop | 7.2 | 7.2 | 7.2 | 7.0 | 7.0 | 6.8 | 6.8 | 6.8 |\n| H — Chainstay length | 41.0 | 41.0 | 41.0 | 41.0 | 41.0 | 41.1 | 41.1 | 41.2 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 | 4.0 | 4.0 | 4.0 | 4.0 |\n| J — Trail | 6.8 | 6.2 | 5.8 | 5.6 | 5.8 | 5.7 | 5.6 | 5.6 |\n| K — Wheelbase | 97.2 | 97.4 | 97.7 | 98.1 | 98.3 | 99.2 | 100.1 | 101.0 |\n| L — Standover | 69.2 | 71.1 | 73.2 | 74.4 | 76.8 | 79.3 | 81.1 | 82.9 |\n| M — Frame reach | 37.3 | 37.8 | 38.3 | 38.6 | 39.1 | 39.6 | 39.9 | 40.3 |\n| N — Frame stack | 50.7 | 52.1 | 53.3 | 54.1 | 56.3 | 58.1 | 60.1 | 62.0 |\n| Saddle rail height min (w/short mast) | 55.5 | 58.5 | 61.5 | 64.0 | 67.0 | 69.0 | 71.0 | 73.0 |\n| Saddle rail height max (w/short mast) | 61.5 | 64.5 | 67.5 | 70.0 | 73.0 | 75.0 | 77.0 | 79.0 |\n| Saddle rail height min (w/tall mast) | 59.0 | 62.0 | 65.0 | 67.5 | 70.5 | 72.5 | 74.5 | 76.5 |\n| Saddle rail height max (w/tall mast) | 65.0 | 68.0 | 71.0 | 73.5 | 76.5 | 78.5 | 80.5 | 82.5 |", "price": 999.99, "tags": [ "bicycle", "city bike", "professional" ] } ] --- ### Spring Ai Commons/Src/Test/Resources/Events.Json (spring-ai-commons/src/test/resources/events.json) [ { "sessions": [ { "description": "Session one" }, { "description": "Session two" }, { "description": "Session three" } ] } ] --- ### Spring Ai Commons/Src/Test/Resources/Person.Json (spring-ai-commons/src/test/resources/person.json) { "name": "Avant SLR 6 Disc Pro", "shortDescription": "Avant SLR 6 Disc Pro is a high-performance carbon road bike designed for riders who prioritize speed and handling. With its aero tube shaping, disc brakes, and lightweight carbon wheels, it offers the perfect balance of speed and control.", "description": "## Overview\nIt's right for you if...\nYou're a rider who values exceptional performance on fast group rides and races, and you want a complete package that includes lightweight carbon wheels. The Avant SLR 6 Disc Pro is designed to provide the speed and aerodynamics you need to excel on any road.\n\nThe tech you get\nThe Avant SLR 6 Disc Pro features a lightweight 500 Series ADV Carbon frame and fork, Bontrager Aeolus Elite 35 carbon wheels, a full Shimano Ultegra 11-speed drivetrain, and powerful Ultegra disc brakes.\n\nThe final word\nThe standout feature of this bike is the combination of its aero frame, high-performance drivetrain, and top-quality carbon wheels. Whether you're racing, tackling challenging climbs, or participating in professional stage races, the Avant SLR 6 Disc Pro is a worthy choice that will enhance your performance.\n\n## Features\nAll-new aero design\nThe Avant SLR 6 Disc Pro features innovative aero tube shapes that provide an advantage in all riding conditions, whether it's climbing or riding on flat roads. Additionally, it is equipped with a sleek new Aeolus RSL bar/stem that enhances front-end aero performance.\n\nAwesome bikes for everyone\nThe Avant SLR 6 Disc Pro is designed with the belief that every rider, regardless of gender, body type, riding style, or ability, deserves a great bike. It is equipped with size-specific components that ensure a perfect fit for competitive riders of all genders.\n\n## Specifications\nFrameset\n- Frame: Ultralight 500 Series ADV Carbon, Ride Tuned performance tube optimization, tapered head tube, internal routing, DuoTrap S compatible, flat mount disc, 142x12mm thru axle\n- Fork: Avant SL full carbon, tapered carbon steerer, internal brake routing, flat mount disc, 12x100mm thru axle\n- Frame fit: H1.5 Race\n\nWheels\n- Front wheel: Bontrager Aeolus Elite 35, ADV Carbon, Tubeless Ready, 35mm rim depth, 100x12mm thru axle\n- Rear wheel: Bontrager Aeolus Elite 35, ADV Carbon, Tubeless Ready, 35mm rim depth, Shimano 11/12-speed freehub, 142x12mm thru axle\n- Front skewer: Bontrager Switch thru axle, removable lever\n- Rear skewer: Bontrager Switch thru axle, removable lever\n- Tire: Bontrager R2 Hard-Case Lite, aramid bead, 60 tpi, 700x25c\n- Max tire size: 28mm\n\nDrivetrain\n- Shifter: \n - Size 47, 50, 52: Shimano Ultegra R8025, short-reach lever, 11-speed\n - Size 54, 56, 58, 60, 62: Shimano Ultegra R8020, 11-speed\n- Front derailleur: Shimano Ultegra R8000, braze-on\n- Rear derailleur: Shimano Ultegra R8000, short cage, 30T max cog\n- Crank: \n - Size 47: Shimano Ultegra R8000, 52/36, 165mm length\n - Size 50, 52: Shimano Ultegra R8000, 52/36, 170mm length\n - Size 54, 56, 58: Shimano Ultegra R8000, 52/36, 172.5mm length\n - Size 60, 62: Shimano Ultegra R8000, 52/36, 175mm length\n- Bottom bracket: Praxis, T47 threaded, internal bearing\n- Cassette: Shimano Ultegra R8000, 11-30, 11-speed\n- Chain: Shimano Ultegra HG701, 11-speed\n- Max chainring size: 1x: 50T, 2x: 53/39\n\nComponents\n- Saddle: Bontrager Aeolus Comp, steel rails, 145mm width\n- Seatpost: \n - Size 47, 50, 52, 54: Bontrager carbon seatmast cap, 20mm offset, short length\n - Size 56, 58, 60, 62: Bontrager carbon seatmast cap, 20mm offset, tall length\n- Handlebar: \n - Size 47, 50: Bontrager Elite VR-C, alloy, 31.8mm, 100mm reach, 124mm drop, 38cm width\n - Size 52: Bontrager Elite VR-C, alloy, 31.8mm, 100mm reach, 124mm drop, 40cm width\n - Size 54, 56, 58: Bontrager Elite VR-C, alloy, 31.8mm, 100mm reach, 124mm drop, 42cm width\n - Size 60, 62: Bontrager Elite VR-C, alloy, 31.8mm, 100mm reach, 124mm drop, 44cm width\n- Handlebar tape: Bontrager Supertack Perf tape\n- Stem: \n - Size 47: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 70mm length\n - Size 50: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 80mm length\n - Size 52, 54: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 90mm length\n - Size 56: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 100mm length\n - Size 58, 60, 62: Bontrager Pro, 31.8mm, Blendr compatible, 7-degree, 110mm length\n- Brake: Shimano Ultegra hydraulic disc, flat mount\n- Brake rotor: Shimano RT800, centerlock, 160mm\n\nWeight\n- Weight: 56 - 8.03 kg / 17.71 lbs\n- Weight limit: This bike has a maximum total weight limit (combined weight of bicycle, rider, and cargo) of 275 pounds (125 kg).\n\n## Sizing\n| Size | Rider Height | Inseam |\n|:----:|:-------------------------:|:--------------------:|\n| 47 | 152 - 158 cm 5'0\" - 5'2\" | 71 - 75 cm 28\" - 30\" |\n| 50 | 158 - 163 cm 5'2\" - 5'4\" | 74 - 77 cm 29\" - 30\" |\n| 52 | 163 - 168 cm 5'4\" - 5'6\" | 76 - 79 cm 30\" - 31\" |\n| 54 | 168 - 174 cm 5'6\" - 5'9\" | 78 - 82 cm 31\" - 32\" |\n| 56 | 174 - 180 cm 5'9\" - 5'11\" | 81 - 85 cm 32\" - 33\" |\n| 58 | 180 - 185 cm 5'11\" - 6'1\" | 84 - 87 cm 33\" - 34\" |\n| 60 | 185 - 190 cm 6'1\" - 6'3\" | 86 - 90 cm 34\" - 35\" |\n| 62 | 190 - 195 cm 6'3\" - 6'5\" | 89 - 92 cm 35\" - 36\" |\n\n## Geometry\n| Frame size number | 47 cm | 50 cm | 52 cm | 54 cm | 56 cm | 58 cm | 60 cm | 62 cm |\n|---------------------------------------|-------|-------|-------|-------|-------|-------|-------|-------|\n| Wheel size | 700c | 700c | 700c | 700c | 700c | 700c | 700c | 700c |\n| A — Seat tube | 42.4 | 45.3 | 48.3 | 49.6 | 52.5 | 55.3 | 57.3 | 59.3 |\n| B — Seat tube angle | 74.6° | 74.6° | 74.2° | 73.7° | 73.3° | 73.0° | 72.8° | 72.5° |\n| C — Head tube length | 10.0 | 11.1 | 12.1 | 13.1 | 15.1 | 17.1 | 19.1 | 21.1 |\n| D — Head angle | 72.1° | 72.1° | 72.8° | 73.0° | 73.5° | 73.8° | 73.9° | 73.9° |\n| E — Effective top tube | 51.2 | 52.1 | 53.4 | 54.3 | 55.9 | 57.4 | 58.6 | 59.8 |\n| G — Bottom bracket drop | 7.2 | 7.2 | 7.2 | 7.0 | 7.0 | 6.8 | 6.8 | 6.8 |\n| H — Chainstay length | 41.0 | 41.0 | 41.0 | 41.0 | 41.0 | 41.1 | 41.1 | 41.2 |\n| I — Offset | 4.5 | 4.5 | 4.5 | 4.5 | 4.0 | 4.0 | 4.0 | 4.0 |\n| J — Trail | 6.8 | 6.2 | 5.8 | 5.6 | 5.8 | 5.7 | 5.6 | 5.6 |\n| K — Wheelbase | 97.2 | 97.4 | 97.7 | 98.1 | 98.3 | 99.2 | 100.1 | 101.0 |\n| L — Standover | 69.2 | 71.1 | 73.2 | 74.4 | 76.8 | 79.3 | 81.1 | 82.9 |\n| M — Frame reach | 37.3 | 37.8 | 38.3 | 38.6 | 39.1 | 39.6 | 39.9 | 40.3 |\n| N — Frame stack | 50.7 | 52.1 | 53.3 | 54.1 | 56.3 | 58.1 | 60.1 | 62.0 |\n| Saddle rail height min (w/short mast) | 55.5 | 58.5 | 61.5 | 64.0 | 67.0 | 69.0 | 71.0 | 73.0 |\n| Saddle rail height max (w/short mast) | 61.5 | 64.5 | 67.5 | 70.0 | 73.0 | 75.0 | 77.0 | 79.0 |\n| Saddle rail height min (w/tall mast) | 59.0 | 62.0 | 65.0 | 67.5 | 70.5 | 72.5 | 74.5 | 76.5 |\n| Saddle rail height max (w/tall mast) | 65.0 | 68.0 | 71.0 | 73.5 | 76.5 | 78.5 | 80.5 | 82.5 |", "price": 999.99, "tags": [ "bicycle", "city bike", "professional" ], "store": { "name": "Bike Shop", "location": { "city": "San Francisco", "state": "CA", "address": { "street": "123 Market St", "zipcode": "94103" } }, "products": [ { "name": "Avant SLR 6 Disc Pro", "price": 999.99, "tags": [ "bicycle", "city bike", "professional" ], "details": { "weight": "7.5kg", "color": "red" } }, { "name": "Mountain Master 3000", "price": 1299.99, "tags": [ "bicycle", "mountain bike", "professional" ], "details": { "weight": "9kg", "color": "blue" } } ] }, "employees": [ { "name": "John Doe", "role": "Manager" }, { "name": "Jane Smith", "role": "Sales" } ] } --- ### Spring Ai Commons/Src/Test/Resources/Text Source (spring-ai-commons/src/test/resources/text_source.txt) Spring Framework Documentation Version 6.0.0 Chapter 1. Spring Framework Overview Spring makes it easy to create Java enterprise applications. It provides everything you need to embrace the Java language in an enterprise environment, with support for Groovy and Kotlin as alternative languages on the JVM, and with the flexibility to create many kinds of architectures depending on an application’s needs. As of Spring Framework 5.1, Spring requires JDK 8+ (Java SE 8+) and provides out-of-the-box support for JDK 11 LTS. Java SE 8 update 60 is suggested as the minimum patch release for Java 8, but it is generally recommended to use a recent patch release. Spring supports a wide range of application scenarios. In a large enterprise, applications often exist for a long time and have to run on a JDK and application server whose upgrade cycle is beyond developer control. Others may run as a single jar with the server embedded, possibly in a cloud environment. Yet others may be standalone applications (such as batch or integration workloads) that do not need a server. Spring is open source. It has a large and active community that provides continuous feedback based on a diverse range of real-world use cases. This has helped Spring to successfully evolve over a very long time. 1.1. What We Mean by "Spring" The term "Spring" means different things in different contexts. It can be used to refer to the Spring Framework project itself, which is where it all started. Over time, other Spring projects have been built on top of the Spring Framework. Most often, when people say "Spring", they mean the entire family of projects. This reference documentation focuses on the foundation: the Spring Framework itself. The Spring Framework is divided into modules. Applications can choose which modules they need. At the heart are the modules of the core container, including a configuration model and a dependency injection mechanism. Beyond that, the Spring Framework provides foundational support for different application architectures, including messaging, transactional data and persistence, and web. It also includes the Servlet-based Spring MVC web framework and, in parallel, the Spring WebFlux reactive web framework. A note about modules: Spring’s framework jars allow for deployment to JDK 9’s module path ("Jigsaw"). For use in Jigsaw-enabled applications, the Spring Framework 5 jars come with "Automatic-Module-Name" manifest entries which define stable language-level module names ("spring.core", "spring.context", etc.) independent from jar artifact names (the jars follow the same naming pattern with "-" instead of ".", e.g. "spring-core" and "spring-context"). Of course, Spring’s framework jars keep working fine on the classpath on both JDK 8 and 9+. 1.2. History of Spring and the Spring Framework Spring came into being in 2003 as a response to the complexity of the early J2EE specifications. While some consider Java EE and its modern-day successor Jakarta EE to be in competition with Spring, they are in fact complementary. The Spring programming model does not embrace the Jakarta EE platform specification; rather, it integrates with carefully selected individual specifications from the traditional EE umbrella: • Servlet API (JSR 340) • WebSocket API (JSR 356) • Concurrency Utilities (JSR 236) • JSON Binding API (JSR 367) • Bean Validation (JSR 303) • JPA (JSR 338) • JMS (JSR 914) • as well as JTA/JCA setups for transaction coordination, if necessary. The Spring Framework also supports the Dependency Injection (JSR 330) and Common Annotations (JSR 250) specifications, which application developers may choose to use instead of the Spring- specific mechanisms provided by the Spring Framework. Originally, those were based on common javax packages. As of Spring Framework 6.0, Spring has been upgraded to the Jakarta EE 9 level (e.g. Servlet 5.0+, JPA 3.0+), based on the jakarta namespace instead of the traditional javax packages. With EE 9 as the minimum and EE 10 supported already, Spring is prepared to provide out-of-the-box support for the further evolution of the Jakarta EE APIs. Spring Framework 6.0 is fully compatible with Tomcat 10.1, Jetty 11 and Undertow 2.3 as web servers, and also with Hibernate ORM 6.1. Over time, the role of Java/Jakarta EE in application development has evolved. In the early days of J2EE and Spring, applications were created to be deployed to an application server. Today, with the help of Spring Boot, applications are created in a devops- and cloud-friendly way, with the Servlet container embedded and trivial to change. As of Spring Framework 5, a WebFlux application does not even use the Servlet API directly and can run on servers (such as Netty) that are not Servlet containers. Spring continues to innovate and to evolve. Beyond the Spring Framework, there are other projects, such as Spring Boot, Spring Security, Spring Data, Spring Cloud, Spring Batch, among others. It’s important to remember that each project has its own source code repository, issue tracker, and release cadence. See spring.io/projects for the complete list of Spring projects. 1.3. Design Philosophy When you learn about a framework, it’s important to know not only what it does but what principles it follows. Here are the guiding principles of the Spring Framework: • Provide choice at every level. Spring lets you defer design decisions as late as possible. For example, you can switch persistence providers through configuration without changing your code. The same is true for many other infrastructure concerns and integration with third-party APIs. • Accommodate diverse perspectives. Spring embraces flexibility and is not opinionated about how things should be done. It supports a wide range of application needs with different perspectives. • Maintain strong backward compatibility. Spring’s evolution has been carefully managed to force few breaking changes between versions. Spring supports a carefully chosen range of JDK versions and third-party libraries to facilitate maintenance of applications and libraries that depend on Spring. • Care about API design. The Spring team puts a lot of thought and time into making APIs that are intuitive and that hold up across many versions and many years. • Set high standards for code quality. The Spring Framework puts a strong emphasis on meaningful, current, and accurate javadoc. It is one of very few projects that can claim clean code structure with no circular dependencies between packages. 1.4. Feedback and Contributions For how-to questions or diagnosing or debugging issues, we suggest using Stack Overflow. Click here for a list of the suggested tags to use on Stack Overflow. If you’re fairly certain that there is a problem in the Spring Framework or would like to suggest a feature, please use the GitHub Issues. If you have a solution in mind or a suggested fix, you can submit a pull request on Github. However, please keep in mind that, for all but the most trivial issues, we expect a ticket to be filed in the issue tracker, where discussions take place and leave a record for future reference. For more details see the guidelines at the CONTRIBUTING, top-level project page. 1.5. Getting Started If you are just getting started with Spring, you may want to begin using the Spring Framework by creating a Spring Boot-based application. Spring Boot provides a quick (and opinionated) way to create a production-ready Spring-based application. It is based on the Spring Framework, favors convention over configuration, and is designed to get you up and running as quickly as possible. You can use start.spring.io to generate a basic project or follow one of the "Getting Started" guides, such as Getting Started Building a RESTful Web Service. As well as being easier to digest, these guides are very task focused, and most of them are based on Spring Boot. They also cover other projects from the Spring portfolio that you might want to consider when solving a particular problem. Chapter 2. Core Technologies This part of the reference documentation covers all the technologies that are absolutely integral to the Spring Framework. Foremost amongst these is the Spring Framework’s Inversion of Control (IoC) container. A thorough treatment of the Spring Framework’s IoC container is closely followed by comprehensive coverage of Spring’s Aspect-Oriented Programming (AOP) technologies. The Spring Framework has its own AOP framework, which is conceptually easy to understand and which successfully addresses the 80% sweet spot of AOP requirements in Java enterprise programming. Coverage of Spring’s integration with AspectJ (currently the richest — in terms of features — and certainly most mature AOP implementation in the Java enterprise space) is also provided. AOT processing can be used to optimize your application ahead-of-time. It is typically used for native image deployment using GraalVM. 2.1. The IoC Container This chapter covers Spring’s Inversion of Control (IoC) container. 2.1.1. Introduction to the Spring IoC Container and Beans This chapter covers the Spring Framework implementation of the Inversion of Control (IoC) principle. IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes or a mechanism such as the Service Locator pattern. The org.springframework.beans and org.springframework.context packages are the basis for Spring Framework’s IoC container. The BeanFactory interface provides an advanced configuration mechanism capable of managing any type of object. ApplicationContext is a sub-interface of BeanFactory. It adds: • Easier integration with Spring’s AOP features • Message resource handling (for use in internationalization) • Event publication • Application-layer specific contexts such as the WebApplicationContext for use in web applications. In short, the BeanFactory provides the configuration framework and basic functionality, and the ApplicationContext adds more enterprise-specific functionality. The ApplicationContext is a complete superset of the BeanFactory and is used exclusively in this chapter in descriptions of Spring’s IoC container. For more information on using the BeanFactory instead of the ApplicationContext, see the section covering the BeanFactory API. In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container. 2.1.2. Container Overview The org.springframework.context.ApplicationContext interface represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the beans. The container gets its instructions on what objects to instantiate, configure, and assemble by reading configuration metadata. The configuration metadata is represented in XML, Java annotations, or Java code. It lets you express the objects that compose your application and the rich interdependencies between those objects. Several implementations of the ApplicationContext interface are supplied with Spring. In stand- alone applications, it is common to create an instance of ClassPathXmlApplicationContext or FileSystemXmlApplicationContext. While XML has been the traditional format for defining configuration metadata, you can instruct the container to use Java annotations or code as the metadata format by providing a small amount of XML configuration to declaratively enable support for these additional metadata formats. In most application scenarios, explicit user code is not required to instantiate one or more instances of a Spring IoC container. For example, in a web application scenario, a simple eight (or so) lines of boilerplate web descriptor XML in the web.xml file of the application typically suffices (see Convenient ApplicationContext Instantiation for Web Applications). If you use the Spring Tools for Eclipse (an Eclipse-powered development environment), you can easily create this boilerplate configuration with a few mouse clicks or keystrokes. The following diagram shows a high-level view of how Spring works. Your application classes are combined with configuration metadata so that, after the ApplicationContext is created and initialized, you have a fully configured and executable system or application. Figure 1. The Spring IoC container Configuration Metadata As the preceding diagram shows, the Spring IoC container consumes a form of configuration metadata. This configuration metadata represents how you, as an application developer, tell the Spring container to instantiate, configure, and assemble the objects in your application. Configuration metadata is traditionally supplied in a simple and intuitive XML format, which is what most of this chapter uses to convey key concepts and features of the Spring IoC container. XML-based metadata is not the only allowed form of configuration metadata. The Spring IoC container itself is totally decoupled from the format in which this  configuration metadata is actually written. These days, many developers choose Java-based configuration for their Spring applications. For information about using other forms of metadata with the Spring container, see: • Annotation-based configuration: Spring 2.5 introduced support for annotation-based configuration metadata. • Java-based configuration: Starting with Spring 3.0, many features provided by the Spring JavaConfig project became part of the core Spring Framework. Thus, you can define beans external to your application classes by using Java rather than XML files. To use these new features, see the @Configuration, @Bean, @Import, and @DependsOn annotations. Spring configuration consists of at least one and typically more than one bean definition that the container must manage. XML-based configuration metadata configures these beans as elements inside a top-level element. Java configuration typically uses @Bean-annotated methods within a @Configuration class. These bean definitions correspond to the actual objects that make up your application. Typically, you define service layer objects, data access objects (DAOs), presentation objects such as Struts Action instances, infrastructure objects such as Hibernate SessionFactories, JMS Queues, and so forth. Typically, one does not configure fine-grained domain objects in the container, because it is usually the responsibility of DAOs and business logic to create and load domain objects. However, you can use Spring’s integration with AspectJ to configure objects that have been created outside the control of an IoC container. See Using AspectJ to dependency-inject domain objects with Spring. The following example shows the basic structure of XML-based configuration metadata:   ① ②             ① The id attribute is a string that identifies the individual bean definition. ② The class attribute defines the type of the bean and uses the fully qualified classname. The value of the id attribute refers to collaborating objects. The XML for referring to collaborating objects is not shown in this example. See Dependencies for more information. Instantiating a Container The location path or paths supplied to an ApplicationContext constructor are resource strings that let the container load configuration metadata from a variety of external resources, such as the local file system, the Java CLASSPATH, and so on. Java ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml"); Kotlin val context = ClassPathXmlApplicationContext("services.xml", "daos.xml") After you learn about Spring’s IoC container, you may want to know more about Spring’s Resource abstraction (as described in Resources), which provides a  convenient mechanism for reading an InputStream from locations defined in a URI syntax. In particular, Resource paths are used to construct applications contexts, as described in Application Contexts and Resource Paths. The following example shows the service layer objects (services.xml) configuration file:               The following example shows the data access objects daos.xml file:               In the preceding example, the service layer consists of the PetStoreServiceImpl class and two data access objects of the types JpaAccountDao and JpaItemDao (based on the JPA Object-Relational Mapping standard). The property name element refers to the name of the JavaBean property, and the ref element refers to the name of another bean definition. This linkage between id and ref elements expresses the dependency between collaborating objects. For details of configuring an object’s dependencies, see Dependencies. Composing XML-based Configuration Metadata It can be useful to have bean definitions span multiple XML files. Often, each individual XML configuration file represents a logical layer or module in your architecture. You can use the application context constructor to load bean definitions from all these XML fragments. This constructor takes multiple Resource locations, as was shown in the previous section. Alternatively, use one or more occurrences of the element to load bean definitions from another file or files. The following example shows how to do so:           In the preceding example, external bean definitions are loaded from three files: services.xml, messageSource.xml, and themeSource.xml. All location paths are relative to the definition file doing the importing, so services.xml must be in the same directory or classpath location as the file doing the importing, while messageSource.xml and themeSource.xml must be in a resources location below the location of the importing file. As you can see, a leading slash is ignored. However, given that these paths are relative, it is better form not to use the slash at all. The contents of the files being imported, including the top level element, must be valid XML bean definitions, according to the Spring Schema. It is possible, but not recommended, to reference files in parent directories using a relative "../" path. Doing so creates a dependency on a file that is outside the current application. In particular, this reference is not recommended for classpath: URLs (for example, classpath:../services.xml), where the runtime resolution process chooses the “nearest” classpath root and then looks into its parent directory. Classpath configuration changes may lead to the choice of a different, incorrect directory.  You can always use fully qualified resource locations instead of relative paths: for example, file:C:/config/services.xml or classpath:/config/services.xml. However, be aware that you are coupling your application’s configuration to specific absolute locations. It is generally preferable to keep an indirection for such absolute locations — for example, through "${…}" placeholders that are resolved against JVM system properties at runtime. The namespace itself provides the import directive feature. Further configuration features beyond plain bean definitions are available in a selection of XML namespaces provided by Spring — for example, the context and util namespaces. The Groovy Bean Definition DSL As a further example for externalized configuration metadata, bean definitions can also be expressed in Spring’s Groovy Bean Definition DSL, as known from the Grails framework. Typically, such configuration live in a ".groovy" file with the structure shown in the following example: beans {   dataSource(BasicDataSource) {   driverClassName = "org.hsqldb.jdbcDriver"   url = "jdbc:hsqldb:mem:grailsDB"   username = "sa"   password = ""   settings = [mynew:"setting"]   }   sessionFactory(SessionFactory) {   dataSource = dataSource   }   myService(MyService) {   nestedBean = { AnotherBean bean ->   dataSource = dataSource   }   } } This configuration style is largely equivalent to XML bean definitions and even supports Spring’s XML configuration namespaces. It also allows for importing XML bean definition files through an importBeans directive. Using the Container The ApplicationContext is the interface for an advanced factory capable of maintaining a registry of different beans and their dependencies. By using the method T getBean(String name, Class requiredType), you can retrieve instances of your beans. The ApplicationContext lets you read bean definitions and access them, as the following example shows: Java // create and configure beans ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml"); // retrieve configured instance PetStoreService service = context.getBean("petStore", PetStoreService.class); // use configured instance List userList = service.getUsernameList(); Kotlin import org.springframework.beans.factory.getBean // create and configure beans val context = ClassPathXmlApplicationContext("services.xml", "daos.xml") // retrieve configured instance val service = context.getBean("petStore") // use configured instance var userList = service.getUsernameList() With Groovy configuration, bootstrapping looks very similar. It has a different context implementation class which is Groovy-aware (but also understands XML bean definitions). The following example shows Groovy configuration: Java ApplicationContext context = new GenericGroovyApplicationContext("services.groovy", "daos.groovy"); Kotlin val context = GenericGroovyApplicationContext("services.groovy", "daos.groovy") The most flexible variant is GenericApplicationContext in combination with reader delegates — for example, with XmlBeanDefinitionReader for XML files, as the following example shows: Java GenericApplicationContext context = new GenericApplicationContext(); new XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml"); context.refresh(); Kotlin val context = GenericApplicationContext() XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml") context.refresh() You can also use the GroovyBeanDefinitionReader for Groovy files, as the following example shows: Java GenericApplicationContext context = new GenericApplicationContext(); new GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy"); context.refresh(); Kotlin val context = GenericApplicationContext() GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy") context.refresh() You can mix and match such reader delegates on the same ApplicationContext, reading bean definitions from diverse configuration sources. You can then use getBean to retrieve instances of your beans. The ApplicationContext interface has a few other methods for retrieving beans, but, ideally, your application code should never use them. Indeed, your application code should have no calls to the getBean() method at all and thus have no dependency on Spring APIs at all. For example, Spring’s integration with web frameworks provides dependency injection for various web framework components such as controllers and JSF-managed beans, letting you declare a dependency on a specific bean through metadata (such as an autowiring annotation). 2.1.3. Bean Overview A Spring IoC container manages one or more beans. These beans are created with the configuration metadata that you supply to the container (for example, in the form of XML definitions). Within the container itself, these bean definitions are represented as BeanDefinition objects, which contain (among other information) the following metadata: • A package-qualified class name: typically, the actual implementation class of the bean being defined. • Bean behavioral configuration elements, which state how the bean should behave in the container (scope, lifecycle callbacks, and so forth). • References to other beans that are needed for the bean to do its work. These references are also called collaborators or dependencies. • Other configuration settings to set in the newly created object — for example, the size limit of the pool or the number of connections to use in a bean that manages a connection pool. This metadata translates to a set of properties that make up each bean definition. The following table describes these properties: Table 1. The bean definition Property Explained in… Class Instantiating Beans Name Naming Beans Scope Bean Scopes Constructor arguments Dependency Injection Properties Dependency Injection Autowiring mode Autowiring Collaborators Lazy initialization mode Lazy-initialized Beans Initialization method Initialization Callbacks Destruction method Destruction Callbacks In addition to bean definitions that contain information on how to create a specific bean, the ApplicationContext implementations also permit the registration of existing objects that are created outside the container (by users). This is done by accessing the ApplicationContext’s BeanFactory through the getBeanFactory() method, which returns the DefaultListableBeanFactory implementation. DefaultListableBeanFactory supports this registration through the registerSingleton(..) and registerBeanDefinition(..) methods. However, typical applications work solely with beans defined through regular bean definition metadata. Bean metadata and manually supplied singleton instances need to be registered as early as possible, in order for the container to properly reason about them during autowiring and other introspection steps. While overriding existing metadata and  existing singleton instances is supported to some degree, the registration of new beans at runtime (concurrently with live access to the factory) is not officially supported and may lead to concurrent access exceptions, inconsistent state in the bean container, or both. Naming Beans Every bean has one or more identifiers. These identifiers must be unique within the container that hosts the bean. A bean usually has only one identifier. However, if it requires more than one, the extra ones can be considered aliases. In XML-based configuration metadata, you use the id attribute, the name attribute, or both to specify the bean identifiers. The id attribute lets you specify exactly one id. Conventionally, these names are alphanumeric ('myBean', 'someService', etc.), but they can contain special characters as well. If you want to introduce other aliases for the bean, you can also specify them in the name attribute, separated by a comma (,), semicolon (;), or white space. As a historical note, in versions prior to Spring 3.1, the id attribute was defined as an xsd:ID type, which constrained possible characters. As of 3.1, it is defined as an xsd:string type. Note that bean id uniqueness is still enforced by the container, though no longer by XML parsers. You are not required to supply a name or an id for a bean. If you do not supply a name or id explicitly, the container generates a unique name for that bean. However, if you want to refer to that bean by name, through the use of the ref element or a Service Locator style lookup, you must provide a name. Motivations for not supplying a name are related to using inner beans and autowiring collaborators. Bean Naming Conventions The convention is to use the standard Java convention for instance field names when naming beans. That is, bean names start with a lowercase letter and are camel-cased from there. Examples of such names include accountManager, accountService, userDao, loginController, and so forth. Naming beans consistently makes your configuration easier to read and understand. Also, if you use Spring AOP, it helps a lot when applying advice to a set of beans related by name. With component scanning in the classpath, Spring generates bean names for unnamed components, following the rules described earlier: essentially, taking the simple class name and turning its initial character to lower-case. However, in the  (unusual) special case when there is more than one character and both the first and second characters are upper case, the original casing gets preserved. These are the same rules as defined by java.beans.Introspector.decapitalize (which Spring uses here). Aliasing a Bean outside the Bean Definition In a bean definition itself, you can supply more than one name for the bean, by using a combination of up to one name specified by the id attribute and any number of other names in the name attribute. These names can be equivalent aliases to the same bean and are useful for some situations, such as letting each component in an application refer to a common dependency by using a bean name that is specific to that component itself. Specifying all aliases where the bean is actually defined is not always adequate, however. It is sometimes desirable to introduce an alias for a bean that is defined elsewhere. This is commonly the case in large systems where configuration is split amongst each subsystem, with each subsystem having its own set of object definitions. In XML-based configuration metadata, you can use the element to accomplish this. The following example shows how to do so: In this case, a bean (in the same container) named fromName may also, after the use of this alias definition, be referred to as toName. For example, the configuration metadata for subsystem A may refer to a DataSource by the name of subsystemA-dataSource. The configuration metadata for subsystem B may refer to a DataSource by the name of subsystemB-dataSource. When composing the main application that uses both these subsystems, the main application refers to the DataSource by the name of myApp-dataSource. To have all three names refer to the same object, you can add the following alias definitions to the configuration metadata: Now each component and the main application can refer to the dataSource through a name that is unique and guaranteed not to clash with any other definition (effectively creating a namespace), yet they refer to the same bean. Java-configuration If you use Javaconfiguration, the @Bean annotation can be used to provide aliases. See Using the @Bean Annotation for details. Instantiating Beans A bean definition is essentially a recipe for creating one or more objects. The container looks at the recipe for a named bean when asked and uses the configuration metadata encapsulated by that bean definition to create (or acquire) an actual object. If you use XML-based configuration metadata, you specify the type (or class) of object that is to be instantiated in the class attribute of the element. This class attribute (which, internally, is a Class property on a BeanDefinition instance) is usually mandatory. (For exceptions, see Instantiation by Using an Instance Factory Method and Bean Definition Inheritance.) You can use the Class property in one of two ways: • Typically, to specify the bean class to be constructed in the case where the container itself directly creates the bean by calling its constructor reflectively, somewhat equivalent to Java code with the new operator. • To specify the actual class containing the static factory method that is invoked to create the object, in the less common case where the container invokes a static factory method on a class to create the bean. The object type returned from the invocation of the static factory method may be the same class or another class entirely. Nested class names If you want to configure a bean definition for a nested class, you may use either the binary name or the source name of the nested class. For example, if you have a class called SomeThing in the com.example package, and this SomeThing class has a static nested class called OtherThing, they can be separated by a dollar sign ($) or a dot (.). So the value of the class attribute in a bean definition would be com.example.SomeThing$OtherThing or com.example.SomeThing.OtherThing. Instantiation with a Constructor When you create a bean by the constructor approach, all normal classes are usable by and compatible with Spring. That is, the class being developed does not need to implement any specific interfaces or to be coded in a specific fashion. Simply specifying the bean class should suffice. However, depending on what type of IoC you use for that specific bean, you may need a default (empty) constructor. The Spring IoC container can manage virtually any class you want it to manage. It is not limited to managing true JavaBeans. Most Spring users prefer actual JavaBeans with only a default (no- argument) constructor and appropriate setters and getters modeled after the properties in the container. You can also have more exotic non-bean-style classes in your container. If, for example, you need to use a legacy connection pool that absolutely does not adhere to the JavaBean specification, Spring can manage it as well. With XML-based configuration metadata you can specify your bean class as follows: For details about the mechanism for supplying arguments to the constructor (if required) and setting object instance properties after the object is constructed, see Injecting Dependencies. Instantiation with a Static Factory Method When defining a bean that you create with a static factory method, use the class attribute to specify the class that contains the static factory method and an attribute named factory-method to specify the name of the factory method itself. You should be able to call this method (with optional arguments, as described later) and return a live object, which subsequently is treated as if it had been created through a constructor. One use for such a bean definition is to call static factories in legacy code. The following bean definition specifies that the bean will be created by calling a factory method. The definition does not specify the type (class) of the returned object, but rather the class containing the factory method. In this example, the createInstance() method must be a static method. The following example shows how to specify a factory method: The following example shows a class that would work with the preceding bean definition: Java public class ClientService {   private static ClientService clientService = new ClientService();   private ClientService() {}   public static ClientService createInstance() {   return clientService;   } } Kotlin class ClientService private constructor() {   companion object {   private val clientService = ClientService()   @JvmStatic   fun createInstance() = clientService   } } For details about the mechanism for supplying (optional) arguments to the factory method and setting object instance properties after the object is returned from the factory, see Dependencies and Configuration in Detail. Instantiation by Using an Instance Factory Method Similar to instantiation through a static factory method, instantiation with an instance factory method invokes a non-static method of an existing bean from the container to create a new bean. To use this mechanism, leave the class attribute empty and, in the factory-bean attribute, specify the name of a bean in the current (or parent or ancestor) container that contains the instance method that is to be invoked to create the object. Set the name of the factory method itself with the factory-method attribute. The following example shows how to configure such a bean:   The following example shows the corresponding class: Java public class DefaultServiceLocator {   private static ClientService clientService = new ClientServiceImpl();   public ClientService createClientServiceInstance() {   return clientService;   } } Kotlin class DefaultServiceLocator {   companion object {   private val clientService = ClientServiceImpl()   }   fun createClientServiceInstance(): ClientService {   return clientService   } } One factory class can also hold more than one factory method, as the following example shows:   The following example shows the corresponding class: Java public class DefaultServiceLocator {   private static ClientService clientService = new ClientServiceImpl();   private static AccountService accountService = new AccountServiceImpl();   public ClientService createClientServiceInstance() {   return clientService;   }   public AccountService createAccountServiceInstance() {   return accountService;   } } Kotlin class DefaultServiceLocator {   companion object {   private val clientService = ClientServiceImpl()   private val accountService = AccountServiceImpl()   }   fun createClientServiceInstance(): ClientService {   return clientService   }   fun createAccountServiceInstance(): AccountService {   return accountService   } } This approach shows that the factory bean itself can be managed and configured through dependency injection (DI). See Dependencies and Configuration in Detail. In Spring documentation, "factory bean" refers to a bean that is configured in the Spring container and that creates objects through an instance or static factory  method. By contrast, FactoryBean (notice the capitalization) refers to a Spring- specific FactoryBean implementation class. Determining a Bean’s Runtime Type The runtime type of a specific bean is non-trivial to determine. A specified class in the bean metadata definition is just an initial class reference, potentially combined with a declared factory method or being a FactoryBean class which may lead to a different runtime type of the bean, or not being set at all in case of an instance-level factory method (which is resolved via the specified factory-bean name instead). Additionally, AOP proxying may wrap a bean instance with an interface-based proxy with limited exposure of the target bean’s actual type (just its implemented interfaces). The recommended way to find out about the actual runtime type of a particular bean is a BeanFactory.getType call for the specified bean name. This takes all of the above cases into account and returns the type of object that a BeanFactory.getBean call is going to return for the same bean name. 2.1.4. Dependencies A typical enterprise application does not consist of a single object (or bean in the Spring parlance). Even the simplest application has a few objects that work together to present what the end-user sees as a coherent application. This next section explains how you go from defining a number of bean definitions that stand alone to a fully realized application where objects collaborate to achieve a goal. Dependency Injection Dependency injection (DI) is a process whereby objects define their dependencies (that is, the other objects with which they work) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies on its own by using direct construction of classes or the Service Locator pattern. Code is cleaner with the DI principle, and decoupling is more effective when objects are provided with their dependencies. The object does not look up its dependencies and does not know the location or class of the dependencies. As a result, your classes become easier to test, particularly when the dependencies are on interfaces or abstract base classes, which allow for stub or mock implementations to be used in unit tests. DI exists in two major variants: Constructor-based dependency injection and Setter-based dependency injection. Constructor-based Dependency Injection Constructor-based DI is accomplished by the container invoking a constructor with a number of arguments, each representing a dependency. Calling a static factory method with specific arguments to construct the bean is nearly equivalent, and this discussion treats arguments to a constructor and to a static factory method similarly. The following example shows a class that can only be dependency-injected with constructor injection: Java public class SimpleMovieLister {   // the SimpleMovieLister has a dependency on a MovieFinder   private final MovieFinder movieFinder;   // a constructor so that the Spring container can inject a MovieFinder   public SimpleMovieLister(MovieFinder movieFinder) {   this.movieFinder = movieFinder;   }   // business logic that actually uses the injected MovieFinder is omitted... } Kotlin // a constructor so that the Spring container can inject a MovieFinder class SimpleMovieLister(private val movieFinder: MovieFinder) {   // business logic that actually uses the injected MovieFinder is omitted... } Notice that there is nothing special about this class. It is a POJO that has no dependencies on container specific interfaces, base classes, or annotations. Constructor Argument Resolution Constructor argument resolution matching occurs by using the argument’s type. If no potential ambiguity exists in the constructor arguments of a bean definition, the order in which the constructor arguments are defined in a bean definition is the order in which those arguments are supplied to the appropriate constructor when the bean is being instantiated. Consider the following class: Java package x.y; public class ThingOne {   public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {   // ...   } } Kotlin package x.y class ThingOne(thingTwo: ThingTwo, thingThree: ThingThree) Assuming that the ThingTwo and ThingThree classes are not related by inheritance, no potential ambiguity exists. Thus, the following configuration works fine, and you do not need to specify the constructor argument indexes or types explicitly in the element.             When another bean is referenced, the type is known, and matching can occur (as was the case with the preceding example). When a simple type is used, such as true, Spring cannot determine the type of the value, and so cannot match by type without help. Consider the following class: Java package examples; public class ExampleBean {   // Number of years to calculate the Ultimate Answer   private final int years;   // The Answer to Life, the Universe, and Everything   private final String ultimateAnswer;   public ExampleBean(int years, String ultimateAnswer) {   this.years = years;   this.ultimateAnswer = ultimateAnswer;   } } Kotlin package examples class ExampleBean(   private val years: Int, // Number of years to calculate the Ultimate Answer   private val ultimateAnswer: String // The Answer to Life, the Universe, and Everything ) Constructor argument type matching In the preceding scenario, the container can use type matching with simple types if you explicitly specify the type of the constructor argument by using the type attribute, as the following example shows:     Constructor argument index You can use the index attribute to specify explicitly the index of constructor arguments, as the following example shows:     In addition to resolving the ambiguity of multiple simple values, specifying an index resolves ambiguity where a constructor has two arguments of the same type.  The index is 0-based. Constructor argument name You can also use the constructor parameter name for value disambiguation, as the following example shows:     Keep in mind that, to make this work out of the box, your code must be compiled with the debug flag enabled so that Spring can look up the parameter name from the constructor. If you cannot or do not want to compile your code with the debug flag, you can use the @ConstructorProperties JDK annotation to explicitly name your constructor arguments. The sample class would then have to look as follows: Java package examples; public class ExampleBean {   // Fields omitted   @ConstructorProperties({"years", "ultimateAnswer"})   public ExampleBean(int years, String ultimateAnswer) {   this.years = years;   this.ultimateAnswer = ultimateAnswer;   } } Kotlin package examples class ExampleBean @ConstructorProperties("years", "ultimateAnswer") constructor(val years: Int, val ultimateAnswer: String) Setter-based Dependency Injection Setter-based DI is accomplished by the container calling setter methods on your beans after invoking a no-argument constructor or a no-argument static factory method to instantiate your bean. The following example shows a class that can only be dependency-injected by using pure setter injection. This class is conventional Java. It is a POJO that has no dependencies on container specific interfaces, base classes, or annotations. Java public class SimpleMovieLister {   // the SimpleMovieLister has a dependency on the MovieFinder   private MovieFinder movieFinder;   // a setter method so that the Spring container can inject a MovieFinder   public void setMovieFinder(MovieFinder movieFinder) {   this.movieFinder = movieFinder;   }   // business logic that actually uses the injected MovieFinder is omitted... } Kotlin class SimpleMovieLister {   // a late-initialized property so that the Spring container can inject a MovieFinder   lateinit var movieFinder: MovieFinder   // business logic that actually uses the injected MovieFinder is omitted... } The ApplicationContext supports constructor-based and setter-based DI for the beans it manages. It also supports setter-based DI after some dependencies have already been injected through the constructor approach. You configure the dependencies in the form of a BeanDefinition, which you use in conjunction with PropertyEditor instances to convert properties from one format to another. However, most Spring users do not work with these classes directly (that is, programmatically) but rather with XML bean definitions, annotated components (that is, classes annotated with @Component, @Controller, and so forth), or @Bean methods in Java-based @Configuration classes. These sources are then converted internally into instances of BeanDefinition and used to load an entire Spring IoC container instance. Constructor-based or setter-based DI? Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies. Note that use of the @Autowired annotation on a setter method can be used to make the property be a required dependency; however, constructor injection with programmatic validation of arguments is preferable. The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null. Furthermore, constructor-injected components are always returned to the client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns. Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection. Use the DI style that makes the most sense for a particular class. Sometimes, when dealing with third-party classes for which you do not have the source, the choice is made for you. For example, if a third-party class does not expose any setter methods, then constructor injection may be the only available form of DI. Dependency Resolution Process The container performs bean dependency resolution as follows: • The ApplicationContext is created and initialized with configuration metadata that describes all the beans. Configuration metadata can be specified by XML, Java code, or annotations. • For each bean, its dependencies are expressed in the form of properties, constructor arguments, or arguments to the static-factory method (if you use that instead of a normal constructor). These dependencies are provided to the bean, when the bean is actually created. • Each property or constructor argument is an actual definition of the value to set, or a reference to another bean in the container. • Each property or constructor argument that is a value is converted from its specified format to the actual type of that property or constructor argument. By default, Spring can convert a value supplied in string format to all built-in types, such as int, long, String, boolean, and so forth. The Spring container validates the configuration of each bean as the container is created. However, the bean properties themselves are not set until the bean is actually created. Beans that are singleton-scoped and set to be pre-instantiated (the default) are created when the container is created. Scopes are defined in Bean Scopes. Otherwise, the bean is created only when it is requested. Creation of a bean potentially causes a graph of beans to be created, as the bean’s dependencies and its dependencies' dependencies (and so on) are created and assigned. Note that resolution mismatches among those dependencies may show up late — that is, on first creation of the affected bean. Circular dependencies If you use predominantly constructor injection, it is possible to create an unresolvable circular dependency scenario. For example: Class A requires an instance of class B through constructor injection, and class B requires an instance of class A through constructor injection. If you configure beans for classes A and B to be injected into each other, the Spring IoC container detects this circular reference at runtime, and throws a BeanCurrentlyInCreationException. One possible solution is to edit the source code of some classes to be configured by setters rather than constructors. Alternatively, avoid constructor injection and use setter injection only. In other words, although it is not recommended, you can configure circular dependencies with setter injection. Unlike the typical case (with no circular dependencies), a circular dependency between bean A and bean B forces one of the beans to be injected into the other prior to being fully initialized itself (a classic chicken-and-egg scenario). You can generally trust Spring to do the right thing. It detects configuration problems, such as references to non-existent beans and circular dependencies, at container load-time. Spring sets properties and resolves dependencies as late as possible, when the bean is actually created. This means that a Spring container that has loaded correctly can later generate an exception when you request an object if there is a problem creating that object or one of its dependencies — for example, the bean throws an exception as a result of a missing or invalid property. This potentially delayed visibility of some configuration issues is why ApplicationContext implementations by default pre-instantiate singleton beans. At the cost of some upfront time and memory to create these beans before they are actually needed, you discover configuration issues when the ApplicationContext is created, not later. You can still override this default behavior so that singleton beans initialize lazily, rather than being eagerly pre-instantiated. If no circular dependencies exist, when one or more collaborating beans are being injected into a dependent bean, each collaborating bean is totally configured prior to being injected into the dependent bean. This means that, if bean A has a dependency on bean B, the Spring IoC container completely configures bean B prior to invoking the setter method on bean A. In other words, the bean is instantiated (if it is not a pre-instantiated singleton), its dependencies are set, and the relevant lifecycle methods (such as a configured init method or the InitializingBean callback method) are invoked. Examples of Dependency Injection The following example uses XML-based configuration metadata for setter-based DI. A small part of a Spring XML configuration file specifies some bean definitions as follows:               The following example shows the corresponding ExampleBean class: Java public class ExampleBean {   private AnotherBean beanOne;   private YetAnotherBean beanTwo;   private int i;   public void setBeanOne(AnotherBean beanOne) {   this.beanOne = beanOne;   }   public void setBeanTwo(YetAnotherBean beanTwo) {   this.beanTwo = beanTwo;   }   public void setIntegerProperty(int i) {   this.i = i;   } } Kotlin class ExampleBean {   lateinit var beanOne: AnotherBean   lateinit var beanTwo: YetAnotherBean   var i: Int = 0 } In the preceding example, setters are declared to match against the properties specified in the XML file. The following example uses constructor-based DI:               The following example shows the corresponding ExampleBean class: Java public class ExampleBean {   private AnotherBean beanOne;   private YetAnotherBean beanTwo;   private int i;   public ExampleBean(   AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {   this.beanOne = anotherBean;   this.beanTwo = yetAnotherBean;   this.i = i;   } } Kotlin class ExampleBean(   private val beanOne: AnotherBean,   private val beanTwo: YetAnotherBean,   private val i: Int) The constructor arguments specified in the bean definition are used as arguments to the constructor of the ExampleBean. Now consider a variant of this example, where, instead of using a constructor, Spring is told to call a static factory method to return an instance of the object:       The following example shows the corresponding ExampleBean class: Java public class ExampleBean {   // a private constructor   private ExampleBean(...) {   ...   }   // a static factory method; the arguments to this method can be   // considered the dependencies of the bean that is returned,   // regardless of how those arguments are actually used.   public static ExampleBean createInstance (   AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {   ExampleBean eb = new ExampleBean (...);   // some other operations...   return eb;   } } Kotlin class ExampleBean private constructor() {   companion object {   // a static factory method; the arguments to this method can be   // considered the dependencies of the bean that is returned,   // regardless of how those arguments are actually used.   @JvmStatic   fun createInstance(anotherBean: AnotherBean, yetAnotherBean: YetAnotherBean, i: Int): ExampleBean {   val eb = ExampleBean (...)   // some other operations...   return eb   }   } } Arguments to the static factory method are supplied by elements, exactly the same as if a constructor had actually been used. The type of the class being returned by the factory method does not have to be of the same type as the class that contains the static factory method (although, in this example, it is). An instance (non-static) factory method can be used in an essentially identical fashion (aside from the use of the factory-bean attribute instead of the class attribute), so we do not discuss those details here. Dependencies and Configuration in Detail As mentioned in the previous section, you can define bean properties and constructor arguments as references to other managed beans (collaborators) or as values defined inline. Spring’s XML-based configuration metadata supports sub-element types within its and elements for this purpose. Straight Values (Primitives, Strings, and so on) The value attribute of the element specifies a property or constructor argument as a human-readable string representation. Spring’s conversion service is used to convert these values from a String to the actual type of the property or argument. The following example shows various values being set:           The following example uses the p-namespace for even more succinct XML configuration:   The preceding XML is more succinct. However, typos are discovered at runtime rather than design time, unless you use an IDE (such as IntelliJ IDEA or the Spring Tools for Eclipse) that supports automatic property completion when you create bean definitions. Such IDE assistance is highly recommended. You can also configure a java.util.Properties instance, as follows:         jdbc.driver.className=com.mysql.jdbc.Driver   jdbc.url=jdbc:mysql://localhost:3306/mydb     The Spring container converts the text inside the element into a java.util.Properties instance by using the JavaBeans PropertyEditor mechanism. This is a nice shortcut, and is one of a few places where the Spring team do favor the use of the nested element over the value attribute style. The idref element The idref element is simply an error-proof way to pass the id (a string value - not a reference) of another bean in the container to a or element. The following example shows how to use it:       The preceding bean definition snippet is exactly equivalent (at runtime) to the following snippet:   The first form is preferable to the second, because using the idref tag lets the container validate at deployment time that the referenced, named bean actually exists. In the second variation, no validation is performed on the value that is passed to the targetName property of the client bean. Typos are only discovered (with most likely fatal results) when the client bean is actually instantiated. If the client bean is a prototype bean, this typo and the resulting exception may only be discovered long after the container is deployed. The local attribute on the idref element is no longer supported in the 4.0 beans XSD, since it does not provide value over a regular bean reference any more.  Change your existing idref local references to idref bean when upgrading to the 4.0 schema. A common place (at least in versions earlier than Spring 2.0) where the element brings value is in the configuration of AOP interceptors in a ProxyFactoryBean bean definition. Using elements when you specify the interceptor names prevents you from misspelling an interceptor ID. References to Other Beans (Collaborators) The ref element is the final element inside a or definition element. Here, you set the value of the specified property of a bean to be a reference to another bean (a collaborator) managed by the container. The referenced bean is a dependency of the bean whose property is to be set, and it is initialized on demand as needed before the property is set. (If the collaborator is a singleton bean, it may already be initialized by the container.) All references are ultimately a reference to another object. Scoping and validation depend on whether you specify the ID or name of the other object through the bean or parent attribute. Specifying the target bean through the bean attribute of the tag is the most general form and allows creation of a reference to any bean in the same container or parent container, regardless of whether it is in the same XML file. The value of the bean attribute may be the same as the id attribute of the target bean or be the same as one of the values in the name attribute of the target bean. The following example shows how to use a ref element: Specifying the target bean through the parent attribute creates a reference to a bean that is in a parent container of the current container. The value of the parent attribute may be the same as either the id attribute of the target bean or one of the values in the name attribute of the target bean. The target bean must be in a parent container of the current one. You should use this bean reference variant mainly when you have a hierarchy of containers and you want to wrap an existing bean in a parent container with a proxy that has the same name as the parent bean. The following pair of listings shows how to use the parent attribute:           The local attribute on the ref element is no longer supported in the 4.0 beans XSD,  since it does not provide value over a regular bean reference any more. Change your existing ref local references to ref bean when upgrading to the 4.0 schema. Inner Beans A element inside the or elements defines an inner bean, as the following example shows:               An inner bean definition does not require a defined ID or name. If specified, the container does not use such a value as an identifier. The container also ignores the scope flag on creation, because inner beans are always anonymous and are always created with the outer bean. It is not possible to access inner beans independently or to inject them into collaborating beans other than into the enclosing bean. As a corner case, it is possible to receive destruction callbacks from a custom scope — for example, for a request-scoped inner bean contained within a singleton bean. The creation of the inner bean instance is tied to its containing bean, but destruction callbacks let it participate in the request scope’s lifecycle. This is not a common scenario. Inner beans typically simply share their containing bean’s scope. Collections The , , , and elements set the properties and arguments of the Java Collection types List, Set, Map, and Properties, respectively. The following example shows how to use them:         administrator@example.org   support@example.org   development@example.org             a list element followed by a reference                             just some string       The value of a map key or value, or a set value, can also be any of the following elements: bean | ref | idref | list | set | map | props | value | null Collection Merging The Spring container also supports merging collections. An application developer can define a parent , , or element and have child , , or elements inherit and override values from the parent collection. That is, the child collection’s values are the result of merging the elements of the parent and child collections, with the child’s collection elements overriding values specified in the parent collection. This section on merging discusses the parent-child bean mechanism. Readers unfamiliar with parent and child bean definitions may wish to read the relevant section before continuing. The following example demonstrates collection merging:         administrator@example.com   support@example.com                 sales@example.com   support@example.co.uk       Notice the use of the merge=true attribute on the element of the adminEmails property of the child bean definition. When the child bean is resolved and instantiated by the container, the resulting instance has an adminEmails Properties collection that contains the result of merging the child’s adminEmails collection with the parent’s adminEmails collection. The following listing shows the result: administrator=administrator@example.com sales=sales@example.com support=support@example.co.uk The child Properties collection’s value set inherits all property elements from the parent , and the child’s value for the support value overrides the value in the parent collection. This merging behavior applies similarly to the , , and collection types. In the specific case of the element, the semantics associated with the List collection type (that is, the notion of an ordered collection of values) is maintained. The parent’s values precede all of the child list’s values. In the case of the Map, Set, and Properties collection types, no ordering exists. Hence, no ordering semantics are in effect for the collection types that underlie the associated Map, Set, and Properties implementation types that the container uses internally. Limitations of Collection Merging You cannot merge different collection types (such as a Map and a List). If you do attempt to do so, an appropriate Exception is thrown. The merge attribute must be specified on the lower, inherited, child definition. Specifying the merge attribute on a parent collection definition is redundant and does not result in the desired merging. Strongly-typed collection Thanks to Java’s support for generic types, you can use strongly typed collections. That is, it is possible to declare a Collection type such that it can only contain (for example) String elements. If you use Spring to dependency-inject a strongly-typed Collection into a bean, you can take advantage of Spring’s type-conversion support such that the elements of your strongly-typed Collection instances are converted to the appropriate type prior to being added to the Collection. The following Java class and bean definition show how to do so: Java public class SomeClass {   private Map accounts;   public void setAccounts(Map accounts) {   this.accounts = accounts;   } } Kotlin class SomeClass {   lateinit var accounts: Map }                   When the accounts property of the something bean is prepared for injection, the generics information about the element type of the strongly-typed Map is available by reflection. Thus, Spring’s type conversion infrastructure recognizes the various value elements as being of type Float, and the string values (9.99, 2.75, and 3.99) are converted into an actual Float type. Null and Empty String Values Spring treats empty arguments for properties and the like as empty Strings. The following XML- based configuration metadata snippet sets the email property to the empty String value ("").   The preceding example is equivalent to the following Java code: Java exampleBean.setEmail(""); Kotlin exampleBean.email = "" The element handles null values. The following listing shows an example:       The preceding configuration is equivalent to the following Java code: Java exampleBean.setEmail(null); Kotlin exampleBean.email = null XML Shortcut with the p-namespace The p-namespace lets you use the bean element’s attributes (instead of nested elements) to describe your property values collaborating beans, or both. Spring supports extensible configuration formats with namespaces, which are based on an XML Schema definition. The beans configuration format discussed in this chapter is defined in an XML Schema document. However, the p-namespace is not defined in an XSD file and exists only in the core of Spring. The following example shows two XML snippets (the first uses standard XML format and the second uses the p-namespace) that resolve to the same result:         The example shows an attribute in the p-namespace called email in the bean definition. This tells Spring to include a property declaration. As previously mentioned, the p-namespace does not have a schema definition, so you can set the name of the attribute to the property name. This next example includes two more bean definitions that both have a reference to another bean:                 This example includes not only a property value using the p-namespace but also uses a special format to declare property references. Whereas the first bean definition uses to create a reference from bean john to bean jane, the second bean definition uses p:spouse-ref="jane" as an attribute to do the exact same thing. In this case, spouse is the property name, whereas the -ref part indicates that this is not a straight value but rather a reference to another bean. The p-namespace is not as flexible as the standard XML format. For example, the format for declaring property references clashes with properties that end in Ref,  whereas the standard XML format does not. We recommend that you choose your approach carefully and communicate this to your team members to avoid producing XML documents that use all three approaches at the same time. XML Shortcut with the c-namespace Similar to the XML Shortcut with the p-namespace, the c-namespace, introduced in Spring 3.1, allows inlined attributes for configuring the constructor arguments rather then nested constructor- arg elements. The following example uses the c: namespace to do the same thing as the from Constructor-based Dependency Injection:                     The c: namespace uses the same conventions as the p: one (a trailing -ref for bean references) for setting the constructor arguments by their names. Similarly, it needs to be declared in the XML file even though it is not defined in an XSD schema (it exists inside the Spring core). For the rare cases where the constructor argument names are not available (usually if the bytecode was compiled without debugging information), you can use fallback to the argument indexes, as follows: Due to the XML grammar, the index notation requires the presence of the leading _, as XML attribute names cannot start with a number (even though some IDEs  allow it). A corresponding index notation is also available for elements but not commonly used since the plain order of declaration is usually sufficient there. In practice, the constructor resolution mechanism is quite efficient in matching arguments, so unless you really need to, we recommend using the name notation throughout your configuration. Compound Property Names You can use compound or nested property names when you set bean properties, as long as all components of the path except the final property name are not null. Consider the following bean definition:   The something bean has a fred property, which has a bob property, which has a sammy property, and that final sammy property is being set to a value of 123. In order for this to work, the fred property of something and the bob property of fred must not be null after the bean is constructed. Otherwise, a NullPointerException is thrown. Using depends-on If a bean is a dependency of another bean, that usually means that one bean is set as a property of another. Typically you accomplish this with the element in XML-based configuration metadata. However, sometimes dependencies between beans are less direct. An example is when a static initializer in a class needs to be triggered, such as for database driver registration. The depends-on attribute can explicitly force one or more beans to be initialized before the bean using this element is initialized. The following example uses the depends-on attribute to express a dependency on a single bean: To express a dependency on multiple beans, supply a list of bean names as the value of the depends- on attribute (commas, whitespace, and semicolons are valid delimiters):   The depends-on attribute can specify both an initialization-time dependency and, in the case of singleton beans only, a corresponding destruction-time dependency.  Dependent beans that define a depends-on relationship with a given bean are destroyed first, prior to the given bean itself being destroyed. Thus, depends-on can also control shutdown order. Lazy-initialized Beans By default, ApplicationContext implementations eagerly create and configure all singleton beans as part of the initialization process. Generally, this pre-instantiation is desirable, because errors in the configuration or surrounding environment are discovered immediately, as opposed to hours or even days later. When this behavior is not desirable, you can prevent pre-instantiation of a singleton bean by marking the bean definition as being lazy-initialized. A lazy-initialized bean tells the IoC container to create a bean instance when it is first requested, rather than at startup. In XML, this behavior is controlled by the lazy-init attribute on the element, as the following example shows: When the preceding configuration is consumed by an ApplicationContext, the lazy bean is not eagerly pre-instantiated when the ApplicationContext starts, whereas the not.lazy bean is eagerly pre-instantiated. However, when a lazy-initialized bean is a dependency of a singleton bean that is not lazy- initialized, the ApplicationContext creates the lazy-initialized bean at startup, because it must satisfy the singleton’s dependencies. The lazy-initialized bean is injected into a singleton bean elsewhere that is not lazy-initialized. You can also control lazy-initialization at the container level by using the default-lazy-init attribute on the element, as the following example shows:   Autowiring Collaborators The Spring container can autowire relationships between collaborating beans. You can let Spring resolve collaborators (other beans) automatically for your bean by inspecting the contents of the ApplicationContext. Autowiring has the following advantages: • Autowiring can significantly reduce the need to specify properties or constructor arguments. (Other mechanisms such as a bean template discussed elsewhere in this chapter are also valuable in this regard.) • Autowiring can update a configuration as your objects evolve. For example, if you need to add a dependency to a class, that dependency can be satisfied automatically without you needing to modify the configuration. Thus autowiring can be especially useful during development, without negating the option of switching to explicit wiring when the code base becomes more stable. When using XML-based configuration metadata (see Dependency Injection), you can specify the autowire mode for a bean definition with the autowire attribute of the element. The autowiring functionality has four modes. You specify autowiring per bean and can thus choose which ones to autowire. The following table describes the four autowiring modes: Table 2. Autowiring modes Mode Explanation no (Default) No autowiring. Bean references must be defined by ref elements. Changing the default setting is not recommended for larger deployments, because specifying collaborators explicitly gives greater control and clarity. To some extent, it documents the structure of a system. byName Autowiring by property name. Spring looks for a bean with the same name as the property that needs to be autowired. For example, if a bean definition is set to autowire by name and it contains a master property (that is, it has a setMaster(..) method), Spring looks for a bean definition named master and uses it to set the property. byType Lets a property be autowired if exactly one bean of the property type exists in the container. If more than one exists, a fatal exception is thrown, which indicates that you may not use byType autowiring for that bean. If there are no matching beans, nothing happens (the property is not set). constructor Analogous to byType but applies to constructor arguments. If there is not exactly one bean of the constructor argument type in the container, a fatal error is raised. With byType or constructor autowiring mode, you can wire arrays and typed collections. In such cases, all autowire candidates within the container that match the expected type are provided to satisfy the dependency. You can autowire strongly-typed Map instances if the expected key type is String. An autowired Map instance’s values consist of all bean instances that match the expected type, and the Map instance’s keys contain the corresponding bean names. Limitations and Disadvantages of Autowiring Autowiring works best when it is used consistently across a project. If autowiring is not used in general, it might be confusing to developers to use it to wire only one or two bean definitions. Consider the limitations and disadvantages of autowiring: • Explicit dependencies in property and constructor-arg settings always override autowiring. You cannot autowire simple properties such as primitives, Strings, and Classes (and arrays of such simple properties). This limitation is by-design. • Autowiring is less exact than explicit wiring. Although, as noted in the earlier table, Spring is careful to avoid guessing in case of ambiguity that might have unexpected results. The relationships between your Spring-managed objects are no longer documented explicitly. • Wiring information may not be available to tools that may generate documentation from a Spring container. • Multiple bean definitions within the container may match the type specified by the setter method or constructor argument to be autowired. For arrays, collections, or Map instances, this is not necessarily a problem. However, for dependencies that expect a single value, this ambiguity is not arbitrarily resolved. If no unique bean definition is available, an exception is thrown. In the latter scenario, you have several options: • Abandon autowiring in favor of explicit wiring. • Avoid autowiring for a bean definition by setting its autowire-candidate attributes to false, as described in the next section. • Designate a single bean definition as the primary candidate by setting the primary attribute of its element to true. • Implement the more fine-grained control available with annotation-based configuration, as described in Annotation-based Container Configuration. Excluding a Bean from Autowiring On a per-bean basis, you can exclude a bean from autowiring. In Spring’s XML format, set the autowire-candidate attribute of the element to false. The container makes that specific bean definition unavailable to the autowiring infrastructure (including annotation style configurations such as @Autowired). The autowire-candidate attribute is designed to only affect type-based autowiring. It does not affect explicit references by name, which get resolved even if the  specified bean is not marked as an autowire candidate. As a consequence, autowiring by name nevertheless injects a bean if the name matches. You can also limit autowire candidates based on pattern-matching against bean names. The top- level element accepts one or more patterns within its default-autowire-candidates attribute. For example, to limit autowire candidate status to any bean whose name ends with Repository, provide a value of *Repository. To provide multiple patterns, define them in a comma- separated list. An explicit value of true or false for a bean definition’s autowire-candidate attribute always takes precedence. For such beans, the pattern matching rules do not apply. These techniques are useful for beans that you never want to be injected into other beans by autowiring. It does not mean that an excluded bean cannot itself be configured by using autowiring. Rather, the bean itself is not a candidate for autowiring other beans. Method Injection In most application scenarios, most beans in the container are singletons. When a singleton bean needs to collaborate with another singleton bean or a non-singleton bean needs to collaborate with another non-singleton bean, you typically handle the dependency by defining one bean as a property of the other. A problem arises when the bean lifecycles are different. Suppose singleton bean A needs to use non-singleton (prototype) bean B, perhaps on each method invocation on A. The container creates the singleton bean A only once, and thus only gets one opportunity to set the properties. The container cannot provide bean A with a new instance of bean B every time one is needed. A solution is to forego some inversion of control. You can make bean A aware of the container by implementing the ApplicationContextAware interface, and by making a getBean("B") call to the container ask for (a typically new) bean B instance every time bean A needs it. The following example shows this approach: Java // a class that uses a stateful Command-style class to perform some processing package fiona.apple; // Spring-API imports import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class CommandManager implements ApplicationContextAware {   private ApplicationContext applicationContext;   public Object process(Map commandState) {   // grab a new instance of the appropriate Command   Command command = createCommand();   // set the state on the (hopefully brand new) Command instance   command.setState(commandState);   return command.execute();   }   protected Command createCommand() {   // notice the Spring API dependency!   return this.applicationContext.getBean("command", Command.class);   }   public void setApplicationContext(   ApplicationContext applicationContext) throws BeansException {   this.applicationContext = applicationContext;   } } Kotlin // a class that uses a stateful Command-style class to perform some processing package fiona.apple // Spring-API imports import org.springframework.context.ApplicationContext import org.springframework.context.ApplicationContextAware class CommandManager : ApplicationContextAware {   private lateinit var applicationContext: ApplicationContext   fun process(commandState: Map<*, *>): Any {   // grab a new instance of the appropriate Command   val command = createCommand()   // set the state on the (hopefully brand new) Command instance   command.state = commandState   return command.execute()   }   // notice the Spring API dependency!   protected fun createCommand() =   applicationContext.getBean("command", Command::class.java)   override fun setApplicationContext(applicationContext: ApplicationContext) {   this.applicationContext = applicationContext   } } The preceding is not desirable, because the business code is aware of and coupled to the Spring Framework. Method Injection, a somewhat advanced feature of the Spring IoC container, lets you handle this use case cleanly. You can read more about the motivation for Method Injection in this blog entry. Lookup Method Injection Lookup method injection is the ability of the container to override methods on container-managed beans and return the lookup result for another named bean in the container. The lookup typically involves a prototype bean, as in the scenario described in the preceding section. The Spring Framework implements this method injection by using bytecode generation from the CGLIB library to dynamically generate a subclass that overrides the method. • For this dynamic subclassing to work, the class that the Spring bean container subclasses cannot be final, and the method to be overridden cannot be final, either. • Unit-testing a class that has an abstract method requires you to subclass the class yourself and to supply a stub implementation of the abstract method.  • Concrete methods are also necessary for component scanning, which requires concrete classes to pick up. • A further key limitation is that lookup methods do not work with factory methods and in particular not with @Bean methods in configuration classes, since, in that case, the container is not in charge of creating the instance and therefore cannot create a runtime-generated subclass on the fly. In the case of the CommandManager class in the previous code snippet, the Spring container dynamically overrides the implementation of the createCommand() method. The CommandManager class does not have any Spring dependencies, as the reworked example shows: Java package fiona.apple; // no more Spring imports! public abstract class CommandManager {   public Object process(Object commandState) {   // grab a new instance of the appropriate Command interface   Command command = createCommand();   // set the state on the (hopefully brand new) Command instance   command.setState(commandState);   return command.execute();   }   // okay... but where is the implementation of this method?   protected abstract Command createCommand(); } Kotlin package fiona.apple // no more Spring imports! abstract class CommandManager {   fun process(commandState: Any): Any {   // grab a new instance of the appropriate Command interface   val command = createCommand()   // set the state on the (hopefully brand new) Command instance   command.state = commandState   return command.execute()   }   // okay... but where is the implementation of this method?   protected abstract fun createCommand(): Command } In the client class that contains the method to be injected (the CommandManager in this case), the method to be injected requires a signature of the following form: [abstract] theMethodName(no-arguments); If the method is abstract, the dynamically-generated subclass implements the method. Otherwise, the dynamically-generated subclass overrides the concrete method defined in the original class. Consider the following example:     The bean identified as commandManager calls its own createCommand() method whenever it needs a new instance of the myCommand bean. You must be careful to deploy the myCommand bean as a prototype if that is actually what is needed. If it is a singleton, the same instance of the myCommand bean is returned each time. Alternatively, within the annotation-based component model, you can declare a lookup method through the @Lookup annotation, as the following example shows: Java public abstract class CommandManager {   public Object process(Object commandState) {   Command command = createCommand();   command.setState(commandState);   return command.execute();   }   @Lookup("myCommand")   protected abstract Command createCommand(); } Kotlin abstract class CommandManager {   fun process(commandState: Any): Any {   val command = createCommand()   command.state = commandState   return command.execute()   }   @Lookup("myCommand")   protected abstract fun createCommand(): Command } Or, more idiomatically, you can rely on the target bean getting resolved against the declared return type of the lookup method: Java public abstract class CommandManager {   public Object process(Object commandState) {   Command command = createCommand();   command.setState(commandState);   return command.execute();   }   @Lookup   protected abstract Command createCommand(); } Kotlin abstract class CommandManager {   fun process(commandState: Any): Any {   val command = createCommand()   command.state = commandState   return command.execute()   }   @Lookup   protected abstract fun createCommand(): Command } Note that you should typically declare such annotated lookup methods with a concrete stub implementation, in order for them to be compatible with Spring’s component scanning rules where abstract classes get ignored by default. This limitation does not apply to explicitly registered or explicitly imported bean classes. Another way of accessing differently scoped target beans is an ObjectFactory/ Provider injection point. See Scoped Beans as Dependencies.  You may also find the ServiceLocatorFactoryBean (in the org.springframework.beans.factory.config package) to be useful. Arbitrary Method Replacement A less useful form of method injection than lookup method injection is the ability to replace arbitrary methods in a managed bean with another method implementation. You can safely skip the rest of this section until you actually need this functionality. With XML-based configuration metadata, you can use the replaced-method element to replace an existing method implementation with another, for a deployed bean. Consider the following class, which has a method called computeValue that we want to override: Java public class MyValueCalculator {   public String computeValue(String input) {   // some real code...   }   // some other methods... } Kotlin class MyValueCalculator {   fun computeValue(input: String): String {   // some real code...   }   // some other methods... } A class that implements the org.springframework.beans.factory.support.MethodReplacer interface provides the new method definition, as the following example shows: Java /**  * meant to be used to override the existing computeValue(String)  * implementation in MyValueCalculator  */ public class ReplacementComputeValue implements MethodReplacer {   public Object reimplement(Object o, Method m, Object[] args) throws Throwable {   // get the input value, work with it, and return a computed result   String input = (String) args[0];   ...   return ...;   } } Kotlin /**  * meant to be used to override the existing computeValue(String)  * implementation in MyValueCalculator  */ class ReplacementComputeValue : MethodReplacer {   override fun reimplement(obj: Any, method: Method, args: Array): Any {   // get the input value, work with it, and return a computed result   val input = args[0] as String;   ...   return ...;   } } The bean definition to deploy the original class and specify the method override would resemble the following example:       String   You can use one or more elements within the element to indicate the method signature of the method being overridden. The signature for the arguments is necessary only if the method is overloaded and multiple variants exist within the class. For convenience, the type string for an argument may be a substring of the fully qualified type name. For example, the following all match java.lang.String: java.lang.String String Str Because the number of arguments is often enough to distinguish between each possible choice, this shortcut can save a lot of typing, by letting you type only the shortest string that matches an argument type. 2.1.5. Bean Scopes When you create a bean definition, you create a recipe for creating actual instances of the class defined by that bean definition. The idea that a bean definition is a recipe is important, because it means that, as with a class, you can create many object instances from a single recipe. You can control not only the various dependencies and configuration values that are to be plugged into an object that is created from a particular bean definition but also control the scope of the objects created from a particular bean definition. This approach is powerful and flexible, because you can choose the scope of the objects you create through configuration instead of having to bake in the scope of an object at the Java class level. Beans can be defined to be deployed in one of a number of scopes. The Spring Framework supports six scopes, four of which are available only if you use a web-aware ApplicationContext. You can also create a custom scope. The following table describes the supported scopes: Table 3. Bean scopes Scope Description singleton (Default) Scopes a single bean definition to a single object instance for each Spring IoC container. prototype Scopes a single bean definition to any number of object instances. Scope Description request Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext. session Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext. application Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext. websocket Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext. As of Spring 3.0, a thread scope is available but is not registered by default. For  more information, see the documentation for SimpleThreadScope. For instructions on how to register this or any other custom scope, see Using a Custom Scope. The Singleton Scope Only one shared instance of a singleton bean is managed, and all requests for beans with an ID or IDs that match that bean definition result in that one specific bean instance being returned by the Spring container. To put it another way, when you define a bean definition and it is scoped as a singleton, the Spring IoC container creates exactly one instance of the object defined by that bean definition. This single instance is stored in a cache of such singleton beans, and all subsequent requests and references for that named bean return the cached object. The following image shows how the singleton scope works: Spring’s concept of a singleton bean differs from the singleton pattern as defined in the Gang of Four (GoF) patterns book. The GoF singleton hard-codes the scope of an object such that one and only one instance of a particular class is created per ClassLoader. The scope of the Spring singleton is best described as being per-container and per-bean. This means that, if you define one bean for a particular class in a single Spring container, the Spring container creates one and only one instance of the class defined by that bean definition. The singleton scope is the default scope in Spring. To define a bean as a singleton in XML, you can define a bean as shown in the following example: The Prototype Scope The non-singleton prototype scope of bean deployment results in the creation of a new bean instance every time a request for that specific bean is made. That is, the bean is injected into another bean or you request it through a getBean() method call on the container. As a rule, you should use the prototype scope for all stateful beans and the singleton scope for stateless beans. The following diagram illustrates the Spring prototype scope: (A data access object (DAO) is not typically configured as a prototype, because a typical DAO does not hold any conversational state. It was easier for us to reuse the core of the singleton diagram.) The following example defines a bean as a prototype in XML: In contrast to the other scopes, Spring does not manage the complete lifecycle of a prototype bean. The container instantiates, configures, and otherwise assembles a prototype object and hands it to the client, with no further record of that prototype instance. Thus, although initialization lifecycle callback methods are called on all objects regardless of scope, in the case of prototypes, configured destruction lifecycle callbacks are not called. The client code must clean up prototype-scoped objects and release expensive resources that the prototype beans hold. To get the Spring container to release resources held by prototype-scoped beans, try using a custom bean post-processor, which holds a reference to beans that need to be cleaned up. In some respects, the Spring container’s role in regard to a prototype-scoped bean is a replacement for the Java new operator. All lifecycle management past that point must be handled by the client. (For details on the lifecycle of a bean in the Spring container, see Lifecycle Callbacks.) Singleton Beans with Prototype-bean Dependencies When you use singleton-scoped beans with dependencies on prototype beans, be aware that dependencies are resolved at instantiation time. Thus, if you dependency-inject a prototype-scoped bean into a singleton-scoped bean, a new prototype bean is instantiated and then dependency- injected into the singleton bean. The prototype instance is the sole instance that is ever supplied to the singleton-scoped bean. However, suppose you want the singleton-scoped bean to acquire a new instance of the prototype- scoped bean repeatedly at runtime. You cannot dependency-inject a prototype-scoped bean into your singleton bean, because that injection occurs only once, when the Spring container instantiates the singleton bean and resolves and injects its dependencies. If you need a new instance of a prototype bean at runtime more than once, see Method Injection. Request, Session, Application, and WebSocket Scopes The request, session, application, and websocket scopes are available only if you use a web-aware Spring ApplicationContext implementation (such as XmlWebApplicationContext). If you use these scopes with regular Spring IoC containers, such as the ClassPathXmlApplicationContext, an IllegalStateException that complains about an unknown bean scope is thrown. Initial Web Configuration To support the scoping of beans at the request, session, application, and websocket levels (web- scoped beans), some minor initial configuration is required before you define your beans. (This initial setup is not required for the standard scopes: singleton and prototype.) How you accomplish this initial setup depends on your particular Servlet environment. If you access scoped beans within Spring Web MVC, in effect, within a request that is processed by the Spring DispatcherServlet, no special setup is necessary. DispatcherServlet already exposes all relevant state. If you use a Servlet web container, with requests processed outside of Spring’s DispatcherServlet (for example, when using JSF or Struts), you need to register the org.springframework.web.context.request.RequestContextListener ServletRequestListener. This can be done programmatically by using the WebApplicationInitializer interface. Alternatively, add the following declaration to your web application’s web.xml file:   ...       org.springframework.web.context.request.RequestContextListener       ... Alternatively, if there are issues with your listener setup, consider using Spring’s RequestContextFilter. The filter mapping depends on the surrounding web application configuration, so you have to change it as appropriate. The following listing shows the filter part of a web application:   ...     requestContextFilter   org.springframework.web.filter.RequestContextFilter       requestContextFilter   /*     ... DispatcherServlet, RequestContextListener, and RequestContextFilter all do exactly the same thing, namely bind the HTTP request object to the Thread that is servicing that request. This makes beans that are request- and session-scoped available further down the call chain. Request scope Consider the following XML configuration for a bean definition: The Spring container creates a new instance of the LoginAction bean by using the loginAction bean definition for each and every HTTP request. That is, the loginAction bean is scoped at the HTTP request level. You can change the internal state of the instance that is created as much as you want, because other instances created from the same loginAction bean definition do not see these changes in state. They are particular to an individual request. When the request completes processing, the bean that is scoped to the request is discarded. When using annotation-driven components or Java configuration, the @RequestScope annotation can be used to assign a component to the request scope. The following example shows how to do so: Java @RequestScope @Component public class LoginAction {   // ... } Kotlin @RequestScope @Component class LoginAction {   // ... } Session Scope Consider the following XML configuration for a bean definition: The Spring container creates a new instance of the UserPreferences bean by using the userPreferences bean definition for the lifetime of a single HTTP Session. In other words, the userPreferences bean is effectively scoped at the HTTP Session level. As with request-scoped beans, you can change the internal state of the instance that is created as much as you want, knowing that other HTTP Session instances that are also using instances created from the same userPreferences bean definition do not see these changes in state, because they are particular to an individual HTTP Session. When the HTTP Session is eventually discarded, the bean that is scoped to that particular HTTP Session is also discarded. When using annotation-driven components or Java configuration, you can use the @SessionScope annotation to assign a component to the session scope. Java @SessionScope @Component public class UserPreferences {   // ... } Kotlin @SessionScope @Component class UserPreferences {   // ... } Application Scope Consider the following XML configuration for a bean definition: The Spring container creates a new instance of the AppPreferences bean by using the appPreferences bean definition once for the entire web application. That is, the appPreferences bean is scoped at the ServletContext level and stored as a regular ServletContext attribute. This is somewhat similar to a Spring singleton bean but differs in two important ways: It is a singleton per ServletContext, not per Spring ApplicationContext (for which there may be several in any given web application), and it is actually exposed and therefore visible as a ServletContext attribute. When using annotation-driven components or Java configuration, you can use the @ApplicationScope annotation to assign a component to the application scope. The following example shows how to do so: Java @ApplicationScope @Component public class AppPreferences {   // ... } Kotlin @ApplicationScope @Component class AppPreferences {   // ... } WebSocket Scope WebSocket scope is associated with the lifecycle of a WebSocket session and applies to STOMP over WebSocket applications, see WebSocket scope for more details. Scoped Beans as Dependencies The Spring IoC container manages not only the instantiation of your objects (beans), but also the wiring up of collaborators (or dependencies). If you want to inject (for example) an HTTP request- scoped bean into another bean of a longer-lived scope, you may choose to inject an AOP proxy in place of the scoped bean. That is, you need to inject a proxy object that exposes the same public interface as the scoped object but that can also retrieve the real target object from the relevant scope (such as an HTTP request) and delegate method calls onto the real object. You may also use between beans that are scoped as singleton, with the reference then going through an intermediate proxy that is serializable and therefore able to re-obtain the target singleton bean on deserialization. When declaring against a bean of scope prototype, every method call on the shared proxy leads to the creation of a new target instance to which the call is then being forwarded. Also, scoped proxies are not the only way to access beans from shorter scopes in a lifecycle-safe fashion. You may also declare your injection point (that is, the  constructor or setter argument or autowired field) as ObjectFactory, allowing for a getObject() call to retrieve the current instance on demand every time it is needed — without holding on to the instance or storing it separately. As an extended variant, you may declare ObjectProvider which delivers several additional access variants, including getIfAvailable and getIfUnique. The JSR-330 variant of this is called Provider and is used with a Provider declaration and a corresponding get() call for every retrieval attempt. See here for more details on JSR-330 overall. The configuration in the following example is only one line, but it is important to understand the “why” as well as the “how” behind it:         ①             ① The line that defines the proxy. To create such a proxy, you insert a child element into a scoped bean definition (see Choosing the Type of Proxy to Create and XML Schema-based configuration). Why do definitions of beans scoped at the request, session and custom-scope levels require the element? Consider the following singleton bean definition and contrast it with what you need to define for the aforementioned scopes (note that the following userPreferences bean definition as it stands is incomplete):   In the preceding example, the singleton bean (userManager) is injected with a reference to the HTTP Session-scoped bean (userPreferences). The salient point here is that the userManager bean is a singleton: it is instantiated exactly once per container, and its dependencies (in this case only one, the userPreferences bean) are also injected only once. This means that the userManager bean operates only on the exact same userPreferences object (that is, the one with which it was originally injected). This is not the behavior you want when injecting a shorter-lived scoped bean into a longer-lived scoped bean (for example, injecting an HTTP Session-scoped collaborating bean as a dependency into singleton bean). Rather, you need a single userManager object, and, for the lifetime of an HTTP Session, you need a userPreferences object that is specific to the HTTP Session. Thus, the container creates an object that exposes the exact same public interface as the UserPreferences class (ideally an object that is a UserPreferences instance), which can fetch the real UserPreferences object from the scoping mechanism (HTTP request, Session, and so forth). The container injects this proxy object into the userManager bean, which is unaware that this UserPreferences reference is a proxy. In this example, when a UserManager instance invokes a method on the dependency-injected UserPreferences object, it is actually invoking a method on the proxy. The proxy then fetches the real UserPreferences object from (in this case) the HTTP Session and delegates the method invocation onto the retrieved real UserPreferences object. Thus, you need the following (correct and complete) configuration when injecting request- and session-scoped beans into collaborating objects, as the following example shows:     Choosing the Type of Proxy to Create By default, when the Spring container creates a proxy for a bean that is marked up with the element, a CGLIB-based class proxy is created. CGLIB proxies intercept only public method calls! Do not call non-public methods  on such a proxy. They are not delegated to the actual scoped target object. Alternatively, you can configure the Spring container to create standard JDK interface-based proxies for such scoped beans, by specifying false for the value of the proxy-target-class attribute of the element. Using JDK interface-based proxies means that you do not need additional libraries in your application classpath to affect such proxying. However, it also means that the class of the scoped bean must implement at least one interface and that all collaborators into which the scoped bean is injected must reference the bean through one of its interfaces. The following example shows a proxy based on an interface:     For more detailed information about choosing class-based or interface-based proxying, see Proxying Mechanisms. Custom Scopes The bean scoping mechanism is extensible. You can define your own scopes or even redefine existing scopes, although the latter is considered bad practice and you cannot override the built-in singleton and prototype scopes. Creating a Custom Scope To integrate your custom scopes into the Spring container, you need to implement the org.springframework.beans.factory.config.Scope interface, which is described in this section. For an idea of how to implement your own scopes, see the Scope implementations that are supplied with the Spring Framework itself and the Scope javadoc, which explains the methods you need to implement in more detail. The Scope interface has four methods to get objects from the scope, remove them from the scope, and let them be destroyed. The session scope implementation, for example, returns the session-scoped bean (if it does not exist, the method returns a new instance of the bean, after having bound it to the session for future reference). The following method returns the object from the underlying scope: Java Object get(String name, ObjectFactory objectFactory) Kotlin fun get(name: String, objectFactory: ObjectFactory<*>): Any The session scope implementation, for example, removes the session-scoped bean from the underlying session. The object should be returned, but you can return null if the object with the specified name is not found. The following method removes the object from the underlying scope: Java Object remove(String name) Kotlin fun remove(name: String): Any The following method registers a callback that the scope should invoke when it is destroyed or when the specified object in the scope is destroyed: Java void registerDestructionCallback(String name, Runnable destructionCallback) Kotlin fun registerDestructionCallback(name: String, destructionCallback: Runnable) See the javadoc or a Spring scope implementation for more information on destruction callbacks. The following method obtains the conversation identifier for the underlying scope: Java String getConversationId() Kotlin fun getConversationId(): String This identifier is different for each scope. For a session scoped implementation, this identifier can be the session identifier. Using a Custom Scope After you write and test one or more custom Scope implementations, you need to make the Spring container aware of your new scopes. The following method is the central method to register a new Scope with the Spring container: Java void registerScope(String scopeName, Scope scope); Kotlin fun registerScope(scopeName: String, scope: Scope) This method is declared on the ConfigurableBeanFactory interface, which is available through the BeanFactory property on most of the concrete ApplicationContext implementations that ship with Spring. The first argument to the registerScope(..) method is the unique name associated with a scope. Examples of such names in the Spring container itself are singleton and prototype. The second argument to the registerScope(..) method is an actual instance of the custom Scope implementation that you wish to register and use. Suppose that you write your custom Scope implementation, and then register it as shown in the next example. The next example uses SimpleThreadScope, which is included with Spring but is not  registered by default. The instructions would be the same for your own custom Scope implementations. Java Scope threadScope = new SimpleThreadScope(); beanFactory.registerScope("thread", threadScope); Kotlin val threadScope = SimpleThreadScope() beanFactory.registerScope("thread", threadScope) You can then create bean definitions that adhere to the scoping rules of your custom Scope, as follows: With a custom Scope implementation, you are not limited to programmatic registration of the scope. You can also do the Scope registration declaratively, by using the CustomScopeConfigurer class, as the following example shows:                                 When you place within a declaration for a FactoryBean  implementation, it is the factory bean itself that is scoped, not the object returned from getObject(). 2.1.6. Customizing the Nature of a Bean The Spring Framework provides a number of interfaces you can use to customize the nature of a bean. This section groups them as follows: • Lifecycle Callbacks • ApplicationContextAware and BeanNameAware • Other Aware Interfaces Lifecycle Callbacks To interact with the container’s management of the bean lifecycle, you can implement the Spring InitializingBean and DisposableBean interfaces. The container calls afterPropertiesSet() for the former and destroy() for the latter to let the bean perform certain actions upon initialization and destruction of your beans. The JSR-250 @PostConstruct and @PreDestroy annotations are generally considered best practice for receiving lifecycle callbacks in a modern Spring application. Using these annotations means that your beans are not coupled to Spring-specific  interfaces. For details, see Using @PostConstruct and @PreDestroy. If you do not want to use the JSR-250 annotations but you still want to remove coupling, consider init-method and destroy-method bean definition metadata. Internally, the Spring Framework uses BeanPostProcessor implementations to process any callback interfaces it can find and call the appropriate methods. If you need custom features or other lifecycle behavior Spring does not by default offer, you can implement a BeanPostProcessor yourself. For more information, see Container Extension Points. In addition to the initialization and destruction callbacks, Spring-managed objects may also implement the Lifecycle interface so that those objects can participate in the startup and shutdown process, as driven by the container’s own lifecycle. The lifecycle callback interfaces are described in this section. Initialization Callbacks The org.springframework.beans.factory.InitializingBean interface lets a bean perform initialization work after the container has set all necessary properties on the bean. The InitializingBean interface specifies a single method: void afterPropertiesSet() throws Exception; We recommend that you do not use the InitializingBean interface, because it unnecessarily couples the code to Spring. Alternatively, we suggest using the @PostConstruct annotation or specifying a POJO initialization method. In the case of XML-based configuration metadata, you can use the init- method attribute to specify the name of the method that has a void no-argument signature. With Java configuration, you can use the initMethod attribute of @Bean. See Receiving Lifecycle Callbacks. Consider the following example: Java public class ExampleBean {   public void init() {   // do some initialization work   } } Kotlin class ExampleBean {   fun init() {   // do some initialization work   } } The preceding example has almost exactly the same effect as the following example (which consists of two listings): Java public class AnotherExampleBean implements InitializingBean {   @Override   public void afterPropertiesSet() {   // do some initialization work   } } Kotlin class AnotherExampleBean : InitializingBean {   override fun afterPropertiesSet() {   // do some initialization work   } } However, the first of the two preceding examples does not couple the code to Spring. Destruction Callbacks Implementing the org.springframework.beans.factory.DisposableBean interface lets a bean get a callback when the container that contains it is destroyed. The DisposableBean interface specifies a single method: void destroy() throws Exception; We recommend that you do not use the DisposableBean callback interface, because it unnecessarily couples the code to Spring. Alternatively, we suggest using the @PreDestroy annotation or specifying a generic method that is supported by bean definitions. With XML-based configuration metadata, you can use the destroy-method attribute on the . With Java configuration, you can use the destroyMethod attribute of @Bean. See Receiving Lifecycle Callbacks. Consider the following definition: Java public class ExampleBean {   public void cleanup() {   // do some destruction work (like releasing pooled connections)   } } Kotlin class ExampleBean {   fun cleanup() {   // do some destruction work (like releasing pooled connections)   } } The preceding definition has almost exactly the same effect as the following definition: Java public class AnotherExampleBean implements DisposableBean {   @Override   public void destroy() {   // do some destruction work (like releasing pooled connections)   } } Kotlin class AnotherExampleBean : DisposableBean {   override fun destroy() {   // do some destruction work (like releasing pooled connections)   } } However, the first of the two preceding definitions does not couple the code to Spring. You can assign the destroy-method attribute of a element a special (inferred) value, which instructs Spring to automatically detect a public close or shutdown method on the specific bean class. (Any class that implements java.lang.AutoCloseable or java.io.Closeable would therefore match.) You can  also set this special (inferred) value on the default-destroy-method attribute of a element to apply this behavior to an entire set of beans (see Default Initialization and Destroy Methods). Note that this is the default behavior with Java configuration. Default Initialization and Destroy Methods When you write initialization and destroy method callbacks that do not use the Spring-specific InitializingBean and DisposableBean callback interfaces, you typically write methods with names such as init(), initialize(), dispose(), and so on. Ideally, the names of such lifecycle callback methods are standardized across a project so that all developers use the same method names and ensure consistency. You can configure the Spring container to “look” for named initialization and destroy callback method names on every bean. This means that you, as an application developer, can write your application classes and use an initialization callback called init(), without having to configure an init-method="init" attribute with each bean definition. The Spring IoC container calls that method when the bean is created (and in accordance with the standard lifecycle callback contract described previously). This feature also enforces a consistent naming convention for initialization and destroy method callbacks. Suppose that your initialization callback methods are named init() and your destroy callback methods are named destroy(). Your class then resembles the class in the following example: Java public class DefaultBlogService implements BlogService {   private BlogDao blogDao;   public void setBlogDao(BlogDao blogDao) {   this.blogDao = blogDao;   }   // this is (unsurprisingly) the initialization callback method   public void init() {   if (this.blogDao == null) {   throw new IllegalStateException("The [blogDao] property must be set.");   }   } } Kotlin class DefaultBlogService : BlogService {   private var blogDao: BlogDao? = null   // this is (unsurprisingly) the initialization callback method   fun init() {   if (blogDao == null) {   throw IllegalStateException("The [blogDao] property must be set.")   }   } } You could then use that class in a bean resembling the following:       The presence of the default-init-method attribute on the top-level element attribute causes the Spring IoC container to recognize a method called init on the bean class as the initialization method callback. When a bean is created and assembled, if the bean class has such a method, it is invoked at the appropriate time. You can configure destroy method callbacks similarly (in XML, that is) by using the default- destroy-method attribute on the top-level element. Where existing bean classes already have callback methods that are named at variance with the convention, you can override the default by specifying (in XML, that is) the method name by using the init-method and destroy-method attributes of the itself. The Spring container guarantees that a configured initialization callback is called immediately after a bean is supplied with all dependencies. Thus, the initialization callback is called on the raw bean reference, which means that AOP interceptors and so forth are not yet applied to the bean. A target bean is fully created first and then an AOP proxy (for example) with its interceptor chain is applied. If the target bean and the proxy are defined separately, your code can even interact with the raw target bean, bypassing the proxy. Hence, it would be inconsistent to apply the interceptors to the init method, because doing so would couple the lifecycle of the target bean to its proxy or interceptors and leave strange semantics when your code interacts directly with the raw target bean. --- ### Spring Ai Docs/Src/Main/Antora/Antora Playbook.Yml (spring-ai-docs/src/main/antora/antora-playbook.yml) # PACKAGES antora@3.2.0-alpha.6 @antora/atlas-extension:1.0.0-alpha.1 @antora/collector-extension@1.0.0-alpha.3 @springio/antora-extensions@1.1.0-alpha.2 @asciidoctor/tabs@1.0.0-alpha.12 @opendevise/antora-release-line-extension@1.0.0-alpha.2 # # The purpose of this Antora playbook is to build the docs in the current branch. antora: extensions: - '@antora/collector-extension' # - require: '@springio/antora-extensions/root-component-extension' - require: '@springio/antora-extensions' root_component_name: 'ai' site: title: Spring AI Reference url: https://docs.spring.io/spring-ai/reference robots: allow git: ensure_git_suffix: false content: sources: - url: ./../../../.. branches: HEAD start_path: spring-ai-docs/src/main/antora worktrees: true asciidoc: attributes: page-related-doc-categories: ai,java,ml page-pagination: '' hide-uri-scheme: '@' tabs-sync-option: '@' chomp: 'all' stem: 'asciimath' extensions: - '@asciidoctor/tabs' - '@springio/asciidoctor-extensions' - '@springio/asciidoctor-extensions/javadoc-extension' - '@springio/asciidoctor-extensions/include-code-extension' - '@djencks/asciidoctor-mathjax' sourcemap: true urls: latest_version_segment_strategy: redirect:to latest_version_segment: '' redirect_facility: httpd runtime: log: failure_level: warn format: pretty ui: bundle: url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.17/ui-bundle.zip snapshot: true --- ### Spring Ai Docs/Src/Main/Antora/Antora.Yml (spring-ai-docs/src/main/antora/antora.yml) name: ai version: true title: Spring AI nav: - modules/ROOT/nav.adoc ext: collector: - run: command: mvnw process-resources local: true scan: dir: spring-ai-docs/target/classes/antora-resources --- ### Spring Ai Docs/Src/Main/Antora/Resources/Antora Resources/Antora.Yml (spring-ai-docs/src/main/antora/resources/antora-resources/antora.yml) version: ${antora-component.version} prerelease: ${antora-component.prerelease} --- ### Spring Ai Docs/Src/Main/Asciidoc/Mcp (spring-ai-docs/src/main/asciidoc/mcp.md) # Model Context Protocol (MCP) Server The Spring AI MCP module provides integration with the Model Context Protocol, allowing you to expose your AI tools and resources through a standardized protocol. This module is particularly useful when you want to make your Spring AI tools and resources available to MCP-compatible clients. ## Dependencies To use the MCP server functionality, add the following dependency to your project: ```xml org.springframework.ai spring-ai-starter-mcp-server ${spring-ai.version} ``` ## Configuration Properties The MCP server can be configured using the following properties under the `spring.ai.mcp.server` prefix: | Property | Default | Description | |----------|---------|-------------| | `enabled` | `false` | Enable/disable the MCP server | | `name` | `"mcp-server"` | Name of the MCP server | | `version` | `"1.0.0"` | Version of the MCP server | | `type` | `SYNC` | Server type (`SYNC` or `ASYNC`) | | `resource-change-notification` | `true` | Enable/disable resource change notifications | | `tool-change-notification` | `true` | Enable/disable tool change notifications | | `prompt-change-notification` | `true` | Enable/disable prompt change notifications | | `transport` | `STDIO` | Transport type (`STDIO`, `WEBMVC`, or `WEBFLUX`) | | `sse-message-endpoint` | `"/mcp/message"` | Server-Sent Events (SSE) message endpoint for web transports | ## Server Types The MCP server supports two operation modes: ### 1. Synchronous Mode (Default) The synchronous mode is the default option, suitable for most use cases where tools and resources are accessed sequentially: ```yaml spring: ai: mcp: server: type: SYNC ``` ### 2. Asynchronous Mode The asynchronous mode is designed for reactive applications and scenarios requiring non-blocking operations: ```yaml spring: ai: mcp: server: type: ASYNC ``` ## Transport Options The MCP server supports three transport types: ### 1. STDIO Transport (Default) The Standard Input/Output transport is the default option, suitable for command-line tools and local development: ```yaml spring: ai: mcp: server: transport: STDIO ``` ### 2. WebMvc Transport The WebMvc transport uses Spring MVC's Server-Sent Events (SSE) for communication: ```yaml spring: ai: mcp: server: transport: WEBMVC sse-message-endpoint: /mcp/message # Optional, defaults to /mcp/message ``` Required dependencies: ```xml org.springframework.ai mcp-spring-webmvc org.springframework.boot spring-boot-starter-web ``` ### 3. WebFlux Transport The WebFlux transport uses Spring WebFlux's Server-Sent Events for reactive communication: ```yaml spring: ai: mcp: server: transport: WEBFLUX sse-message-endpoint: /mcp/message # Optional, defaults to /mcp/message ``` Required dependencies: ```xml org.springframework.ai mcp-spring-webflux org.springframework.boot spring-boot-starter-webflux ``` ## Core Features The MCP server provides several core features: ### Tools - Extensible tool registration system supporting both sync and async execution - Automatic tool discovery and registration through Spring's component scanning - Change notification support for tool updates ### Resources - Static and dynamic resource management - Optional change notifications for resource updates - Support for both sync and async resource access ### Prompts - Configurable prompt templates - Change notification support for template updates - Integration with Spring AI's prompt system ## Usage Example Here's an example of configuring the MCP server with WebMvc transport and custom settings: ```yaml spring: ai: mcp: server: enabled: true name: "My AI Tools Server" version: "1.0.0" type: SYNC transport: WEBMVC sse-message-endpoint: /ai/mcp/events resource-change-notification: true tool-change-notification: true prompt-change-notification: false ``` ## Auto-configuration The MCP server auto-configuration is provided through: 1. `McpServerAutoConfiguration`: Core server configuration supporting both sync and async modes 2. `McpWebMvcServerAutoConfiguration`: WebMvc transport configuration (activated when WebMvc dependencies are present) 3. `McpWebFluxServerAutoConfiguration`: WebFlux transport configuration (activated when WebFlux dependencies are present) The auto-configuration will automatically set up the appropriate server type and transport based on your configuration and available dependencies. ## Implementing Tools and Resources To expose your Spring AI tools and resources through the MCP server: 1. Implement the `ToolCallback` interface for your AI tools: ```java @Component public class MyAiTool implements ToolCallback { // Implementation } ``` 2. The auto-configuration will automatically discover and register your tools with the MCP server, converting them to either sync or async implementations based on your server type configuration. ## Monitoring The MCP server provides notifications for changes in: - Tools (when tools are added or removed) - Resources (when resources are updated) - Prompts (when prompt templates change) You can enable/disable these notifications using the configuration properties. The notification system works with both sync and async server types, providing consistent change tracking regardless of the chosen operation mode. --- ### Spring Ai Integration Tests/Src/Test/Resources/Application.Yml (spring-ai-integration-tests/src/test/resources/application.yml) spring: main: web-application-type: none ai: openai: api-key: ${OPENAI_API_KEY} chat: options: model: gpt-4o-mini embedding: options: model: text-embedding-ada-002 retry: max-attempts: 3 vectorstore: pgvector: initialize-schema: true --- ### Spring Ai Integration Tests/Src/Test/Resources/Documents/Knowledge Base (spring-ai-integration-tests/src/test/resources/documents/knowledge-base.md) # Anacletus and Birba's Quest for the Loch of the Stars ## Chapter 1: The Map and the Adventure Once upon a time, in a cozy little cottage nestled at the edge of the Scottish Highlands, lived an owl named Anacletus and a curious cat named Birba. Anacletus was wise and careful, always reading maps and planning things thoroughly, while Birba was lively and adventurous, always ready to chase after the next interesting thing. Despite their differences, they were the best of friends and loved going on little adventures together. ## Chapter 2: The Journey Begins One sunny morning, Anacletus showed Birba an old, crinkled map he’d found in the attic. “Look, Birba,” he said, pointing with his feathery wing. “This map leads to the legendary Loch of the Stars. They say it shines brighter than any other lake at night.” Birba’s eyes sparkled with excitement. “Oh, we have to go there!” she meowed. So, they packed a small bag with snacks, a compass, and a flashlight, and off they went, eager to find the legendary loch. ## Chapter 3: The Highland Adventure Their journey began with a climb up the rolling hills covered in purple heather. Anacletus flapped his wings, soaring ahead to scout for any obstacles, while Birba trotted along below, her nose sniffing the air for interesting scents. Soon, they came across a bubbling brook. Anacletus carefully flew over it, but Birba hesitated. “Just a little jump!” Anacletus called out. With a deep breath, Birba leaped and landed safely on the other side. She purred proudly, and they continued on their way. ## Chapter 4: The Highland Cows and the Hidden Path As they ventured deeper into the Highlands, they stumbled upon a herd of curious Highland cows with long, shaggy hair. The cows mooed softly, and one of them named Fergus approached. “Where are you two headed?” Fergus asked. “We’re searching for the Loch of the Stars!” Anacletus replied. Fergus nodded knowingly and pointed his nose north. “Follow the path by the big stones, and it will lead you closer to the loch,” he said. Thanking Fergus, they set off again, Birba occasionally stopping to bat at the fluttering butterflies along the way. ## Chapter 5: The Mysterious Forest and the Deer Family The day wore on, and they soon found themselves in a mysterious forest. Tall, ancient pine trees surrounded them, casting long shadows. “Stay close, Birba,” Anacletus whispered, his wise eyes scanning for any sign of danger. But Birba had already darted after a flicker of light, thinking it was a firefly. Anacletus sighed and followed her until they came to a hidden glade where a family of deer grazed quietly. The smallest fawn looked up and gave them a curious nod before they moved along. ## Chapter 6: The Loch of the Stars After a while, the sun began to set, painting the sky in shades of pink and gold. Anacletus decided it was a good time to rest. They found a cozy hollow at the base of a tree, where they shared the snacks they’d packed. Birba munched on her fish treats while Anacletus nibbled on a biscuit. “Do you think we’ll find the Loch of the Stars?” Birba asked, her eyes twinkling. “I think so,” Anacletus replied with a wise smile. “We’re getting closer.” ## Chapter 7: The Shimmering Loch As night fell, they finally reached the top of a hill where they could see a shimmering light in the distance. “Look, Birba!” Anacletus hooted excitedly. There, nestled among the hills, was the Loch of the Stars, gleaming like a sky full of stars. The two friends hurried down to the water’s edge, marveling at how the loch sparkled under the moonlight, casting a gentle glow all around. ## Chapter 8: The Magic of the Loch Birba dipped a curious paw into the water, causing ripples that sent stars dancing across the surface. “It’s beautiful!” she gasped. Anacletus nodded, his heart filled with awe. They spent the night by the loch, watching the shimmering stars reflected in the water, feeling as though they were surrounded by magic. ## Chapter 9: The Journey Home When dawn broke, the shimmering loch returned to its quiet, glassy calm. With a satisfied yawn, Birba stretched and said, “That was the best adventure yet.” Anacletus agreed, feeling a warmth in his feathers as they turned back toward home, carrying memories of the Loch of the Stars in their hearts. ## Chapter 10: The End of the Adventure And as they made their way back to their cozy cottage, they already started dreaming of their next big adventure—because Anacletus and Birba knew that the Scottish Highlands held endless wonders for those who dared to explore. --- ### Spring Ai Model/Src/Test/Resources/Text Source (spring-ai-model/src/test/resources/text_source.txt) Spring Framework Documentation Version 6.0.0 Chapter 1. Spring Framework Overview Spring makes it easy to create Java enterprise applications. It provides everything you need to embrace the Java language in an enterprise environment, with support for Groovy and Kotlin as alternative languages on the JVM, and with the flexibility to create many kinds of architectures depending on an application’s needs. As of Spring Framework 5.1, Spring requires JDK 8+ (Java SE 8+) and provides out-of-the-box support for JDK 11 LTS. Java SE 8 update 60 is suggested as the minimum patch release for Java 8, but it is generally recommended to use a recent patch release. Spring supports a wide range of application scenarios. In a large enterprise, applications often exist for a long time and have to run on a JDK and application server whose upgrade cycle is beyond developer control. Others may run as a single jar with the server embedded, possibly in a cloud environment. Yet others may be standalone applications (such as batch or integration workloads) that do not need a server. Spring is open source. It has a large and active community that provides continuous feedback based on a diverse range of real-world use cases. This has helped Spring to successfully evolve over a very long time. 1.1. What We Mean by "Spring" The term "Spring" means different things in different contexts. It can be used to refer to the Spring Framework project itself, which is where it all started. Over time, other Spring projects have been built on top of the Spring Framework. Most often, when people say "Spring", they mean the entire family of projects. This reference documentation focuses on the foundation: the Spring Framework itself. The Spring Framework is divided into modules. Applications can choose which modules they need. At the heart are the modules of the core container, including a configuration model and a dependency injection mechanism. Beyond that, the Spring Framework provides foundational support for different application architectures, including messaging, transactional data and persistence, and web. It also includes the Servlet-based Spring MVC web framework and, in parallel, the Spring WebFlux reactive web framework. A note about modules: Spring’s framework jars allow for deployment to JDK 9’s module path ("Jigsaw"). For use in Jigsaw-enabled applications, the Spring Framework 5 jars come with "Automatic-Module-Name" manifest entries which define stable language-level module names ("spring.core", "spring.context", etc.) independent from jar artifact names (the jars follow the same naming pattern with "-" instead of ".", e.g. "spring-core" and "spring-context"). Of course, Spring’s framework jars keep working fine on the classpath on both JDK 8 and 9+. 1.2. History of Spring and the Spring Framework Spring came into being in 2003 as a response to the complexity of the early J2EE specifications. While some consider Java EE and its modern-day successor Jakarta EE to be in competition with Spring, they are in fact complementary. The Spring programming model does not embrace the Jakarta EE platform specification; rather, it integrates with carefully selected individual specifications from the traditional EE umbrella: • Servlet API (JSR 340) • WebSocket API (JSR 356) • Concurrency Utilities (JSR 236) • JSON Binding API (JSR 367) • Bean Validation (JSR 303) • JPA (JSR 338) • JMS (JSR 914) • as well as JTA/JCA setups for transaction coordination, if necessary. The Spring Framework also supports the Dependency Injection (JSR 330) and Common Annotations (JSR 250) specifications, which application developers may choose to use instead of the Spring- specific mechanisms provided by the Spring Framework. Originally, those were based on common javax packages. As of Spring Framework 6.0, Spring has been upgraded to the Jakarta EE 9 level (e.g. Servlet 5.0+, JPA 3.0+), based on the jakarta namespace instead of the traditional javax packages. With EE 9 as the minimum and EE 10 supported already, Spring is prepared to provide out-of-the-box support for the further evolution of the Jakarta EE APIs. Spring Framework 6.0 is fully compatible with Tomcat 10.1, Jetty 11 and Undertow 2.3 as web servers, and also with Hibernate ORM 6.1. Over time, the role of Java/Jakarta EE in application development has evolved. In the early days of J2EE and Spring, applications were created to be deployed to an application server. Today, with the help of Spring Boot, applications are created in a devops- and cloud-friendly way, with the Servlet container embedded and trivial to change. As of Spring Framework 5, a WebFlux application does not even use the Servlet API directly and can run on servers (such as Netty) that are not Servlet containers. Spring continues to innovate and to evolve. Beyond the Spring Framework, there are other projects, such as Spring Boot, Spring Security, Spring Data, Spring Cloud, Spring Batch, among others. It’s important to remember that each project has its own source code repository, issue tracker, and release cadence. See spring.io/projects for the complete list of Spring projects. 1.3. Design Philosophy When you learn about a framework, it’s important to know not only what it does but what principles it follows. Here are the guiding principles of the Spring Framework: • Provide choice at every level. Spring lets you defer design decisions as late as possible. For example, you can switch persistence providers through configuration without changing your code. The same is true for many other infrastructure concerns and integration with third-party APIs. • Accommodate diverse perspectives. Spring embraces flexibility and is not opinionated about how things should be done. It supports a wide range of application needs with different perspectives. • Maintain strong backward compatibility. Spring’s evolution has been carefully managed to force few breaking changes between versions. Spring supports a carefully chosen range of JDK versions and third-party libraries to facilitate maintenance of applications and libraries that depend on Spring. • Care about API design. The Spring team puts a lot of thought and time into making APIs that are intuitive and that hold up across many versions and many years. • Set high standards for code quality. The Spring Framework puts a strong emphasis on meaningful, current, and accurate javadoc. It is one of very few projects that can claim clean code structure with no circular dependencies between packages. 1.4. Feedback and Contributions For how-to questions or diagnosing or debugging issues, we suggest using Stack Overflow. Click here for a list of the suggested tags to use on Stack Overflow. If you’re fairly certain that there is a problem in the Spring Framework or would like to suggest a feature, please use the GitHub Issues. If you have a solution in mind or a suggested fix, you can submit a pull request on Github. However, please keep in mind that, for all but the most trivial issues, we expect a ticket to be filed in the issue tracker, where discussions take place and leave a record for future reference. For more details see the guidelines at the CONTRIBUTING, top-level project page. 1.5. Getting Started If you are just getting started with Spring, you may want to begin using the Spring Framework by creating a Spring Boot-based application. Spring Boot provides a quick (and opinionated) way to create a production-ready Spring-based application. It is based on the Spring Framework, favors convention over configuration, and is designed to get you up and running as quickly as possible. You can use start.spring.io to generate a basic project or follow one of the "Getting Started" guides, such as Getting Started Building a RESTful Web Service. As well as being easier to digest, these guides are very task focused, and most of them are based on Spring Boot. They also cover other projects from the Spring portfolio that you might want to consider when solving a particular problem. Chapter 2. Core Technologies This part of the reference documentation covers all the technologies that are absolutely integral to the Spring Framework. Foremost amongst these is the Spring Framework’s Inversion of Control (IoC) container. A thorough treatment of the Spring Framework’s IoC container is closely followed by comprehensive coverage of Spring’s Aspect-Oriented Programming (AOP) technologies. The Spring Framework has its own AOP framework, which is conceptually easy to understand and which successfully addresses the 80% sweet spot of AOP requirements in Java enterprise programming. Coverage of Spring’s integration with AspectJ (currently the richest — in terms of features — and certainly most mature AOP implementation in the Java enterprise space) is also provided. AOT processing can be used to optimize your application ahead-of-time. It is typically used for native image deployment using GraalVM. 2.1. The IoC Container This chapter covers Spring’s Inversion of Control (IoC) container. 2.1.1. Introduction to the Spring IoC Container and Beans This chapter covers the Spring Framework implementation of the Inversion of Control (IoC) principle. IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes or a mechanism such as the Service Locator pattern. The org.springframework.beans and org.springframework.context packages are the basis for Spring Framework’s IoC container. The BeanFactory interface provides an advanced configuration mechanism capable of managing any type of object. ApplicationContext is a sub-interface of BeanFactory. It adds: • Easier integration with Spring’s AOP features • Message resource handling (for use in internationalization) • Event publication • Application-layer specific contexts such as the WebApplicationContext for use in web applications. In short, the BeanFactory provides the configuration framework and basic functionality, and the ApplicationContext adds more enterprise-specific functionality. The ApplicationContext is a complete superset of the BeanFactory and is used exclusively in this chapter in descriptions of Spring’s IoC container. For more information on using the BeanFactory instead of the ApplicationContext, see the section covering the BeanFactory API. In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container. 2.1.2. Container Overview The org.springframework.context.ApplicationContext interface represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the beans. The container gets its instructions on what objects to instantiate, configure, and assemble by reading configuration metadata. The configuration metadata is represented in XML, Java annotations, or Java code. It lets you express the objects that compose your application and the rich interdependencies between those objects. Several implementations of the ApplicationContext interface are supplied with Spring. In stand- alone applications, it is common to create an instance of ClassPathXmlApplicationContext or FileSystemXmlApplicationContext. While XML has been the traditional format for defining configuration metadata, you can instruct the container to use Java annotations or code as the metadata format by providing a small amount of XML configuration to declaratively enable support for these additional metadata formats. In most application scenarios, explicit user code is not required to instantiate one or more instances of a Spring IoC container. For example, in a web application scenario, a simple eight (or so) lines of boilerplate web descriptor XML in the web.xml file of the application typically suffices (see Convenient ApplicationContext Instantiation for Web Applications). If you use the Spring Tools for Eclipse (an Eclipse-powered development environment), you can easily create this boilerplate configuration with a few mouse clicks or keystrokes. The following diagram shows a high-level view of how Spring works. Your application classes are combined with configuration metadata so that, after the ApplicationContext is created and initialized, you have a fully configured and executable system or application. Figure 1. The Spring IoC container Configuration Metadata As the preceding diagram shows, the Spring IoC container consumes a form of configuration metadata. This configuration metadata represents how you, as an application developer, tell the Spring container to instantiate, configure, and assemble the objects in your application. Configuration metadata is traditionally supplied in a simple and intuitive XML format, which is what most of this chapter uses to convey key concepts and features of the Spring IoC container. XML-based metadata is not the only allowed form of configuration metadata. The Spring IoC container itself is totally decoupled from the format in which this  configuration metadata is actually written. These days, many developers choose Java-based configuration for their Spring applications. For information about using other forms of metadata with the Spring container, see: • Annotation-based configuration: Spring 2.5 introduced support for annotation-based configuration metadata. • Java-based configuration: Starting with Spring 3.0, many features provided by the Spring JavaConfig project became part of the core Spring Framework. Thus, you can define beans external to your application classes by using Java rather than XML files. To use these new features, see the @Configuration, @Bean, @Import, and @DependsOn annotations. Spring configuration consists of at least one and typically more than one bean definition that the container must manage. XML-based configuration metadata configures these beans as elements inside a top-level element. Java configuration typically uses @Bean-annotated methods within a @Configuration class. These bean definitions correspond to the actual objects that make up your application. Typically, you define service layer objects, data access objects (DAOs), presentation objects such as Struts Action instances, infrastructure objects such as Hibernate SessionFactories, JMS Queues, and so forth. Typically, one does not configure fine-grained domain objects in the container, because it is usually the responsibility of DAOs and business logic to create and load domain objects. However, you can use Spring’s integration with AspectJ to configure objects that have been created outside the control of an IoC container. See Using AspectJ to dependency-inject domain objects with Spring. The following example shows the basic structure of XML-based configuration metadata:   ① ②             ① The id attribute is a string that identifies the individual bean definition. ② The class attribute defines the type of the bean and uses the fully qualified classname. The value of the id attribute refers to collaborating objects. The XML for referring to collaborating objects is not shown in this example. See Dependencies for more information. Instantiating a Container The location path or paths supplied to an ApplicationContext constructor are resource strings that let the container load configuration metadata from a variety of external resources, such as the local file system, the Java CLASSPATH, and so on. Java ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml"); Kotlin val context = ClassPathXmlApplicationContext("services.xml", "daos.xml") After you learn about Spring’s IoC container, you may want to know more about Spring’s Resource abstraction (as described in Resources), which provides a  convenient mechanism for reading an InputStream from locations defined in a URI syntax. In particular, Resource paths are used to construct applications contexts, as described in Application Contexts and Resource Paths. The following example shows the service layer objects (services.xml) configuration file:               The following example shows the data access objects daos.xml file:               In the preceding example, the service layer consists of the PetStoreServiceImpl class and two data access objects of the types JpaAccountDao and JpaItemDao (based on the JPA Object-Relational Mapping standard). The property name element refers to the name of the JavaBean property, and the ref element refers to the name of another bean definition. This linkage between id and ref elements expresses the dependency between collaborating objects. For details of configuring an object’s dependencies, see Dependencies. Composing XML-based Configuration Metadata It can be useful to have bean definitions span multiple XML files. Often, each individual XML configuration file represents a logical layer or module in your architecture. You can use the application context constructor to load bean definitions from all these XML fragments. This constructor takes multiple Resource locations, as was shown in the previous section. Alternatively, use one or more occurrences of the element to load bean definitions from another file or files. The following example shows how to do so:           In the preceding example, external bean definitions are loaded from three files: services.xml, messageSource.xml, and themeSource.xml. All location paths are relative to the definition file doing the importing, so services.xml must be in the same directory or classpath location as the file doing the importing, while messageSource.xml and themeSource.xml must be in a resources location below the location of the importing file. As you can see, a leading slash is ignored. However, given that these paths are relative, it is better form not to use the slash at all. The contents of the files being imported, including the top level element, must be valid XML bean definitions, according to the Spring Schema. It is possible, but not recommended, to reference files in parent directories using a relative "../" path. Doing so creates a dependency on a file that is outside the current application. In particular, this reference is not recommended for classpath: URLs (for example, classpath:../services.xml), where the runtime resolution process chooses the “nearest” classpath root and then looks into its parent directory. Classpath configuration changes may lead to the choice of a different, incorrect directory.  You can always use fully qualified resource locations instead of relative paths: for example, file:C:/config/services.xml or classpath:/config/services.xml. However, be aware that you are coupling your application’s configuration to specific absolute locations. It is generally preferable to keep an indirection for such absolute locations — for example, through "${…}" placeholders that are resolved against JVM system properties at runtime. The namespace itself provides the import directive feature. Further configuration features beyond plain bean definitions are available in a selection of XML namespaces provided by Spring — for example, the context and util namespaces. The Groovy Bean Definition DSL As a further example for externalized configuration metadata, bean definitions can also be expressed in Spring’s Groovy Bean Definition DSL, as known from the Grails framework. Typically, such configuration live in a ".groovy" file with the structure shown in the following example: beans {   dataSource(BasicDataSource) {   driverClassName = "org.hsqldb.jdbcDriver"   url = "jdbc:hsqldb:mem:grailsDB"   username = "sa"   password = ""   settings = [mynew:"setting"]   }   sessionFactory(SessionFactory) {   dataSource = dataSource   }   myService(MyService) {   nestedBean = { AnotherBean bean ->   dataSource = dataSource   }   } } This configuration style is largely equivalent to XML bean definitions and even supports Spring’s XML configuration namespaces. It also allows for importing XML bean definition files through an importBeans directive. Using the Container The ApplicationContext is the interface for an advanced factory capable of maintaining a registry of different beans and their dependencies. By using the method T getBean(String name, Class requiredType), you can retrieve instances of your beans. The ApplicationContext lets you read bean definitions and access them, as the following example shows: Java // create and configure beans ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml"); // retrieve configured instance PetStoreService service = context.getBean("petStore", PetStoreService.class); // use configured instance List userList = service.getUsernameList(); Kotlin import org.springframework.beans.factory.getBean // create and configure beans val context = ClassPathXmlApplicationContext("services.xml", "daos.xml") // retrieve configured instance val service = context.getBean("petStore") // use configured instance var userList = service.getUsernameList() With Groovy configuration, bootstrapping looks very similar. It has a different context implementation class which is Groovy-aware (but also understands XML bean definitions). The following example shows Groovy configuration: Java ApplicationContext context = new GenericGroovyApplicationContext("services.groovy", "daos.groovy"); Kotlin val context = GenericGroovyApplicationContext("services.groovy", "daos.groovy") The most flexible variant is GenericApplicationContext in combination with reader delegates — for example, with XmlBeanDefinitionReader for XML files, as the following example shows: Java GenericApplicationContext context = new GenericApplicationContext(); new XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml"); context.refresh(); Kotlin val context = GenericApplicationContext() XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml") context.refresh() You can also use the GroovyBeanDefinitionReader for Groovy files, as the following example shows: Java GenericApplicationContext context = new GenericApplicationContext(); new GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy"); context.refresh(); Kotlin val context = GenericApplicationContext() GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy") context.refresh() You can mix and match such reader delegates on the same ApplicationContext, reading bean definitions from diverse configuration sources. You can then use getBean to retrieve instances of your beans. The ApplicationContext interface has a few other methods for retrieving beans, but, ideally, your application code should never use them. Indeed, your application code should have no calls to the getBean() method at all and thus have no dependency on Spring APIs at all. For example, Spring’s integration with web frameworks provides dependency injection for various web framework components such as controllers and JSF-managed beans, letting you declare a dependency on a specific bean through metadata (such as an autowiring annotation). 2.1.3. Bean Overview A Spring IoC container manages one or more beans. These beans are created with the configuration metadata that you supply to the container (for example, in the form of XML definitions). Within the container itself, these bean definitions are represented as BeanDefinition objects, which contain (among other information) the following metadata: • A package-qualified class name: typically, the actual implementation class of the bean being defined. • Bean behavioral configuration elements, which state how the bean should behave in the container (scope, lifecycle callbacks, and so forth). • References to other beans that are needed for the bean to do its work. These references are also called collaborators or dependencies. • Other configuration settings to set in the newly created object — for example, the size limit of the pool or the number of connections to use in a bean that manages a connection pool. This metadata translates to a set of properties that make up each bean definition. The following table describes these properties: Table 1. The bean definition Property Explained in… Class Instantiating Beans Name Naming Beans Scope Bean Scopes Constructor arguments Dependency Injection Properties Dependency Injection Autowiring mode Autowiring Collaborators Lazy initialization mode Lazy-initialized Beans Initialization method Initialization Callbacks Destruction method Destruction Callbacks In addition to bean definitions that contain information on how to create a specific bean, the ApplicationContext implementations also permit the registration of existing objects that are created outside the container (by users). This is done by accessing the ApplicationContext’s BeanFactory through the getBeanFactory() method, which returns the DefaultListableBeanFactory implementation. DefaultListableBeanFactory supports this registration through the registerSingleton(..) and registerBeanDefinition(..) methods. However, typical applications work solely with beans defined through regular bean definition metadata. Bean metadata and manually supplied singleton instances need to be registered as early as possible, in order for the container to properly reason about them during autowiring and other introspection steps. While overriding existing metadata and  existing singleton instances is supported to some degree, the registration of new beans at runtime (concurrently with live access to the factory) is not officially supported and may lead to concurrent access exceptions, inconsistent state in the bean container, or both. Naming Beans Every bean has one or more identifiers. These identifiers must be unique within the container that hosts the bean. A bean usually has only one identifier. However, if it requires more than one, the extra ones can be considered aliases. In XML-based configuration metadata, you use the id attribute, the name attribute, or both to specify the bean identifiers. The id attribute lets you specify exactly one id. Conventionally, these names are alphanumeric ('myBean', 'someService', etc.), but they can contain special characters as well. If you want to introduce other aliases for the bean, you can also specify them in the name attribute, separated by a comma (,), semicolon (;), or white space. As a historical note, in versions prior to Spring 3.1, the id attribute was defined as an xsd:ID type, which constrained possible characters. As of 3.1, it is defined as an xsd:string type. Note that bean id uniqueness is still enforced by the container, though no longer by XML parsers. You are not required to supply a name or an id for a bean. If you do not supply a name or id explicitly, the container generates a unique name for that bean. However, if you want to refer to that bean by name, through the use of the ref element or a Service Locator style lookup, you must provide a name. Motivations for not supplying a name are related to using inner beans and autowiring collaborators. Bean Naming Conventions The convention is to use the standard Java convention for instance field names when naming beans. That is, bean names start with a lowercase letter and are camel-cased from there. Examples of such names include accountManager, accountService, userDao, loginController, and so forth. Naming beans consistently makes your configuration easier to read and understand. Also, if you use Spring AOP, it helps a lot when applying advice to a set of beans related by name. With component scanning in the classpath, Spring generates bean names for unnamed components, following the rules described earlier: essentially, taking the simple class name and turning its initial character to lower-case. However, in the  (unusual) special case when there is more than one character and both the first and second characters are upper case, the original casing gets preserved. These are the same rules as defined by java.beans.Introspector.decapitalize (which Spring uses here). Aliasing a Bean outside the Bean Definition In a bean definition itself, you can supply more than one name for the bean, by using a combination of up to one name specified by the id attribute and any number of other names in the name attribute. These names can be equivalent aliases to the same bean and are useful for some situations, such as letting each component in an application refer to a common dependency by using a bean name that is specific to that component itself. Specifying all aliases where the bean is actually defined is not always adequate, however. It is sometimes desirable to introduce an alias for a bean that is defined elsewhere. This is commonly the case in large systems where configuration is split amongst each subsystem, with each subsystem having its own set of object definitions. In XML-based configuration metadata, you can use the element to accomplish this. The following example shows how to do so: In this case, a bean (in the same container) named fromName may also, after the use of this alias definition, be referred to as toName. For example, the configuration metadata for subsystem A may refer to a DataSource by the name of subsystemA-dataSource. The configuration metadata for subsystem B may refer to a DataSource by the name of subsystemB-dataSource. When composing the main application that uses both these subsystems, the main application refers to the DataSource by the name of myApp-dataSource. To have all three names refer to the same object, you can add the following alias definitions to the configuration metadata: Now each component and the main application can refer to the dataSource through a name that is unique and guaranteed not to clash with any other definition (effectively creating a namespace), yet they refer to the same bean. Java-configuration If you use Javaconfiguration, the @Bean annotation can be used to provide aliases. See Using the @Bean Annotation for details. Instantiating Beans A bean definition is essentially a recipe for creating one or more objects. The container looks at the recipe for a named bean when asked and uses the configuration metadata encapsulated by that bean definition to create (or acquire) an actual object. If you use XML-based configuration metadata, you specify the type (or class) of object that is to be instantiated in the class attribute of the element. This class attribute (which, internally, is a Class property on a BeanDefinition instance) is usually mandatory. (For exceptions, see Instantiation by Using an Instance Factory Method and Bean Definition Inheritance.) You can use the Class property in one of two ways: • Typically, to specify the bean class to be constructed in the case where the container itself directly creates the bean by calling its constructor reflectively, somewhat equivalent to Java code with the new operator. • To specify the actual class containing the static factory method that is invoked to create the object, in the less common case where the container invokes a static factory method on a class to create the bean. The object type returned from the invocation of the static factory method may be the same class or another class entirely. Nested class names If you want to configure a bean definition for a nested class, you may use either the binary name or the source name of the nested class. For example, if you have a class called SomeThing in the com.example package, and this SomeThing class has a static nested class called OtherThing, they can be separated by a dollar sign ($) or a dot (.). So the value of the class attribute in a bean definition would be com.example.SomeThing$OtherThing or com.example.SomeThing.OtherThing. Instantiation with a Constructor When you create a bean by the constructor approach, all normal classes are usable by and compatible with Spring. That is, the class being developed does not need to implement any specific interfaces or to be coded in a specific fashion. Simply specifying the bean class should suffice. However, depending on what type of IoC you use for that specific bean, you may need a default (empty) constructor. The Spring IoC container can manage virtually any class you want it to manage. It is not limited to managing true JavaBeans. Most Spring users prefer actual JavaBeans with only a default (no- argument) constructor and appropriate setters and getters modeled after the properties in the container. You can also have more exotic non-bean-style classes in your container. If, for example, you need to use a legacy connection pool that absolutely does not adhere to the JavaBean specification, Spring can manage it as well. With XML-based configuration metadata you can specify your bean class as follows: For details about the mechanism for supplying arguments to the constructor (if required) and setting object instance properties after the object is constructed, see Injecting Dependencies. Instantiation with a Static Factory Method When defining a bean that you create with a static factory method, use the class attribute to specify the class that contains the static factory method and an attribute named factory-method to specify the name of the factory method itself. You should be able to call this method (with optional arguments, as described later) and return a live object, which subsequently is treated as if it had been created through a constructor. One use for such a bean definition is to call static factories in legacy code. The following bean definition specifies that the bean will be created by calling a factory method. The definition does not specify the type (class) of the returned object, but rather the class containing the factory method. In this example, the createInstance() method must be a static method. The following example shows how to specify a factory method: The following example shows a class that would work with the preceding bean definition: Java public class ClientService {   private static ClientService clientService = new ClientService();   private ClientService() {}   public static ClientService createInstance() {   return clientService;   } } Kotlin class ClientService private constructor() {   companion object {   private val clientService = ClientService()   @JvmStatic   fun createInstance() = clientService   } } For details about the mechanism for supplying (optional) arguments to the factory method and setting object instance properties after the object is returned from the factory, see Dependencies and Configuration in Detail. Instantiation by Using an Instance Factory Method Similar to instantiation through a static factory method, instantiation with an instance factory method invokes a non-static method of an existing bean from the container to create a new bean. To use this mechanism, leave the class attribute empty and, in the factory-bean attribute, specify the name of a bean in the current (or parent or ancestor) container that contains the instance method that is to be invoked to create the object. Set the name of the factory method itself with the factory-method attribute. The following example shows how to configure such a bean:   The following example shows the corresponding class: Java public class DefaultServiceLocator {   private static ClientService clientService = new ClientServiceImpl();   public ClientService createClientServiceInstance() {   return clientService;   } } Kotlin class DefaultServiceLocator {   companion object {   private val clientService = ClientServiceImpl()   }   fun createClientServiceInstance(): ClientService {   return clientService   } } One factory class can also hold more than one factory method, as the following example shows:   The following example shows the corresponding class: Java public class DefaultServiceLocator {   private static ClientService clientService = new ClientServiceImpl();   private static AccountService accountService = new AccountServiceImpl();   public ClientService createClientServiceInstance() {   return clientService;   }   public AccountService createAccountServiceInstance() {   return accountService;   } } Kotlin class DefaultServiceLocator {   companion object {   private val clientService = ClientServiceImpl()   private val accountService = AccountServiceImpl()   }   fun createClientServiceInstance(): ClientService {   return clientService   }   fun createAccountServiceInstance(): AccountService {   return accountService   } } This approach shows that the factory bean itself can be managed and configured through dependency injection (DI). See Dependencies and Configuration in Detail. In Spring documentation, "factory bean" refers to a bean that is configured in the Spring container and that creates objects through an instance or static factory  method. By contrast, FactoryBean (notice the capitalization) refers to a Spring- specific FactoryBean implementation class. Determining a Bean’s Runtime Type The runtime type of a specific bean is non-trivial to determine. A specified class in the bean metadata definition is just an initial class reference, potentially combined with a declared factory method or being a FactoryBean class which may lead to a different runtime type of the bean, or not being set at all in case of an instance-level factory method (which is resolved via the specified factory-bean name instead). Additionally, AOP proxying may wrap a bean instance with an interface-based proxy with limited exposure of the target bean’s actual type (just its implemented interfaces). The recommended way to find out about the actual runtime type of a particular bean is a BeanFactory.getType call for the specified bean name. This takes all of the above cases into account and returns the type of object that a BeanFactory.getBean call is going to return for the same bean name. 2.1.4. Dependencies A typical enterprise application does not consist of a single object (or bean in the Spring parlance). Even the simplest application has a few objects that work together to present what the end-user sees as a coherent application. This next section explains how you go from defining a number of bean definitions that stand alone to a fully realized application where objects collaborate to achieve a goal. Dependency Injection Dependency injection (DI) is a process whereby objects define their dependencies (that is, the other objects with which they work) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies on its own by using direct construction of classes or the Service Locator pattern. Code is cleaner with the DI principle, and decoupling is more effective when objects are provided with their dependencies. The object does not look up its dependencies and does not know the location or class of the dependencies. As a result, your classes become easier to test, particularly when the dependencies are on interfaces or abstract base classes, which allow for stub or mock implementations to be used in unit tests. DI exists in two major variants: Constructor-based dependency injection and Setter-based dependency injection. Constructor-based Dependency Injection Constructor-based DI is accomplished by the container invoking a constructor with a number of arguments, each representing a dependency. Calling a static factory method with specific arguments to construct the bean is nearly equivalent, and this discussion treats arguments to a constructor and to a static factory method similarly. The following example shows a class that can only be dependency-injected with constructor injection: Java public class SimpleMovieLister {   // the SimpleMovieLister has a dependency on a MovieFinder   private final MovieFinder movieFinder;   // a constructor so that the Spring container can inject a MovieFinder   public SimpleMovieLister(MovieFinder movieFinder) {   this.movieFinder = movieFinder;   }   // business logic that actually uses the injected MovieFinder is omitted... } Kotlin // a constructor so that the Spring container can inject a MovieFinder class SimpleMovieLister(private val movieFinder: MovieFinder) {   // business logic that actually uses the injected MovieFinder is omitted... } Notice that there is nothing special about this class. It is a POJO that has no dependencies on container specific interfaces, base classes, or annotations. Constructor Argument Resolution Constructor argument resolution matching occurs by using the argument’s type. If no potential ambiguity exists in the constructor arguments of a bean definition, the order in which the constructor arguments are defined in a bean definition is the order in which those arguments are supplied to the appropriate constructor when the bean is being instantiated. Consider the following class: Java package x.y; public class ThingOne {   public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {   // ...   } } Kotlin package x.y class ThingOne(thingTwo: ThingTwo, thingThree: ThingThree) Assuming that the ThingTwo and ThingThree classes are not related by inheritance, no potential ambiguity exists. Thus, the following configuration works fine, and you do not need to specify the constructor argument indexes or types explicitly in the element.             When another bean is referenced, the type is known, and matching can occur (as was the case with the preceding example). When a simple type is used, such as true, Spring cannot determine the type of the value, and so cannot match by type without help. Consider the following class: Java package examples; public class ExampleBean {   // Number of years to calculate the Ultimate Answer   private final int years;   // The Answer to Life, the Universe, and Everything   private final String ultimateAnswer;   public ExampleBean(int years, String ultimateAnswer) {   this.years = years;   this.ultimateAnswer = ultimateAnswer;   } } Kotlin package examples class ExampleBean(   private val years: Int, // Number of years to calculate the Ultimate Answer   private val ultimateAnswer: String // The Answer to Life, the Universe, and Everything ) Constructor argument type matching In the preceding scenario, the container can use type matching with simple types if you explicitly specify the type of the constructor argument by using the type attribute, as the following example shows:     Constructor argument index You can use the index attribute to specify explicitly the index of constructor arguments, as the following example shows:     In addition to resolving the ambiguity of multiple simple values, specifying an index resolves ambiguity where a constructor has two arguments of the same type.  The index is 0-based. Constructor argument name You can also use the constructor parameter name for value disambiguation, as the following example shows:     Keep in mind that, to make this work out of the box, your code must be compiled with the debug flag enabled so that Spring can look up the parameter name from the constructor. If you cannot or do not want to compile your code with the debug flag, you can use the @ConstructorProperties JDK annotation to explicitly name your constructor arguments. The sample class would then have to look as follows: Java package examples; public class ExampleBean {   // Fields omitted   @ConstructorProperties({"years", "ultimateAnswer"})   public ExampleBean(int years, String ultimateAnswer) {   this.years = years;   this.ultimateAnswer = ultimateAnswer;   } } Kotlin package examples class ExampleBean @ConstructorProperties("years", "ultimateAnswer") constructor(val years: Int, val ultimateAnswer: String) Setter-based Dependency Injection Setter-based DI is accomplished by the container calling setter methods on your beans after invoking a no-argument constructor or a no-argument static factory method to instantiate your bean. The following example shows a class that can only be dependency-injected by using pure setter injection. This class is conventional Java. It is a POJO that has no dependencies on container specific interfaces, base classes, or annotations. Java public class SimpleMovieLister {   // the SimpleMovieLister has a dependency on the MovieFinder   private MovieFinder movieFinder;   // a setter method so that the Spring container can inject a MovieFinder   public void setMovieFinder(MovieFinder movieFinder) {   this.movieFinder = movieFinder;   }   // business logic that actually uses the injected MovieFinder is omitted... } Kotlin class SimpleMovieLister {   // a late-initialized property so that the Spring container can inject a MovieFinder   lateinit var movieFinder: MovieFinder   // business logic that actually uses the injected MovieFinder is omitted... } The ApplicationContext supports constructor-based and setter-based DI for the beans it manages. It also supports setter-based DI after some dependencies have already been injected through the constructor approach. You configure the dependencies in the form of a BeanDefinition, which you use in conjunction with PropertyEditor instances to convert properties from one format to another. However, most Spring users do not work with these classes directly (that is, programmatically) but rather with XML bean definitions, annotated components (that is, classes annotated with @Component, @Controller, and so forth), or @Bean methods in Java-based @Configuration classes. These sources are then converted internally into instances of BeanDefinition and used to load an entire Spring IoC container instance. Constructor-based or setter-based DI? Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies. Note that use of the @Autowired annotation on a setter method can be used to make the property be a required dependency; however, constructor injection with programmatic validation of arguments is preferable. The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null. Furthermore, constructor-injected components are always returned to the client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns. Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection. Use the DI style that makes the most sense for a particular class. Sometimes, when dealing with third-party classes for which you do not have the source, the choice is made for you. For example, if a third-party class does not expose any setter methods, then constructor injection may be the only available form of DI. Dependency Resolution Process The container performs bean dependency resolution as follows: • The ApplicationContext is created and initialized with configuration metadata that describes all the beans. Configuration metadata can be specified by XML, Java code, or annotations. • For each bean, its dependencies are expressed in the form of properties, constructor arguments, or arguments to the static-factory method (if you use that instead of a normal constructor). These dependencies are provided to the bean, when the bean is actually created. • Each property or constructor argument is an actual definition of the value to set, or a reference to another bean in the container. • Each property or constructor argument that is a value is converted from its specified format to the actual type of that property or constructor argument. By default, Spring can convert a value supplied in string format to all built-in types, such as int, long, String, boolean, and so forth. The Spring container validates the configuration of each bean as the container is created. However, the bean properties themselves are not set until the bean is actually created. Beans that are singleton-scoped and set to be pre-instantiated (the default) are created when the container is created. Scopes are defined in Bean Scopes. Otherwise, the bean is created only when it is requested. Creation of a bean potentially causes a graph of beans to be created, as the bean’s dependencies and its dependencies' dependencies (and so on) are created and assigned. Note that resolution mismatches among those dependencies may show up late — that is, on first creation of the affected bean. Circular dependencies If you use predominantly constructor injection, it is possible to create an unresolvable circular dependency scenario. For example: Class A requires an instance of class B through constructor injection, and class B requires an instance of class A through constructor injection. If you configure beans for classes A and B to be injected into each other, the Spring IoC container detects this circular reference at runtime, and throws a BeanCurrentlyInCreationException. One possible solution is to edit the source code of some classes to be configured by setters rather than constructors. Alternatively, avoid constructor injection and use setter injection only. In other words, although it is not recommended, you can configure circular dependencies with setter injection. Unlike the typical case (with no circular dependencies), a circular dependency between bean A and bean B forces one of the beans to be injected into the other prior to being fully initialized itself (a classic chicken-and-egg scenario). You can generally trust Spring to do the right thing. It detects configuration problems, such as references to non-existent beans and circular dependencies, at container load-time. Spring sets properties and resolves dependencies as late as possible, when the bean is actually created. This means that a Spring container that has loaded correctly can later generate an exception when you request an object if there is a problem creating that object or one of its dependencies — for example, the bean throws an exception as a result of a missing or invalid property. This potentially delayed visibility of some configuration issues is why ApplicationContext implementations by default pre-instantiate singleton beans. At the cost of some upfront time and memory to create these beans before they are actually needed, you discover configuration issues when the ApplicationContext is created, not later. You can still override this default behavior so that singleton beans initialize lazily, rather than being eagerly pre-instantiated. If no circular dependencies exist, when one or more collaborating beans are being injected into a dependent bean, each collaborating bean is totally configured prior to being injected into the dependent bean. This means that, if bean A has a dependency on bean B, the Spring IoC container completely configures bean B prior to invoking the setter method on bean A. In other words, the bean is instantiated (if it is not a pre-instantiated singleton), its dependencies are set, and the relevant lifecycle methods (such as a configured init method or the InitializingBean callback method) are invoked. Examples of Dependency Injection The following example uses XML-based configuration metadata for setter-based DI. A small part of a Spring XML configuration file specifies some bean definitions as follows:               The following example shows the corresponding ExampleBean class: Java public class ExampleBean {   private AnotherBean beanOne;   private YetAnotherBean beanTwo;   private int i;   public void setBeanOne(AnotherBean beanOne) {   this.beanOne = beanOne;   }   public void setBeanTwo(YetAnotherBean beanTwo) {   this.beanTwo = beanTwo;   }   public void setIntegerProperty(int i) {   this.i = i;   } } Kotlin class ExampleBean {   lateinit var beanOne: AnotherBean   lateinit var beanTwo: YetAnotherBean   var i: Int = 0 } In the preceding example, setters are declared to match against the properties specified in the XML file. The following example uses constructor-based DI:               The following example shows the corresponding ExampleBean class: Java public class ExampleBean {   private AnotherBean beanOne;   private YetAnotherBean beanTwo;   private int i;   public ExampleBean(   AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {   this.beanOne = anotherBean;   this.beanTwo = yetAnotherBean;   this.i = i;   } } Kotlin class ExampleBean(   private val beanOne: AnotherBean,   private val beanTwo: YetAnotherBean,   private val i: Int) The constructor arguments specified in the bean definition are used as arguments to the constructor of the ExampleBean. Now consider a variant of this example, where, instead of using a constructor, Spring is told to call a static factory method to return an instance of the object:       The following example shows the corresponding ExampleBean class: Java public class ExampleBean {   // a private constructor   private ExampleBean(...) {   ...   }   // a static factory method; the arguments to this method can be   // considered the dependencies of the bean that is returned,   // regardless of how those arguments are actually used.   public static ExampleBean createInstance (   AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {   ExampleBean eb = new ExampleBean (...);   // some other operations...   return eb;   } } Kotlin class ExampleBean private constructor() {   companion object {   // a static factory method; the arguments to this method can be   // considered the dependencies of the bean that is returned,   // regardless of how those arguments are actually used.   @JvmStatic   fun createInstance(anotherBean: AnotherBean, yetAnotherBean: YetAnotherBean, i: Int): ExampleBean {   val eb = ExampleBean (...)   // some other operations...   return eb   }   } } Arguments to the static factory method are supplied by elements, exactly the same as if a constructor had actually been used. The type of the class being returned by the factory method does not have to be of the same type as the class that contains the static factory method (although, in this example, it is). An instance (non-static) factory method can be used in an essentially identical fashion (aside from the use of the factory-bean attribute instead of the class attribute), so we do not discuss those details here. Dependencies and Configuration in Detail As mentioned in the previous section, you can define bean properties and constructor arguments as references to other managed beans (collaborators) or as values defined inline. Spring’s XML-based configuration metadata supports sub-element types within its and elements for this purpose. Straight Values (Primitives, Strings, and so on) The value attribute of the element specifies a property or constructor argument as a human-readable string representation. Spring’s conversion service is used to convert these values from a String to the actual type of the property or argument. The following example shows various values being set:           The following example uses the p-namespace for even more succinct XML configuration:   The preceding XML is more succinct. However, typos are discovered at runtime rather than design time, unless you use an IDE (such as IntelliJ IDEA or the Spring Tools for Eclipse) that supports automatic property completion when you create bean definitions. Such IDE assistance is highly recommended. You can also configure a java.util.Properties instance, as follows:         jdbc.driver.className=com.mysql.jdbc.Driver   jdbc.url=jdbc:mysql://localhost:3306/mydb     The Spring container converts the text inside the element into a java.util.Properties instance by using the JavaBeans PropertyEditor mechanism. This is a nice shortcut, and is one of a few places where the Spring team do favor the use of the nested element over the value attribute style. The idref element The idref element is simply an error-proof way to pass the id (a string value - not a reference) of another bean in the container to a or element. The following example shows how to use it:       The preceding bean definition snippet is exactly equivalent (at runtime) to the following snippet:   The first form is preferable to the second, because using the idref tag lets the container validate at deployment time that the referenced, named bean actually exists. In the second variation, no validation is performed on the value that is passed to the targetName property of the client bean. Typos are only discovered (with most likely fatal results) when the client bean is actually instantiated. If the client bean is a prototype bean, this typo and the resulting exception may only be discovered long after the container is deployed. The local attribute on the idref element is no longer supported in the 4.0 beans XSD, since it does not provide value over a regular bean reference any more.  Change your existing idref local references to idref bean when upgrading to the 4.0 schema. A common place (at least in versions earlier than Spring 2.0) where the element brings value is in the configuration of AOP interceptors in a ProxyFactoryBean bean definition. Using elements when you specify the interceptor names prevents you from misspelling an interceptor ID. References to Other Beans (Collaborators) The ref element is the final element inside a or definition element. Here, you set the value of the specified property of a bean to be a reference to another bean (a collaborator) managed by the container. The referenced bean is a dependency of the bean whose property is to be set, and it is initialized on demand as needed before the property is set. (If the collaborator is a singleton bean, it may already be initialized by the container.) All references are ultimately a reference to another object. Scoping and validation depend on whether you specify the ID or name of the other object through the bean or parent attribute. Specifying the target bean through the bean attribute of the tag is the most general form and allows creation of a reference to any bean in the same container or parent container, regardless of whether it is in the same XML file. The value of the bean attribute may be the same as the id attribute of the target bean or be the same as one of the values in the name attribute of the target bean. The following example shows how to use a ref element: Specifying the target bean through the parent attribute creates a reference to a bean that is in a parent container of the current container. The value of the parent attribute may be the same as either the id attribute of the target bean or one of the values in the name attribute of the target bean. The target bean must be in a parent container of the current one. You should use this bean reference variant mainly when you have a hierarchy of containers and you want to wrap an existing bean in a parent container with a proxy that has the same name as the parent bean. The following pair of listings shows how to use the parent attribute:           The local attribute on the ref element is no longer supported in the 4.0 beans XSD,  since it does not provide value over a regular bean reference any more. Change your existing ref local references to ref bean when upgrading to the 4.0 schema. Inner Beans A element inside the or elements defines an inner bean, as the following example shows:               An inner bean definition does not require a defined ID or name. If specified, the container does not use such a value as an identifier. The container also ignores the scope flag on creation, because inner beans are always anonymous and are always created with the outer bean. It is not possible to access inner beans independently or to inject them into collaborating beans other than into the enclosing bean. As a corner case, it is possible to receive destruction callbacks from a custom scope — for example, for a request-scoped inner bean contained within a singleton bean. The creation of the inner bean instance is tied to its containing bean, but destruction callbacks let it participate in the request scope’s lifecycle. This is not a common scenario. Inner beans typically simply share their containing bean’s scope. Collections The , , , and elements set the properties and arguments of the Java Collection types List, Set, Map, and Properties, respectively. The following example shows how to use them:         administrator@example.org   support@example.org   development@example.org             a list element followed by a reference                             just some string       The value of a map key or value, or a set value, can also be any of the following elements: bean | ref | idref | list | set | map | props | value | null Collection Merging The Spring container also supports merging collections. An application developer can define a parent , , or element and have child , , or elements inherit and override values from the parent collection. That is, the child collection’s values are the result of merging the elements of the parent and child collections, with the child’s collection elements overriding values specified in the parent collection. This section on merging discusses the parent-child bean mechanism. Readers unfamiliar with parent and child bean definitions may wish to read the relevant section before continuing. The following example demonstrates collection merging:         administrator@example.com   support@example.com                 sales@example.com   support@example.co.uk       Notice the use of the merge=true attribute on the element of the adminEmails property of the child bean definition. When the child bean is resolved and instantiated by the container, the resulting instance has an adminEmails Properties collection that contains the result of merging the child’s adminEmails collection with the parent’s adminEmails collection. The following listing shows the result: administrator=administrator@example.com sales=sales@example.com support=support@example.co.uk The child Properties collection’s value set inherits all property elements from the parent , and the child’s value for the support value overrides the value in the parent collection. This merging behavior applies similarly to the , , and collection types. In the specific case of the element, the semantics associated with the List collection type (that is, the notion of an ordered collection of values) is maintained. The parent’s values precede all of the child list’s values. In the case of the Map, Set, and Properties collection types, no ordering exists. Hence, no ordering semantics are in effect for the collection types that underlie the associated Map, Set, and Properties implementation types that the container uses internally. Limitations of Collection Merging You cannot merge different collection types (such as a Map and a List). If you do attempt to do so, an appropriate Exception is thrown. The merge attribute must be specified on the lower, inherited, child definition. Specifying the merge attribute on a parent collection definition is redundant and does not result in the desired merging. Strongly-typed collection Thanks to Java’s support for generic types, you can use strongly typed collections. That is, it is possible to declare a Collection type such that it can only contain (for example) String elements. If you use Spring to dependency-inject a strongly-typed Collection into a bean, you can take advantage of Spring’s type-conversion support such that the elements of your strongly-typed Collection instances are converted to the appropriate type prior to being added to the Collection. The following Java class and bean definition show how to do so: Java public class SomeClass {   private Map accounts;   public void setAccounts(Map accounts) {   this.accounts = accounts;   } } Kotlin class SomeClass {   lateinit var accounts: Map }                   When the accounts property of the something bean is prepared for injection, the generics information about the element type of the strongly-typed Map is available by reflection. Thus, Spring’s type conversion infrastructure recognizes the various value elements as being of type Float, and the string values (9.99, 2.75, and 3.99) are converted into an actual Float type. Null and Empty String Values Spring treats empty arguments for properties and the like as empty Strings. The following XML- based configuration metadata snippet sets the email property to the empty String value ("").   The preceding example is equivalent to the following Java code: Java exampleBean.setEmail(""); Kotlin exampleBean.email = "" The element handles null values. The following listing shows an example:       The preceding configuration is equivalent to the following Java code: Java exampleBean.setEmail(null); Kotlin exampleBean.email = null XML Shortcut with the p-namespace The p-namespace lets you use the bean element’s attributes (instead of nested elements) to describe your property values collaborating beans, or both. Spring supports extensible configuration formats with namespaces, which are based on an XML Schema definition. The beans configuration format discussed in this chapter is defined in an XML Schema document. However, the p-namespace is not defined in an XSD file and exists only in the core of Spring. The following example shows two XML snippets (the first uses standard XML format and the second uses the p-namespace) that resolve to the same result:         The example shows an attribute in the p-namespace called email in the bean definition. This tells Spring to include a property declaration. As previously mentioned, the p-namespace does not have a schema definition, so you can set the name of the attribute to the property name. This next example includes two more bean definitions that both have a reference to another bean:                 This example includes not only a property value using the p-namespace but also uses a special format to declare property references. Whereas the first bean definition uses to create a reference from bean john to bean jane, the second bean definition uses p:spouse-ref="jane" as an attribute to do the exact same thing. In this case, spouse is the property name, whereas the -ref part indicates that this is not a straight value but rather a reference to another bean. The p-namespace is not as flexible as the standard XML format. For example, the format for declaring property references clashes with properties that end in Ref,  whereas the standard XML format does not. We recommend that you choose your approach carefully and communicate this to your team members to avoid producing XML documents that use all three approaches at the same time. XML Shortcut with the c-namespace Similar to the XML Shortcut with the p-namespace, the c-namespace, introduced in Spring 3.1, allows inlined attributes for configuring the constructor arguments rather then nested constructor- arg elements. The following example uses the c: namespace to do the same thing as the from Constructor-based Dependency Injection:                     The c: namespace uses the same conventions as the p: one (a trailing -ref for bean references) for setting the constructor arguments by their names. Similarly, it needs to be declared in the XML file even though it is not defined in an XSD schema (it exists inside the Spring core). For the rare cases where the constructor argument names are not available (usually if the bytecode was compiled without debugging information), you can use fallback to the argument indexes, as follows: Due to the XML grammar, the index notation requires the presence of the leading _, as XML attribute names cannot start with a number (even though some IDEs  allow it). A corresponding index notation is also available for elements but not commonly used since the plain order of declaration is usually sufficient there. In practice, the constructor resolution mechanism is quite efficient in matching arguments, so unless you really need to, we recommend using the name notation throughout your configuration. Compound Property Names You can use compound or nested property names when you set bean properties, as long as all components of the path except the final property name are not null. Consider the following bean definition:   The something bean has a fred property, which has a bob property, which has a sammy property, and that final sammy property is being set to a value of 123. In order for this to work, the fred property of something and the bob property of fred must not be null after the bean is constructed. Otherwise, a NullPointerException is thrown. Using depends-on If a bean is a dependency of another bean, that usually means that one bean is set as a property of another. Typically you accomplish this with the element in XML-based configuration metadata. However, sometimes dependencies between beans are less direct. An example is when a static initializer in a class needs to be triggered, such as for database driver registration. The depends-on attribute can explicitly force one or more beans to be initialized before the bean using this element is initialized. The following example uses the depends-on attribute to express a dependency on a single bean: To express a dependency on multiple beans, supply a list of bean names as the value of the depends- on attribute (commas, whitespace, and semicolons are valid delimiters):   The depends-on attribute can specify both an initialization-time dependency and, in the case of singleton beans only, a corresponding destruction-time dependency.  Dependent beans that define a depends-on relationship with a given bean are destroyed first, prior to the given bean itself being destroyed. Thus, depends-on can also control shutdown order. Lazy-initialized Beans By default, ApplicationContext implementations eagerly create and configure all singleton beans as part of the initialization process. Generally, this pre-instantiation is desirable, because errors in the configuration or surrounding environment are discovered immediately, as opposed to hours or even days later. When this behavior is not desirable, you can prevent pre-instantiation of a singleton bean by marking the bean definition as being lazy-initialized. A lazy-initialized bean tells the IoC container to create a bean instance when it is first requested, rather than at startup. In XML, this behavior is controlled by the lazy-init attribute on the element, as the following example shows: When the preceding configuration is consumed by an ApplicationContext, the lazy bean is not eagerly pre-instantiated when the ApplicationContext starts, whereas the not.lazy bean is eagerly pre-instantiated. However, when a lazy-initialized bean is a dependency of a singleton bean that is not lazy- initialized, the ApplicationContext creates the lazy-initialized bean at startup, because it must satisfy the singleton’s dependencies. The lazy-initialized bean is injected into a singleton bean elsewhere that is not lazy-initialized. You can also control lazy-initialization at the container level by using the default-lazy-init attribute on the element, as the following example shows:   Autowiring Collaborators The Spring container can autowire relationships between collaborating beans. You can let Spring resolve collaborators (other beans) automatically for your bean by inspecting the contents of the ApplicationContext. Autowiring has the following advantages: • Autowiring can significantly reduce the need to specify properties or constructor arguments. (Other mechanisms such as a bean template discussed elsewhere in this chapter are also valuable in this regard.) • Autowiring can update a configuration as your objects evolve. For example, if you need to add a dependency to a class, that dependency can be satisfied automatically without you needing to modify the configuration. Thus autowiring can be especially useful during development, without negating the option of switching to explicit wiring when the code base becomes more stable. When using XML-based configuration metadata (see Dependency Injection), you can specify the autowire mode for a bean definition with the autowire attribute of the element. The autowiring functionality has four modes. You specify autowiring per bean and can thus choose which ones to autowire. The following table describes the four autowiring modes: Table 2. Autowiring modes Mode Explanation no (Default) No autowiring. Bean references must be defined by ref elements. Changing the default setting is not recommended for larger deployments, because specifying collaborators explicitly gives greater control and clarity. To some extent, it documents the structure of a system. byName Autowiring by property name. Spring looks for a bean with the same name as the property that needs to be autowired. For example, if a bean definition is set to autowire by name and it contains a master property (that is, it has a setMaster(..) method), Spring looks for a bean definition named master and uses it to set the property. byType Lets a property be autowired if exactly one bean of the property type exists in the container. If more than one exists, a fatal exception is thrown, which indicates that you may not use byType autowiring for that bean. If there are no matching beans, nothing happens (the property is not set). constructor Analogous to byType but applies to constructor arguments. If there is not exactly one bean of the constructor argument type in the container, a fatal error is raised. With byType or constructor autowiring mode, you can wire arrays and typed collections. In such cases, all autowire candidates within the container that match the expected type are provided to satisfy the dependency. You can autowire strongly-typed Map instances if the expected key type is String. An autowired Map instance’s values consist of all bean instances that match the expected type, and the Map instance’s keys contain the corresponding bean names. Limitations and Disadvantages of Autowiring Autowiring works best when it is used consistently across a project. If autowiring is not used in general, it might be confusing to developers to use it to wire only one or two bean definitions. Consider the limitations and disadvantages of autowiring: • Explicit dependencies in property and constructor-arg settings always override autowiring. You cannot autowire simple properties such as primitives, Strings, and Classes (and arrays of such simple properties). This limitation is by-design. • Autowiring is less exact than explicit wiring. Although, as noted in the earlier table, Spring is careful to avoid guessing in case of ambiguity that might have unexpected results. The relationships between your Spring-managed objects are no longer documented explicitly. • Wiring information may not be available to tools that may generate documentation from a Spring container. • Multiple bean definitions within the container may match the type specified by the setter method or constructor argument to be autowired. For arrays, collections, or Map instances, this is not necessarily a problem. However, for dependencies that expect a single value, this ambiguity is not arbitrarily resolved. If no unique bean definition is available, an exception is thrown. In the latter scenario, you have several options: • Abandon autowiring in favor of explicit wiring. • Avoid autowiring for a bean definition by setting its autowire-candidate attributes to false, as described in the next section. • Designate a single bean definition as the primary candidate by setting the primary attribute of its element to true. • Implement the more fine-grained control available with annotation-based configuration, as described in Annotation-based Container Configuration. Excluding a Bean from Autowiring On a per-bean basis, you can exclude a bean from autowiring. In Spring’s XML format, set the autowire-candidate attribute of the element to false. The container makes that specific bean definition unavailable to the autowiring infrastructure (including annotation style configurations such as @Autowired). The autowire-candidate attribute is designed to only affect type-based autowiring. It does not affect explicit references by name, which get resolved even if the  specified bean is not marked as an autowire candidate. As a consequence, autowiring by name nevertheless injects a bean if the name matches. You can also limit autowire candidates based on pattern-matching against bean names. The top- level element accepts one or more patterns within its default-autowire-candidates attribute. For example, to limit autowire candidate status to any bean whose name ends with Repository, provide a value of *Repository. To provide multiple patterns, define them in a comma- separated list. An explicit value of true or false for a bean definition’s autowire-candidate attribute always takes precedence. For such beans, the pattern matching rules do not apply. These techniques are useful for beans that you never want to be injected into other beans by autowiring. It does not mean that an excluded bean cannot itself be configured by using autowiring. Rather, the bean itself is not a candidate for autowiring other beans. Method Injection In most application scenarios, most beans in the container are singletons. When a singleton bean needs to collaborate with another singleton bean or a non-singleton bean needs to collaborate with another non-singleton bean, you typically handle the dependency by defining one bean as a property of the other. A problem arises when the bean lifecycles are different. Suppose singleton bean A needs to use non-singleton (prototype) bean B, perhaps on each method invocation on A. The container creates the singleton bean A only once, and thus only gets one opportunity to set the properties. The container cannot provide bean A with a new instance of bean B every time one is needed. A solution is to forego some inversion of control. You can make bean A aware of the container by implementing the ApplicationContextAware interface, and by making a getBean("B") call to the container ask for (a typically new) bean B instance every time bean A needs it. The following example shows this approach: Java // a class that uses a stateful Command-style class to perform some processing package fiona.apple; // Spring-API imports import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class CommandManager implements ApplicationContextAware {   private ApplicationContext applicationContext;   public Object process(Map commandState) {   // grab a new instance of the appropriate Command   Command command = createCommand();   // set the state on the (hopefully brand new) Command instance   command.setState(commandState);   return command.execute();   }   protected Command createCommand() {   // notice the Spring API dependency!   return this.applicationContext.getBean("command", Command.class);   }   public void setApplicationContext(   ApplicationContext applicationContext) throws BeansException {   this.applicationContext = applicationContext;   } } Kotlin // a class that uses a stateful Command-style class to perform some processing package fiona.apple // Spring-API imports import org.springframework.context.ApplicationContext import org.springframework.context.ApplicationContextAware class CommandManager : ApplicationContextAware {   private lateinit var applicationContext: ApplicationContext   fun process(commandState: Map<*, *>): Any {   // grab a new instance of the appropriate Command   val command = createCommand()   // set the state on the (hopefully brand new) Command instance   command.state = commandState   return command.execute()   }   // notice the Spring API dependency!   protected fun createCommand() =   applicationContext.getBean("command", Command::class.java)   override fun setApplicationContext(applicationContext: ApplicationContext) {   this.applicationContext = applicationContext   } } The preceding is not desirable, because the business code is aware of and coupled to the Spring Framework. Method Injection, a somewhat advanced feature of the Spring IoC container, lets you handle this use case cleanly. You can read more about the motivation for Method Injection in this blog entry. Lookup Method Injection Lookup method injection is the ability of the container to override methods on container-managed beans and return the lookup result for another named bean in the container. The lookup typically involves a prototype bean, as in the scenario described in the preceding section. The Spring Framework implements this method injection by using bytecode generation from the CGLIB library to dynamically generate a subclass that overrides the method. • For this dynamic subclassing to work, the class that the Spring bean container subclasses cannot be final, and the method to be overridden cannot be final, either. • Unit-testing a class that has an abstract method requires you to subclass the class yourself and to supply a stub implementation of the abstract method.  • Concrete methods are also necessary for component scanning, which requires concrete classes to pick up. • A further key limitation is that lookup methods do not work with factory methods and in particular not with @Bean methods in configuration classes, since, in that case, the container is not in charge of creating the instance and therefore cannot create a runtime-generated subclass on the fly. In the case of the CommandManager class in the previous code snippet, the Spring container dynamically overrides the implementation of the createCommand() method. The CommandManager class does not have any Spring dependencies, as the reworked example shows: Java package fiona.apple; // no more Spring imports! public abstract class CommandManager {   public Object process(Object commandState) {   // grab a new instance of the appropriate Command interface   Command command = createCommand();   // set the state on the (hopefully brand new) Command instance   command.setState(commandState);   return command.execute();   }   // okay... but where is the implementation of this method?   protected abstract Command createCommand(); } Kotlin package fiona.apple // no more Spring imports! abstract class CommandManager {   fun process(commandState: Any): Any {   // grab a new instance of the appropriate Command interface   val command = createCommand()   // set the state on the (hopefully brand new) Command instance   command.state = commandState   return command.execute()   }   // okay... but where is the implementation of this method?   protected abstract fun createCommand(): Command } In the client class that contains the method to be injected (the CommandManager in this case), the method to be injected requires a signature of the following form: [abstract] theMethodName(no-arguments); If the method is abstract, the dynamically-generated subclass implements the method. Otherwise, the dynamically-generated subclass overrides the concrete method defined in the original class. Consider the following example:     The bean identified as commandManager calls its own createCommand() method whenever it needs a new instance of the myCommand bean. You must be careful to deploy the myCommand bean as a prototype if that is actually what is needed. If it is a singleton, the same instance of the myCommand bean is returned each time. Alternatively, within the annotation-based component model, you can declare a lookup method through the @Lookup annotation, as the following example shows: Java public abstract class CommandManager {   public Object process(Object commandState) {   Command command = createCommand();   command.setState(commandState);   return command.execute();   }   @Lookup("myCommand")   protected abstract Command createCommand(); } Kotlin abstract class CommandManager {   fun process(commandState: Any): Any {   val command = createCommand()   command.state = commandState   return command.execute()   }   @Lookup("myCommand")   protected abstract fun createCommand(): Command } Or, more idiomatically, you can rely on the target bean getting resolved against the declared return type of the lookup method: Java public abstract class CommandManager {   public Object process(Object commandState) {   Command command = createCommand();   command.setState(commandState);   return command.execute();   }   @Lookup   protected abstract Command createCommand(); } Kotlin abstract class CommandManager {   fun process(commandState: Any): Any {   val command = createCommand()   command.state = commandState   return command.execute()   }   @Lookup   protected abstract fun createCommand(): Command } Note that you should typically declare such annotated lookup methods with a concrete stub implementation, in order for them to be compatible with Spring’s component scanning rules where abstract classes get ignored by default. This limitation does not apply to explicitly registered or explicitly imported bean classes. Another way of accessing differently scoped target beans is an ObjectFactory/ Provider injection point. See Scoped Beans as Dependencies.  You may also find the ServiceLocatorFactoryBean (in the org.springframework.beans.factory.config package) to be useful. Arbitrary Method Replacement A less useful form of method injection than lookup method injection is the ability to replace arbitrary methods in a managed bean with another method implementation. You can safely skip the rest of this section until you actually need this functionality. With XML-based configuration metadata, you can use the replaced-method element to replace an existing method implementation with another, for a deployed bean. Consider the following class, which has a method called computeValue that we want to override: Java public class MyValueCalculator {   public String computeValue(String input) {   // some real code...   }   // some other methods... } Kotlin class MyValueCalculator {   fun computeValue(input: String): String {   // some real code...   }   // some other methods... } A class that implements the org.springframework.beans.factory.support.MethodReplacer interface provides the new method definition, as the following example shows: Java /**  * meant to be used to override the existing computeValue(String)  * implementation in MyValueCalculator  */ public class ReplacementComputeValue implements MethodReplacer {   public Object reimplement(Object o, Method m, Object[] args) throws Throwable {   // get the input value, work with it, and return a computed result   String input = (String) args[0];   ...   return ...;   } } Kotlin /**  * meant to be used to override the existing computeValue(String)  * implementation in MyValueCalculator  */ class ReplacementComputeValue : MethodReplacer {   override fun reimplement(obj: Any, method: Method, args: Array): Any {   // get the input value, work with it, and return a computed result   val input = args[0] as String;   ...   return ...;   } } The bean definition to deploy the original class and specify the method override would resemble the following example:       String   You can use one or more elements within the element to indicate the method signature of the method being overridden. The signature for the arguments is necessary only if the method is overloaded and multiple variants exist within the class. For convenience, the type string for an argument may be a substring of the fully qualified type name. For example, the following all match java.lang.String: java.lang.String String Str Because the number of arguments is often enough to distinguish between each possible choice, this shortcut can save a lot of typing, by letting you type only the shortest string that matches an argument type. 2.1.5. Bean Scopes When you create a bean definition, you create a recipe for creating actual instances of the class defined by that bean definition. The idea that a bean definition is a recipe is important, because it means that, as with a class, you can create many object instances from a single recipe. You can control not only the various dependencies and configuration values that are to be plugged into an object that is created from a particular bean definition but also control the scope of the objects created from a particular bean definition. This approach is powerful and flexible, because you can choose the scope of the objects you create through configuration instead of having to bake in the scope of an object at the Java class level. Beans can be defined to be deployed in one of a number of scopes. The Spring Framework supports six scopes, four of which are available only if you use a web-aware ApplicationContext. You can also create a custom scope. The following table describes the supported scopes: Table 3. Bean scopes Scope Description singleton (Default) Scopes a single bean definition to a single object instance for each Spring IoC container. prototype Scopes a single bean definition to any number of object instances. Scope Description request Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext. session Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext. application Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext. websocket Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext. As of Spring 3.0, a thread scope is available but is not registered by default. For  more information, see the documentation for SimpleThreadScope. For instructions on how to register this or any other custom scope, see Using a Custom Scope. The Singleton Scope Only one shared instance of a singleton bean is managed, and all requests for beans with an ID or IDs that match that bean definition result in that one specific bean instance being returned by the Spring container. To put it another way, when you define a bean definition and it is scoped as a singleton, the Spring IoC container creates exactly one instance of the object defined by that bean definition. This single instance is stored in a cache of such singleton beans, and all subsequent requests and references for that named bean return the cached object. The following image shows how the singleton scope works: Spring’s concept of a singleton bean differs from the singleton pattern as defined in the Gang of Four (GoF) patterns book. The GoF singleton hard-codes the scope of an object such that one and only one instance of a particular class is created per ClassLoader. The scope of the Spring singleton is best described as being per-container and per-bean. This means that, if you define one bean for a particular class in a single Spring container, the Spring container creates one and only one instance of the class defined by that bean definition. The singleton scope is the default scope in Spring. To define a bean as a singleton in XML, you can define a bean as shown in the following example: The Prototype Scope The non-singleton prototype scope of bean deployment results in the creation of a new bean instance every time a request for that specific bean is made. That is, the bean is injected into another bean or you request it through a getBean() method call on the container. As a rule, you should use the prototype scope for all stateful beans and the singleton scope for stateless beans. The following diagram illustrates the Spring prototype scope: (A data access object (DAO) is not typically configured as a prototype, because a typical DAO does not hold any conversational state. It was easier for us to reuse the core of the singleton diagram.) The following example defines a bean as a prototype in XML: In contrast to the other scopes, Spring does not manage the complete lifecycle of a prototype bean. The container instantiates, configures, and otherwise assembles a prototype object and hands it to the client, with no further record of that prototype instance. Thus, although initialization lifecycle callback methods are called on all objects regardless of scope, in the case of prototypes, configured destruction lifecycle callbacks are not called. The client code must clean up prototype-scoped objects and release expensive resources that the prototype beans hold. To get the Spring container to release resources held by prototype-scoped beans, try using a custom bean post-processor, which holds a reference to beans that need to be cleaned up. In some respects, the Spring container’s role in regard to a prototype-scoped bean is a replacement for the Java new operator. All lifecycle management past that point must be handled by the client. (For details on the lifecycle of a bean in the Spring container, see Lifecycle Callbacks.) Singleton Beans with Prototype-bean Dependencies When you use singleton-scoped beans with dependencies on prototype beans, be aware that dependencies are resolved at instantiation time. Thus, if you dependency-inject a prototype-scoped bean into a singleton-scoped bean, a new prototype bean is instantiated and then dependency- injected into the singleton bean. The prototype instance is the sole instance that is ever supplied to the singleton-scoped bean. However, suppose you want the singleton-scoped bean to acquire a new instance of the prototype- scoped bean repeatedly at runtime. You cannot dependency-inject a prototype-scoped bean into your singleton bean, because that injection occurs only once, when the Spring container instantiates the singleton bean and resolves and injects its dependencies. If you need a new instance of a prototype bean at runtime more than once, see Method Injection. Request, Session, Application, and WebSocket Scopes The request, session, application, and websocket scopes are available only if you use a web-aware Spring ApplicationContext implementation (such as XmlWebApplicationContext). If you use these scopes with regular Spring IoC containers, such as the ClassPathXmlApplicationContext, an IllegalStateException that complains about an unknown bean scope is thrown. Initial Web Configuration To support the scoping of beans at the request, session, application, and websocket levels (web- scoped beans), some minor initial configuration is required before you define your beans. (This initial setup is not required for the standard scopes: singleton and prototype.) How you accomplish this initial setup depends on your particular Servlet environment. If you access scoped beans within Spring Web MVC, in effect, within a request that is processed by the Spring DispatcherServlet, no special setup is necessary. DispatcherServlet already exposes all relevant state. If you use a Servlet web container, with requests processed outside of Spring’s DispatcherServlet (for example, when using JSF or Struts), you need to register the org.springframework.web.context.request.RequestContextListener ServletRequestListener. This can be done programmatically by using the WebApplicationInitializer interface. Alternatively, add the following declaration to your web application’s web.xml file:   ...       org.springframework.web.context.request.RequestContextListener       ... Alternatively, if there are issues with your listener setup, consider using Spring’s RequestContextFilter. The filter mapping depends on the surrounding web application configuration, so you have to change it as appropriate. The following listing shows the filter part of a web application:   ...     requestContextFilter   org.springframework.web.filter.RequestContextFilter       requestContextFilter   /*     ... DispatcherServlet, RequestContextListener, and RequestContextFilter all do exactly the same thing, namely bind the HTTP request object to the Thread that is servicing that request. This makes beans that are request- and session-scoped available further down the call chain. Request scope Consider the following XML configuration for a bean definition: The Spring container creates a new instance of the LoginAction bean by using the loginAction bean definition for each and every HTTP request. That is, the loginAction bean is scoped at the HTTP request level. You can change the internal state of the instance that is created as much as you want, because other instances created from the same loginAction bean definition do not see these changes in state. They are particular to an individual request. When the request completes processing, the bean that is scoped to the request is discarded. When using annotation-driven components or Java configuration, the @RequestScope annotation can be used to assign a component to the request scope. The following example shows how to do so: Java @RequestScope @Component public class LoginAction {   // ... } Kotlin @RequestScope @Component class LoginAction {   // ... } Session Scope Consider the following XML configuration for a bean definition: The Spring container creates a new instance of the UserPreferences bean by using the userPreferences bean definition for the lifetime of a single HTTP Session. In other words, the userPreferences bean is effectively scoped at the HTTP Session level. As with request-scoped beans, you can change the internal state of the instance that is created as much as you want, knowing that other HTTP Session instances that are also using instances created from the same userPreferences bean definition do not see these changes in state, because they are particular to an individual HTTP Session. When the HTTP Session is eventually discarded, the bean that is scoped to that particular HTTP Session is also discarded. When using annotation-driven components or Java configuration, you can use the @SessionScope annotation to assign a component to the session scope. Java @SessionScope @Component public class UserPreferences {   // ... } Kotlin @SessionScope @Component class UserPreferences {   // ... } Application Scope Consider the following XML configuration for a bean definition: The Spring container creates a new instance of the AppPreferences bean by using the appPreferences bean definition once for the entire web application. That is, the appPreferences bean is scoped at the ServletContext level and stored as a regular ServletContext attribute. This is somewhat similar to a Spring singleton bean but differs in two important ways: It is a singleton per ServletContext, not per Spring ApplicationContext (for which there may be several in any given web application), and it is actually exposed and therefore visible as a ServletContext attribute. When using annotation-driven components or Java configuration, you can use the @ApplicationScope annotation to assign a component to the application scope. The following example shows how to do so: Java @ApplicationScope @Component public class AppPreferences {   // ... } Kotlin @ApplicationScope @Component class AppPreferences {   // ... } WebSocket Scope WebSocket scope is associated with the lifecycle of a WebSocket session and applies to STOMP over WebSocket applications, see WebSocket scope for more details. Scoped Beans as Dependencies The Spring IoC container manages not only the instantiation of your objects (beans), but also the wiring up of collaborators (or dependencies). If you want to inject (for example) an HTTP request- scoped bean into another bean of a longer-lived scope, you may choose to inject an AOP proxy in place of the scoped bean. That is, you need to inject a proxy object that exposes the same public interface as the scoped object but that can also retrieve the real target object from the relevant scope (such as an HTTP request) and delegate method calls onto the real object. You may also use between beans that are scoped as singleton, with the reference then going through an intermediate proxy that is serializable and therefore able to re-obtain the target singleton bean on deserialization. When declaring against a bean of scope prototype, every method call on the shared proxy leads to the creation of a new target instance to which the call is then being forwarded. Also, scoped proxies are not the only way to access beans from shorter scopes in a lifecycle-safe fashion. You may also declare your injection point (that is, the  constructor or setter argument or autowired field) as ObjectFactory, allowing for a getObject() call to retrieve the current instance on demand every time it is needed — without holding on to the instance or storing it separately. As an extended variant, you may declare ObjectProvider which delivers several additional access variants, including getIfAvailable and getIfUnique. The JSR-330 variant of this is called Provider and is used with a Provider declaration and a corresponding get() call for every retrieval attempt. See here for more details on JSR-330 overall. The configuration in the following example is only one line, but it is important to understand the “why” as well as the “how” behind it:         ①             ① The line that defines the proxy. To create such a proxy, you insert a child element into a scoped bean definition (see Choosing the Type of Proxy to Create and XML Schema-based configuration). Why do definitions of beans scoped at the request, session and custom-scope levels require the element? Consider the following singleton bean definition and contrast it with what you need to define for the aforementioned scopes (note that the following userPreferences bean definition as it stands is incomplete):   In the preceding example, the singleton bean (userManager) is injected with a reference to the HTTP Session-scoped bean (userPreferences). The salient point here is that the userManager bean is a singleton: it is instantiated exactly once per container, and its dependencies (in this case only one, the userPreferences bean) are also injected only once. This means that the userManager bean operates only on the exact same userPreferences object (that is, the one with which it was originally injected). This is not the behavior you want when injecting a shorter-lived scoped bean into a longer-lived scoped bean (for example, injecting an HTTP Session-scoped collaborating bean as a dependency into singleton bean). Rather, you need a single userManager object, and, for the lifetime of an HTTP Session, you need a userPreferences object that is specific to the HTTP Session. Thus, the container creates an object that exposes the exact same public interface as the UserPreferences class (ideally an object that is a UserPreferences instance), which can fetch the real UserPreferences object from the scoping mechanism (HTTP request, Session, and so forth). The container injects this proxy object into the userManager bean, which is unaware that this UserPreferences reference is a proxy. In this example, when a UserManager instance invokes a method on the dependency-injected UserPreferences object, it is actually invoking a method on the proxy. The proxy then fetches the real UserPreferences object from (in this case) the HTTP Session and delegates the method invocation onto the retrieved real UserPreferences object. Thus, you need the following (correct and complete) configuration when injecting request- and session-scoped beans into collaborating objects, as the following example shows:     Choosing the Type of Proxy to Create By default, when the Spring container creates a proxy for a bean that is marked up with the element, a CGLIB-based class proxy is created. CGLIB proxies intercept only public method calls! Do not call non-public methods  on such a proxy. They are not delegated to the actual scoped target object. Alternatively, you can configure the Spring container to create standard JDK interface-based proxies for such scoped beans, by specifying false for the value of the proxy-target-class attribute of the element. Using JDK interface-based proxies means that you do not need additional libraries in your application classpath to affect such proxying. However, it also means that the class of the scoped bean must implement at least one interface and that all collaborators into which the scoped bean is injected must reference the bean through one of its interfaces. The following example shows a proxy based on an interface:     For more detailed information about choosing class-based or interface-based proxying, see Proxying Mechanisms. Custom Scopes The bean scoping mechanism is extensible. You can define your own scopes or even redefine existing scopes, although the latter is considered bad practice and you cannot override the built-in singleton and prototype scopes. Creating a Custom Scope To integrate your custom scopes into the Spring container, you need to implement the org.springframework.beans.factory.config.Scope interface, which is described in this section. For an idea of how to implement your own scopes, see the Scope implementations that are supplied with the Spring Framework itself and the Scope javadoc, which explains the methods you need to implement in more detail. The Scope interface has four methods to get objects from the scope, remove them from the scope, and let them be destroyed. The session scope implementation, for example, returns the session-scoped bean (if it does not exist, the method returns a new instance of the bean, after having bound it to the session for future reference). The following method returns the object from the underlying scope: Java Object get(String name, ObjectFactory objectFactory) Kotlin fun get(name: String, objectFactory: ObjectFactory<*>): Any The session scope implementation, for example, removes the session-scoped bean from the underlying session. The object should be returned, but you can return null if the object with the specified name is not found. The following method removes the object from the underlying scope: Java Object remove(String name) Kotlin fun remove(name: String): Any The following method registers a callback that the scope should invoke when it is destroyed or when the specified object in the scope is destroyed: Java void registerDestructionCallback(String name, Runnable destructionCallback) Kotlin fun registerDestructionCallback(name: String, destructionCallback: Runnable) See the javadoc or a Spring scope implementation for more information on destruction callbacks. The following method obtains the conversation identifier for the underlying scope: Java String getConversationId() Kotlin fun getConversationId(): String This identifier is different for each scope. For a session scoped implementation, this identifier can be the session identifier. Using a Custom Scope After you write and test one or more custom Scope implementations, you need to make the Spring container aware of your new scopes. The following method is the central method to register a new Scope with the Spring container: Java void registerScope(String scopeName, Scope scope); Kotlin fun registerScope(scopeName: String, scope: Scope) This method is declared on the ConfigurableBeanFactory interface, which is available through the BeanFactory property on most of the concrete ApplicationContext implementations that ship with Spring. The first argument to the registerScope(..) method is the unique name associated with a scope. Examples of such names in the Spring container itself are singleton and prototype. The second argument to the registerScope(..) method is an actual instance of the custom Scope implementation that you wish to register and use. Suppose that you write your custom Scope implementation, and then register it as shown in the next example. The next example uses SimpleThreadScope, which is included with Spring but is not  registered by default. The instructions would be the same for your own custom Scope implementations. Java Scope threadScope = new SimpleThreadScope(); beanFactory.registerScope("thread", threadScope); Kotlin val threadScope = SimpleThreadScope() beanFactory.registerScope("thread", threadScope) You can then create bean definitions that adhere to the scoping rules of your custom Scope, as follows: With a custom Scope implementation, you are not limited to programmatic registration of the scope. You can also do the Scope registration declaratively, by using the CustomScopeConfigurer class, as the following example shows:                                 When you place within a declaration for a FactoryBean  implementation, it is the factory bean itself that is scoped, not the object returned from getObject(). 2.1.6. Customizing the Nature of a Bean The Spring Framework provides a number of interfaces you can use to customize the nature of a bean. This section groups them as follows: • Lifecycle Callbacks • ApplicationContextAware and BeanNameAware • Other Aware Interfaces Lifecycle Callbacks To interact with the container’s management of the bean lifecycle, you can implement the Spring InitializingBean and DisposableBean interfaces. The container calls afterPropertiesSet() for the former and destroy() for the latter to let the bean perform certain actions upon initialization and destruction of your beans. The JSR-250 @PostConstruct and @PreDestroy annotations are generally considered best practice for receiving lifecycle callbacks in a modern Spring application. Using these annotations means that your beans are not coupled to Spring-specific  interfaces. For details, see Using @PostConstruct and @PreDestroy. If you do not want to use the JSR-250 annotations but you still want to remove coupling, consider init-method and destroy-method bean definition metadata. Internally, the Spring Framework uses BeanPostProcessor implementations to process any callback interfaces it can find and call the appropriate methods. If you need custom features or other lifecycle behavior Spring does not by default offer, you can implement a BeanPostProcessor yourself. For more information, see Container Extension Points. In addition to the initialization and destruction callbacks, Spring-managed objects may also implement the Lifecycle interface so that those objects can participate in the startup and shutdown process, as driven by the container’s own lifecycle. The lifecycle callback interfaces are described in this section. Initialization Callbacks The org.springframework.beans.factory.InitializingBean interface lets a bean perform initialization work after the container has set all necessary properties on the bean. The InitializingBean interface specifies a single method: void afterPropertiesSet() throws Exception; We recommend that you do not use the InitializingBean interface, because it unnecessarily couples the code to Spring. Alternatively, we suggest using the @PostConstruct annotation or specifying a POJO initialization method. In the case of XML-based configuration metadata, you can use the init- method attribute to specify the name of the method that has a void no-argument signature. With Java configuration, you can use the initMethod attribute of @Bean. See Receiving Lifecycle Callbacks. Consider the following example: Java public class ExampleBean {   public void init() {   // do some initialization work   } } Kotlin class ExampleBean {   fun init() {   // do some initialization work   } } The preceding example has almost exactly the same effect as the following example (which consists of two listings): Java public class AnotherExampleBean implements InitializingBean {   @Override   public void afterPropertiesSet() {   // do some initialization work   } } Kotlin class AnotherExampleBean : InitializingBean {   override fun afterPropertiesSet() {   // do some initialization work   } } However, the first of the two preceding examples does not couple the code to Spring. Destruction Callbacks Implementing the org.springframework.beans.factory.DisposableBean interface lets a bean get a callback when the container that contains it is destroyed. The DisposableBean interface specifies a single method: void destroy() throws Exception; We recommend that you do not use the DisposableBean callback interface, because it unnecessarily couples the code to Spring. Alternatively, we suggest using the @PreDestroy annotation or specifying a generic method that is supported by bean definitions. With XML-based configuration metadata, you can use the destroy-method attribute on the . With Java configuration, you can use the destroyMethod attribute of @Bean. See Receiving Lifecycle Callbacks. Consider the following definition: Java public class ExampleBean {   public void cleanup() {   // do some destruction work (like releasing pooled connections)   } } Kotlin class ExampleBean {   fun cleanup() {   // do some destruction work (like releasing pooled connections)   } } The preceding definition has almost exactly the same effect as the following definition: Java public class AnotherExampleBean implements DisposableBean {   @Override   public void destroy() {   // do some destruction work (like releasing pooled connections)   } } Kotlin class AnotherExampleBean : DisposableBean {   override fun destroy() {   // do some destruction work (like releasing pooled connections)   } } However, the first of the two preceding definitions does not couple the code to Spring. You can assign the destroy-method attribute of a element a special (inferred) value, which instructs Spring to automatically detect a public close or shutdown method on the specific bean class. (Any class that implements java.lang.AutoCloseable or java.io.Closeable would therefore match.) You can  also set this special (inferred) value on the default-destroy-method attribute of a element to apply this behavior to an entire set of beans (see Default Initialization and Destroy Methods). Note that this is the default behavior with Java configuration. Default Initialization and Destroy Methods When you write initialization and destroy method callbacks that do not use the Spring-specific InitializingBean and DisposableBean callback interfaces, you typically write methods with names such as init(), initialize(), dispose(), and so on. Ideally, the names of such lifecycle callback methods are standardized across a project so that all developers use the same method names and ensure consistency. You can configure the Spring container to “look” for named initialization and destroy callback method names on every bean. This means that you, as an application developer, can write your application classes and use an initialization callback called init(), without having to configure an init-method="init" attribute with each bean definition. The Spring IoC container calls that method when the bean is created (and in accordance with the standard lifecycle callback contract described previously). This feature also enforces a consistent naming convention for initialization and destroy method callbacks. Suppose that your initialization callback methods are named init() and your destroy callback methods are named destroy(). Your class then resembles the class in the following example: Java public class DefaultBlogService implements BlogService {   private BlogDao blogDao;   public void setBlogDao(BlogDao blogDao) {   this.blogDao = blogDao;   }   // this is (unsurprisingly) the initialization callback method   public void init() {   if (this.blogDao == null) {   throw new IllegalStateException("The [blogDao] property must be set.");   }   } } Kotlin class DefaultBlogService : BlogService {   private var blogDao: BlogDao? = null   // this is (unsurprisingly) the initialization callback method   fun init() {   if (blogDao == null) {   throw IllegalStateException("The [blogDao] property must be set.")   }   } } You could then use that class in a bean resembling the following:       The presence of the default-init-method attribute on the top-level element attribute causes the Spring IoC container to recognize a method called init on the bean class as the initialization method callback. When a bean is created and assembled, if the bean class has such a method, it is invoked at the appropriate time. You can configure destroy method callbacks similarly (in XML, that is) by using the default- destroy-method attribute on the top-level element. Where existing bean classes already have callback methods that are named at variance with the convention, you can override the default by specifying (in XML, that is) the method name by using the init-method and destroy-method attributes of the itself. The Spring container guarantees that a configured initialization callback is called immediately after a bean is supplied with all dependencies. Thus, the initialization callback is called on the raw bean reference, which means that AOP interceptors and so forth are not yet applied to the bean. A target bean is fully created first and then an AOP proxy (for example) with its interceptor chain is applied. If the target bean and the proxy are defined separately, your code can even interact with the raw target bean, bypassing the proxy. Hence, it would be inconsistent to apply the interceptors to the init method, because doing so would couple the lifecycle of the target bean to its proxy or interceptors and leave strange semantics when your code interacts directly with the raw target bean. --- ### Spring Ai Spring Boot Docker Compose/Src/Test/Resources/Org/Springframework/Ai/Docker/Compose/Service/Connection/Chroma/Chroma Compose.Yaml (spring-ai-spring-boot-docker-compose/src/test/resources/org/springframework/ai/docker/compose/service/connection/chroma/chroma-compose.yaml) services: chroma: image: '{imageName}' ports: - '8000' --- ### Spring Ai Spring Boot Docker Compose/Src/Test/Resources/Org/Springframework/Ai/Docker/Compose/Service/Connection/Chroma/Chroma With Token Compose.Yaml (spring-ai-spring-boot-docker-compose/src/test/resources/org/springframework/ai/docker/compose/service/connection/chroma/chroma-with-token-compose.yaml) services: chroma: image: '{imageName}' ports: - '8000' environment: - CHROMA_SERVER_AUTHN_CREDENTIALS=secret - CHROMA_SERVER_AUTHN_PROVIDER=chromadb.auth.token_authn.TokenAuthenticationServerProvider --- ### Spring Ai Spring Boot Docker Compose/Src/Test/Resources/Org/Springframework/Ai/Docker/Compose/Service/Connection/Docker/Docker Agents Gateway Compose.Yaml (spring-ai-spring-boot-docker-compose/src/test/resources/org/springframework/ai/docker/compose/service/connection/docker/docker-agents-gateway-compose.yaml) services: mcp-gateway: image: '{imageName}' ports: - 8811 volumes: - "/var/run/docker.sock:/var/run/docker.sock" command: - --transport=sse --- ### Spring Ai Spring Boot Docker Compose/Src/Test/Resources/Org/Springframework/Ai/Docker/Compose/Service/Connection/Milvus/Milvus Compose.Yaml (spring-ai-spring-boot-docker-compose/src/test/resources/org/springframework/ai/docker/compose/service/connection/milvus/milvus-compose.yaml) services: milvus: image: '{imageName}' command: milvus run standalone ports: - '9091' - '19530' environment: - COMMON_STORAGETYPE=local - DEPLOY_MODE=STANDALONE - ETCD_USE_EMBED=true - ETCD_DATA_DIR=/var/lib/milvus/etcd - ETCD_CONFIG_PATH=/milvus/configs/embedEtcd.yaml configs: - source: embedEtcd target: /milvus/configs/embedEtcd.yaml configs: embedEtcd: content: | listen-client-urls: http://0.0.0.0:2379 advertise-client-urls: http://0.0.0.0:2379 --- ### Spring Ai Spring Boot Docker Compose/Src/Test/Resources/Org/Springframework/Ai/Docker/Compose/Service/Connection/Mongo/Mongo Compose.Yaml (spring-ai-spring-boot-docker-compose/src/test/resources/org/springframework/ai/docker/compose/service/connection/mongo/mongo-compose.yaml) services: mongo: image: '{imageName}' ports: - '27017' --- ### Spring Ai Spring Boot Docker Compose/Src/Test/Resources/Org/Springframework/Ai/Docker/Compose/Service/Connection/Ollama/Ollama Compose.Yaml (spring-ai-spring-boot-docker-compose/src/test/resources/org/springframework/ai/docker/compose/service/connection/ollama/ollama-compose.yaml) services: ollama: image: '{imageName}' ports: - '11434' --- ### Spring Ai Spring Boot Docker Compose/Src/Test/Resources/Org/Springframework/Ai/Docker/Compose/Service/Connection/Opensearch/Localstack Compose.Yaml (spring-ai-spring-boot-docker-compose/src/test/resources/org/springframework/ai/docker/compose/service/connection/opensearch/localstack-compose.yaml) services: localstack: image: '{imageName}' ports: - '4566' --- ### Spring Ai Spring Boot Docker Compose/Src/Test/Resources/Org/Springframework/Ai/Docker/Compose/Service/Connection/Opensearch/Opensearch Compose.Yaml (spring-ai-spring-boot-docker-compose/src/test/resources/org/springframework/ai/docker/compose/service/connection/opensearch/opensearch-compose.yaml) services: opensearch: image: '{imageName}' ports: - '9200' environment: - OPENSEARCH_INITIAL_ADMIN_PASSWORD=D3v3l0p-ment - discovery.type=single-node --- ### Spring Ai Spring Boot Docker Compose/Src/Test/Resources/Org/Springframework/Ai/Docker/Compose/Service/Connection/Qdrant/Qdrant Compose.Yaml (spring-ai-spring-boot-docker-compose/src/test/resources/org/springframework/ai/docker/compose/service/connection/qdrant/qdrant-compose.yaml) services: qdrant: image: '{imageName}' ports: - '6334' environment: - QDRANT__SERVICE__API_KEY=springai --- ### Spring Ai Spring Boot Docker Compose/Src/Test/Resources/Org/Springframework/Ai/Docker/Compose/Service/Connection/Typesense/Typesense Compose.Yaml (spring-ai-spring-boot-docker-compose/src/test/resources/org/springframework/ai/docker/compose/service/connection/typesense/typesense-compose.yaml) services: typesense: image: '{imageName}' ports: - '8108' command: '--data-dir /tmp --enable-cors' environment: - TYPESENSE_API_KEY=secret --- ### Spring Ai Spring Boot Docker Compose/Src/Test/Resources/Org/Springframework/Ai/Docker/Compose/Service/Connection/Weaviate/Weaviate Compose.Yaml (spring-ai-spring-boot-docker-compose/src/test/resources/org/springframework/ai/docker/compose/service/connection/weaviate/weaviate-compose.yaml) services: weaviate: image: '{imageName}' ports: - '8080' environment: - AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED=true - PERSISTENCE_DATA_PATH=/var/lib/weaviate --- ### Spring Ai Test/README (spring-ai-test/README.md) # Spring AI Test The Spring AI Test module provides utilities and base classes for testing AI applications built with Spring AI. ## Features - **BasicEvaluationTest**: A base test class for evaluating question-answer quality using AI models - **Vector Store Testing**: Utilities for testing vector store implementations - **Audio Testing**: Utilities for testing audio-related functionality ## BasicEvaluationTest The `BasicEvaluationTest` class provides a framework for evaluating the quality and relevance of AI-generated answers to questions. ### Usage Extend the `BasicEvaluationTest` class in your test classes: ```java @SpringBootTest public class MyAiEvaluationTest extends BasicEvaluationTest { @Test public void testQuestionAnswerAccuracy() { String question = "What is the capital of France?"; String answer = "The capital of France is Paris."; // Evaluate if the answer is accurate and related to the question evaluateQuestionAndAnswer(question, answer, true); } } ``` ### Configuration The test requires: - A `ChatModel` bean (typically OpenAI) - Evaluation prompt templates located in `classpath:/prompts/spring/test/evaluation/` ### Evaluation Types - **Fact-based evaluation**: Use `factBased = true` for questions requiring factual accuracy - **General evaluation**: Use `factBased = false` for more subjective questions The evaluation process: 1. Checks if the answer is related to the question 2. Evaluates the accuracy/appropriateness of the answer 3. Fails the test with detailed feedback if the answer is inadequate --- ### Spring Ai Test/Src/Main/Resources/Test/Data/Great.Depression (spring-ai-test/src/main/resources/test/data/great.depression.txt) The Great Depression (1929–1939) was an economic shock that affected most countries across the world. It was a period of economic depression that became evident after a major fall in stock prices in the United States.[1] The economic contagion began around September 1929 and led to the Wall Street stock market crash of October 24 (Black Thursday). It was the longest, deepest, and most widespread depression of the 20th century.[2] Between 1929 and 1932, worldwide gross domestic product (GDP) fell by an estimated 15%. By comparison, worldwide GDP fell by less than 1% from 2008 to 2009 during the Great Recession.[3] Some economies started to recover by the mid-1930s. However, in many countries,[specify] the negative effects of the Great Depression lasted until the beginning of World War II. Devastating effects were seen in both rich and poor countries with falling personal income, prices, tax revenues, and profits. International trade fell by more than 50%, unemployment in the U.S. rose to 23% and in some countries rose as high as 33%.[4] Cities around the world were hit hard, especially those dependent on heavy industry. Construction was virtually halted in many countries. Farming communities and rural areas suffered as crop prices fell by about 60%.[5][6][7] Faced with plummeting demand and few job alternatives, areas dependent on primary sector industries suffered the most.[8] Economic historians usually consider the catalyst of the Great Depression to be the sudden devastating collapse of U.S. stock market prices, starting on October 24, 1929. However, some dispute this conclusion, seeing the stock crash less than a cause of the Depression and more as a symptom of the rising nervousness of investors partly due to gradual price declines caused by falling sales of consumer goods (as a result of overproduction because of new production techniques, falling exports and income inequality, among other factors) that had already been underway as part of a gradual Depression --- ### Spring Ai Test/Src/Main/Resources/Test/Data/Spring.Ai (spring-ai-test/src/main/resources/test/data/spring.ai.txt) The Spring AI project aims to streamline the development of applications that incorporate artificial intelligence functionality without unnecessary complexity. The project draws inspiration from notable Python projects, such as LangChain and LlamaIndex, but Spring AI is not a direct port of those projects. The project was founded with the belief that the next wave of Generative AI applications will not be only for Python developers but will be ubiquitous across many programming languages. At its core, Spring AI provides abstractions that serve as the foundation for developing AI applications. These abstractions have multiple implementations, enabling easy component swapping with minimal code changes. For example, Spring AI introduces the ChatModel interface with implementations for OpenAI and Azure OpenAI. In addition to these core abstractions, Spring AI aims to provide higher-level functionalities to address common use cases such as “Q&A over your documentation” or “Chat with your documentation.” As the complexity of the use cases increases, the Spring AI project will integrate with other projects in the Spring Ecosystem, such as Spring Integration, Spring Batch, and Spring Data. To simplify setup, Spring Boot starters are available to help set up essential dependencies and classes. There is also a collection of sample applications to help you explore the project’s features. Lastly, the new Spring CLI project also enables you to get started quickly by using the spring boot new AI command for new projects or spring boot add AI for adding AI capabilities to your existing application. --- ### Spring Ai Test/Src/Main/Resources/Test/Data/Time.Shelter (spring-ai-test/src/main/resources/test/data/time.shelter.txt) Somewhere in the Andes, they believe in this very day that the future is behind you. It comes up from behind your back, surprising and unforeseeable, while the past is always before your eyes, that which has already happened. When they talk about the past, the people of the Aymara tribe point in front of them. You walk forward facing the past, and you turn back toward the future. ― Georgi Gospodinov, Time Shelter --- ### Spring Ai Tool Search Tool/Src/Main/Resources/DEFAULT SYSTEM PROMPT SUFFIX (spring-ai-tool-search-tool/src/main/resources/DEFAULT_SYSTEM_PROMPT_SUFFIX.md) You have access to a special tool called `toolSearchTool` that allows you to discover relevant tools on-demand. When you need to perform an action but don't see an appropriate tool in your current context, use `toolSearchTool` to search for it. --- ### Spring Ai Tool Search Tool/Src/Main/Resources/DEFAULT SYSTEM PROMPT SUFFIX LARGE (spring-ai-tool-search-tool/src/main/resources/DEFAULT_SYSTEM_PROMPT_SUFFIX_LARGE.md) You are an AI assistant with access to a large library of tools. However, not all tools are loaded into your context initially to conserve context window space and improve accuracy. ### Tool Discovery Process You have access to a special tool called `toolSearchTool` that allows you to discover relevant tools on-demand. When you need to perform an action but don't see an appropriate tool in your current context, use `toolSearchTool` to search for it. **How tool search works:** 1. When you receive a request that may require tools not currently visible to you, call `toolSearchTool` with a search query describing what capability you need 2. The search will return references to matching tools (typically 3-5 most relevant) 3. These tool references will be automatically expanded into full tool definitions that you can then use 4. Select the most appropriate discovered tool and invoke it with the required parameters **When to use tool search:** - When you need a capability not provided by your currently available tools - When the user's request implies operations (database queries, API calls, file operations, etc.) that require specific tools - When you're unsure which tool to use for a complex task - search can help you discover the right one **Search query best practices:** - Use descriptive keywords related to the functionality you need - Include domain-specific terms (e.g., "github pull request", "slack message", "database query") - You can search by functionality ("send notification"), by service ("jira"), or by action type ("create ticket") **Available tool categories in this system:** [PLACEHOLDER: List your tool categories here, e.g., "Slack messaging, GitHub operations, database queries, file management, calendar scheduling"] Remember: After discovering tools via search, you must still invoke them using the standard tool calling mechanism. The search only makes tools visible to you - it doesn't execute them. --- ### Spring Ai Vector Store/Src/Main/Resources/META INF/Additional Spring Configuration Metadata.Json (spring-ai-vector-store/src/main/resources/META-INF/additional-spring-configuration-metadata.json) { "groups": [], "properties": [ { "name": "spring.ai.vectorstore.type", "type": "java.lang.String", "description": "Vector store type. Requires a vector store." } ], "hints": [], "ignored": { "properties": [] } } --- ### Src/Checkstyle/Checkstyle Header (src/checkstyle/checkstyle-header.txt) ^\Q/*\E$ ^\Q * Copyright 2023-present the original author or authors.\E$ ^\Q *\E$ ^\Q * Licensed under the Apache License, Version 2.0 (the "License");\E$ ^\Q * you may not use this file except in compliance with the License.\E$ ^\Q * You may obtain a copy of the License at\E$ ^\Q *\E$ ^\Q * https://www.apache.org/licenses/LICENSE-2.0\E$ ^\Q *\E$ ^\Q * Unless required by applicable law or agreed to in writing, software\E$ ^\Q * distributed under the License is distributed on an "AS IS" BASIS,\E$ ^\Q * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\E$ ^\Q * See the License for the specific language governing permissions and\E$ ^\Q * limitations under the License.\E$ ^\Q */\E$ ^$ ^.*$ --- ### Src/Ecosystem Ci/README (src/ecosystem-ci/README.md) # Ecosystem CI Dashboard This directory contains the configuration for the Spring AI Ecosystem CI Dashboard, which monitors the CI health of key ecosystem dependencies. ## Overview The dashboard workflow runs daily and: 1. Queries CI status for each monitored repository 2. Updates the [Wiki Dashboard](https://github.com/spring-projects/spring-ai/wiki/Ecosystem-CI-Dashboard) with current status 3. Posts alerts to [Issue #5334](https://github.com/spring-projects/spring-ai/issues/5334) when dependencies fail for extended periods ## Subscribing to Alerts To receive notifications when ecosystem dependencies fail CI: 1. Go to [Issue #5334](https://github.com/spring-projects/spring-ai/issues/5334) 2. Click **Subscribe** in the right sidebar 3. You'll receive GitHub notifications when alerts are posted ## Alert Policy | Condition | Action | |-----------|--------| | Dependency fails (day 1) | Dashboard updated, no alert | | Dependency fails for 2+ days | Alert comment posted (triggers notification) | | Dependency recovers | Dashboard updated, no alert | The `alert_after_days` setting in `ci-alert-config.json` controls the threshold (default: 2 days). ## Adding or Removing Dependencies Edit `ci-alert-config.json`: ```json { "dependencies": [ { "owner": "org-name", "repo": "repo-name" }, ... ] } ``` Each dependency must have: - `owner`: GitHub organization or user - `repo`: Repository name The workflow monitors the branch specified by `tracked_branch` (default: `main`). ## Configuration Reference | Field | Description | Default | |-------|-------------|---------| | `issue_number` | GitHub issue for dashboard and alerts | 5334 | | `tracked_branch` | Branch to monitor for each repo | main | | `alert_after_days` | Days of failure before alerting | 2 | | `heartbeat_days` | Minimum days between repeat alerts | 1 | ## Manual Trigger To run the dashboard manually: 1. Go to [Actions > Ecosystem CI Dashboard](https://github.com/spring-projects/spring-ai/actions/workflows/dependency-ci-dashboard.yml) 2. Click **Run workflow** 3. Select the `main` branch and click **Run workflow** ## Files - `ci-alert-config.json` - Dashboard configuration - `../../.github/workflows/dependency-ci-dashboard.yml` - GitHub Actions workflow --- ### Src/Ecosystem Ci/Ci Alert Config.Json (src/ecosystem-ci/ci-alert-config.json) { "issue_number": 5334, "tracked_branch": "main", "alert_after_days": 2, "heartbeat_days": 1, "dependencies": [ { "owner": "modelcontextprotocol", "repo": "java-sdk" }, { "owner": "spring-projects", "repo": "spring-ai-examples" }, { "owner": "spring-projects", "repo": "spring-ai-integration-tests" }, { "owner": "spring-ai-community", "repo": "spring-ai-tool-search-tool" }, { "owner": "spring-ai-community", "repo": "spring-ai-agent-utils" }, { "owner": "spring-ai-community", "repo": "mcp-security" }, { "owner": "spring-ai-community", "repo": "mcp-annotations" } ] } --- ### Src/Prompts/Update To M7 (src/prompts/update-to-m7.txt) Please perform the following three tasks in my project: Important: File Access Instructions - For all file reading operations, use the view tool to view file contents. e.g. cat on linux/mac - For multi-module projects, you'll need to examine multiple pom.xml or build.gradle files - Examples: cat pom.xml # For Maven root project cat module/pom.xml # For Maven modules cat build.gradle # For Gradle cat module/build.gradle # For Gradle modules cat build.gradle.kts # For Kotlin DSL Task 1: Update Spring AI BOM Version to 1.0.0-M7 For Maven (pom.xml): - Replace 1.0.0-M6 or older versions with 1.0.0-M7 within the spring-ai-bom dependency - Use the exact whitespace/indentation from the original file For Gradle (build.gradle or build.gradle.kts): - Update implementation platform("org.springframework.ai:spring-ai-bom:1.0.0-M6") or older versions to: implementation platform("org.springframework.ai:spring-ai-bom:1.0.0-M7") Task 2: Ensure All Required Repositories Exist For Maven (pom.xml): - Verify these three repositories exist in pom.xml file: spring-milestones Spring Milestones https://repo.spring.io/milestone false - Add any missing repositories to the section - Use the existing indentation style from the pom.xml file For Gradle: - Add any missing repositories with proper formatting: repositories { mavenCentral() maven { url = uri("https://repo.spring.io/milestone") mavenContent { releasesOnly() } } } Task 3: Update Spring AI Artifact IDs Apply this pattern for all Spring AI starters: - Model starters: spring-ai-{model}-spring-boot-starter → spring-ai-starter-model-{model} - Vector Store starters: spring-ai-{store}-store-spring-boot-starter → spring-ai-starter-vector-store-{store} - MCP starters: spring-ai-mcp-{type}-spring-boot-starter → spring-ai-starter-mcp-{type} For Maven (pom.xml) - Examples: org.springframework.ai spring-ai-openai-spring-boot-starter org.springframework.ai spring-ai-starter-model-openai For Gradle - Examples: // BEFORE implementation 'org.springframework.ai:spring-ai-openai-spring-boot-starter' implementation 'org.springframework.ai:spring-ai-redis-store-spring-boot-starter' // AFTER implementation 'org.springframework.ai:spring-ai-starter-model-openai' implementation 'org.springframework.ai:spring-ai-starter-vector-store-redis' CRITICAL - Do NOT make these changes: 1. Do NOT change any XML tags such as: - Do NOT change to (leave all tags exactly as they are) - Do NOT modify any other XML elements like , , etc. 2. Do NOT attempt to fix XML formatting: - Do NOT add or remove whitespace except where specifically instructed - Do NOT add or remove newlines - Do NOT reformat XML indentation 3. Make ONLY the three specific changes described above: - Update spring-ai-bom version to 1.0.0-M7 - Add missing repositories from the list above - Update Spring AI artifactIds using the specified patterns For all replacements, maintain the exact indentation and whitespace from the original file. --- ### Src/Prompts/Update To Snapshot (src/prompts/update-to-snapshot.txt) Please perform the following three tasks in my project: Important: File Access Instructions - For all file reading operations, use the view tool to view file contents. e.g. cat on linux/mac - For multi-module projects, you'll need to examine multiple pom.xml or build.gradle files - Examples: cat pom.xml # For Maven root project cat module/pom.xml # For Maven modules cat build.gradle # For Gradle cat module/build.gradle # For Gradle modules cat build.gradle.kts # For Kotlin DSL Task 1: Update Spring AI BOM Version to 1.0.0-SNAPSHOT For Maven (pom.xml): - Replace 1.0.0-M5 with 1.0.0-SNAPSHOT within the spring-ai-bom dependency - Use the exact whitespace/indentation from the original file For Gradle (build.gradle or build.gradle.kts): - Update implementation platform("org.springframework.ai:spring-ai-bom:1.0.0-M5") to: implementation platform("org.springframework.ai:spring-ai-bom:1.0.0-SNAPSHOT") Task 2: Ensure All Required Repositories Exist For Maven (pom.xml): - Verify these three repositories exist in pom.xml file: spring-milestones Spring Milestones https://repo.spring.io/milestone false spring-snapshots Spring Snapshots https://repo.spring.io/snapshot false central-portal-snapshots Central Portal Snapshots https://central.sonatype.com/repository/maven-snapshots/ false true - Add any missing repositories to the section - Use the existing indentation style from the pom.xml file For Gradle: - Add any missing repositories with proper formatting: repositories { mavenCentral() maven { url = uri("https://repo.spring.io/milestone") mavenContent { releasesOnly() } } maven { url = uri("https://repo.spring.io/snapshot") mavenContent { snapshotsOnly() } } maven { url = uri("https://central.sonatype.com/repository/maven-snapshots/") mavenContent { snapshotsOnly() } } } Task 3: Update Spring AI Artifact IDs Apply this pattern for all Spring AI starters: - Model starters: spring-ai-{model}-spring-boot-starter → spring-ai-starter-model-{model} - Vector Store starters: spring-ai-{store}-store-spring-boot-starter → spring-ai-starter-vector-store-{store} - MCP starters: spring-ai-mcp-{type}-spring-boot-starter → spring-ai-starter-mcp-{type} For Maven (pom.xml) - Examples: org.springframework.ai spring-ai-openai-spring-boot-starter org.springframework.ai spring-ai-starter-model-openai For Gradle - Examples: // BEFORE implementation 'org.springframework.ai:spring-ai-openai-spring-boot-starter' implementation 'org.springframework.ai:spring-ai-redis-store-spring-boot-starter' // AFTER implementation 'org.springframework.ai:spring-ai-starter-model-openai' implementation 'org.springframework.ai:spring-ai-starter-vector-store-redis' CRITICAL - Do NOT make these changes: 1. Do NOT change any XML tags such as: - Do NOT change to (leave all tags exactly as they are) - Do NOT modify any other XML elements like , , etc. 2. Do NOT attempt to fix XML formatting: - Do NOT add or remove whitespace except where specifically instructed - Do NOT add or remove newlines - Do NOT reformat XML indentation 3. Make ONLY the three specific changes described above: - Update spring-ai-bom version to 1.0.0-SNAPSHOT - Add missing repositories from the list above - Update Spring AI artifactIds using the specified patterns For all replacements, maintain the exact indentation and whitespace from the original file. --- ### Src/Rewrite/Migrate To 2 0 0 M3.Yaml (src/rewrite/migrate-to-2-0-0-M3.yaml) --- type: specs.openrewrite.org/v1beta/recipe name: org.springframework.ai.migration.MigrateToSpringAI200M3 displayName: Migrate to Spring AI 2.0.0-M3 description: > Umbrella recipe that applies all breaking-change migrations required for Spring AI 2.0.0-M3. Run this recipe to perform all changes in one step. Included migrations: - M3MigrateMcpAnnotations: org.springaicommunity:mcp-annotations → spring-ai-mcp-annotations - M3MigrateMcpSpringTransports: io.modelcontextprotocol.sdk mcp-spring-webflux/webmvc → org.springframework.ai - M3MigrateMcpClientCustomizer: McpAsyncClientCustomizer / McpSyncClientCustomizer → McpClientCustomizer tags: - spring-ai - mcp - migration recipeList: - org.springframework.ai.migration.M3MigrateMcpAnnotations - org.springframework.ai.migration.M3MigrateMcpSpringTransports - org.springframework.ai.migration.M3MigrateMcpClientCustomizer --- type: specs.openrewrite.org/v1beta/recipe name: org.springframework.ai.migration.M3MigrateMcpAnnotations displayName: Migrate MCP annotations from springaicommunity to Spring AI description: > Migrates all MCP annotation, method-callback, provider, and context classes from the removed `org.springaicommunity:mcp-annotations` library to their new locations inside `org.springframework.ai:spring-ai-mcp-annotations`. Package changes: org.springaicommunity.mcp.annotation.* → org.springframework.ai.mcp.annotation.* org.springaicommunity.mcp.method.* → org.springframework.ai.mcp.annotation.method.* org.springaicommunity.mcp.provider.* → org.springframework.ai.mcp.annotation.provider.* org.springaicommunity.mcp.context.* → org.springframework.ai.mcp.annotation.context.* tags: - spring-ai - mcp - migration recipeList: # ------------------------------------------------------------------------- # Maven: remove the old external dependency (classes are now in spring-ai) # ------------------------------------------------------------------------- - org.openrewrite.maven.RemoveDependency: groupId: org.springaicommunity artifactId: mcp-annotations # ------------------------------------------------------------------------- # Java: text-based package renamings (no classpath resolution needed). # Sub-packages (method, provider, context) must come before the parent # annotation package to avoid double-rewriting already-replaced strings. # ------------------------------------------------------------------------- - org.openrewrite.text.FindAndReplace: find: "org.springaicommunity.mcp.method." replace: "org.springframework.ai.mcp.annotation.method." filePattern: "**/*.java" - org.openrewrite.text.FindAndReplace: find: "org.springaicommunity.mcp.provider." replace: "org.springframework.ai.mcp.annotation.provider." filePattern: "**/*.java" - org.openrewrite.text.FindAndReplace: find: "org.springaicommunity.mcp.context." replace: "org.springframework.ai.mcp.annotation.context." filePattern: "**/*.java" - org.openrewrite.text.FindAndReplace: find: "org.springaicommunity.mcp.annotation." replace: "org.springframework.ai.mcp.annotation." filePattern: "**/*.java" --- type: specs.openrewrite.org/v1beta/recipe name: org.springframework.ai.migration.M3MigrateMcpSpringTransports displayName: Migrate MCP Spring transport modules from MCP Java SDK to Spring AI description: > Migrates the `mcp-spring-webflux` and `mcp-spring-webmvc` transport modules from the MCP Java SDK (`io.modelcontextprotocol.sdk`) to Spring AI (`org.springframework.ai`). Maven dependency group ID changes: io.modelcontextprotocol.sdk:mcp-spring-webflux → org.springframework.ai:mcp-spring-webflux io.modelcontextprotocol.sdk:mcp-spring-webmvc → org.springframework.ai:mcp-spring-webmvc Java package changes (server transports): io.modelcontextprotocol.server.transport.WebFluxSseServerTransportProvider → org.springframework.ai.mcp.server.webflux.transport io.modelcontextprotocol.server.transport.WebFluxStreamableServerTransportProvider → org.springframework.ai.mcp.server.webflux.transport io.modelcontextprotocol.server.transport.WebFluxStatelessServerTransport → org.springframework.ai.mcp.server.webflux.transport io.modelcontextprotocol.server.transport.WebMvcSseServerTransportProvider → org.springframework.ai.mcp.server.webmvc.transport io.modelcontextprotocol.server.transport.WebMvcStreamableServerTransportProvider → org.springframework.ai.mcp.server.webmvc.transport io.modelcontextprotocol.server.transport.WebMvcStatelessServerTransport → org.springframework.ai.mcp.server.webmvc.transport Java package changes (client transports): io.modelcontextprotocol.client.transport.WebFluxSseClientTransport → org.springframework.ai.mcp.client.webflux.transport io.modelcontextprotocol.client.transport.WebClientStreamableHttpTransport → org.springframework.ai.mcp.client.webflux.transport tags: - spring-ai - mcp - migration recipeList: # ------------------------------------------------------------------------- # Maven: change group ID for the WebFlux transport. # Text-based regex replacement is used instead of # org.openrewrite.maven.ChangeDependencyGroupIdAndArtifactId because that # recipe requires Maven to fully resolve the POM model first — which fails # when the dependency declares no (version managed via BOM/parent). # The \s+ capture group preserves whatever whitespace/indentation the file uses. # ------------------------------------------------------------------------- - org.openrewrite.text.FindAndReplace: find: "io\\.modelcontextprotocol\\.sdk(\\s+)mcp-spring-webflux" replace: "org.springframework.ai$1mcp-spring-webflux" regex: true filePattern: "**/pom.xml" # ------------------------------------------------------------------------- # Maven: change group ID for the WebMvc transport (same rationale as above). # ------------------------------------------------------------------------- - org.openrewrite.text.FindAndReplace: find: "io\\.modelcontextprotocol\\.sdk(\\s+)mcp-spring-webmvc" replace: "org.springframework.ai$1mcp-spring-webmvc" regex: true filePattern: "**/pom.xml" # ------------------------------------------------------------------------- # Java: server transport classes (WebFlux) # FindAndReplace is used instead of ChangeType because the old artifacts are # no longer on the classpath, making AST-based type resolution impossible. # ------------------------------------------------------------------------- - org.openrewrite.text.FindAndReplace: find: "io.modelcontextprotocol.server.transport.WebFluxSseServerTransportProvider" replace: "org.springframework.ai.mcp.server.webflux.transport.WebFluxSseServerTransportProvider" filePattern: "**/*.java" - org.openrewrite.text.FindAndReplace: find: "io.modelcontextprotocol.server.transport.WebFluxStreamableServerTransportProvider" replace: "org.springframework.ai.mcp.server.webflux.transport.WebFluxStreamableServerTransportProvider" filePattern: "**/*.java" - org.openrewrite.text.FindAndReplace: find: "io.modelcontextprotocol.server.transport.WebFluxStatelessServerTransport" replace: "org.springframework.ai.mcp.server.webflux.transport.WebFluxStatelessServerTransport" filePattern: "**/*.java" # ------------------------------------------------------------------------- # Java: server transport classes (WebMvc) # ------------------------------------------------------------------------- - org.openrewrite.text.FindAndReplace: find: "io.modelcontextprotocol.server.transport.WebMvcSseServerTransportProvider" replace: "org.springframework.ai.mcp.server.webmvc.transport.WebMvcSseServerTransportProvider" filePattern: "**/*.java" - org.openrewrite.text.FindAndReplace: find: "io.modelcontextprotocol.server.transport.WebMvcStreamableServerTransportProvider" replace: "org.springframework.ai.mcp.server.webmvc.transport.WebMvcStreamableServerTransportProvider" filePattern: "**/*.java" - org.openrewrite.text.FindAndReplace: find: "io.modelcontextprotocol.server.transport.WebMvcStatelessServerTransport" replace: "org.springframework.ai.mcp.server.webmvc.transport.WebMvcStatelessServerTransport" filePattern: "**/*.java" # ------------------------------------------------------------------------- # Java: client transport classes (WebFlux) # ------------------------------------------------------------------------- - org.openrewrite.text.FindAndReplace: find: "io.modelcontextprotocol.client.transport.WebFluxSseClientTransport" replace: "org.springframework.ai.mcp.client.webflux.transport.WebFluxSseClientTransport" filePattern: "**/*.java" - org.openrewrite.text.FindAndReplace: find: "io.modelcontextprotocol.client.transport.WebClientStreamableHttpTransport" replace: "org.springframework.ai.mcp.client.webflux.transport.WebClientStreamableHttpTransport" filePattern: "**/*.java" # ------------------------------------------------------------------------- # Java: McpJsonMapper.createDefault() → McpJsonDefaults.getMapper() # The factory method moved from McpJsonMapper to McpJsonDefaults. # Replace the call first, then the import so the import line is also updated. # ------------------------------------------------------------------------- - org.openrewrite.text.FindAndReplace: find: "McpJsonMapper.createDefault()" replace: "McpJsonDefaults.getMapper()" filePattern: "**/*.java" # Always add the McpJsonDefaults import alongside McpJsonMapper. # If McpJsonMapper is no longer used after the call-site replacement above, # it will surface as an unused-import warning for manual cleanup. - org.openrewrite.text.FindAndReplace: find: "import io.modelcontextprotocol.json.McpJsonMapper;" replace: "import io.modelcontextprotocol.json.McpJsonDefaults;\nimport io.modelcontextprotocol.json.McpJsonMapper;" filePattern: "**/*.java" --- type: specs.openrewrite.org/v1beta/recipe name: org.springframework.ai.migration.M3MigrateMcpClientCustomizer displayName: Migrate McpAsyncClientCustomizer and McpSyncClientCustomizer to McpClientCustomizer description: > Replaces the removed `McpAsyncClientCustomizer` and `McpSyncClientCustomizer` interfaces with the new generic `McpClientCustomizer` interface introduced in Spring AI 2.0.0-M3. Changes applied: - Import `org.springframework.ai.mcp.customizer.McpAsyncClientCustomizer` → `org.springframework.ai.mcp.customizer.McpClientCustomizer` + adds `import io.modelcontextprotocol.client.McpClient;` - Import `org.springframework.ai.mcp.customizer.McpSyncClientCustomizer` → `org.springframework.ai.mcp.customizer.McpClientCustomizer` + adds `import io.modelcontextprotocol.client.McpClient;` - Simple-name usage `McpAsyncClientCustomizer` → `McpClientCustomizer` - Simple-name usage `McpSyncClientCustomizer` → `McpClientCustomizer` NOTE: `McpSyncHttpClientRequestCustomizer` and `McpAsyncHttpClientRequestCustomizer` (from `io.modelcontextprotocol.client.transport.customizer`) are no longer applied by the auto-configurations. Migrate them manually to `McpClientCustomizer` or `McpClientCustomizer` as appropriate. tags: - spring-ai - mcp - migration recipeList: # ------------------------------------------------------------------------- # Step 1 — rewrite the fully-qualified import for McpAsyncClientCustomizer. # The McpClient import is added at the same time because the new parameterised # type McpClientCustomizer requires it at the call-site. # ------------------------------------------------------------------------- - org.openrewrite.text.FindAndReplace: find: "import org.springframework.ai.mcp.customizer.McpAsyncClientCustomizer;" replace: "import io.modelcontextprotocol.client.McpClient;\nimport org.springframework.ai.mcp.customizer.McpClientCustomizer;" filePattern: "**/*.java" # ------------------------------------------------------------------------- # Step 2 — rewrite the fully-qualified import for McpSyncClientCustomizer. # ------------------------------------------------------------------------- - org.openrewrite.text.FindAndReplace: find: "import org.springframework.ai.mcp.customizer.McpSyncClientCustomizer;" replace: "import io.modelcontextprotocol.client.McpClient;\nimport org.springframework.ai.mcp.customizer.McpClientCustomizer;" filePattern: "**/*.java" # ------------------------------------------------------------------------- # Step 3 — replace simple-name occurrences of McpAsyncClientCustomizer # (return types, implements clauses, parameter types, variable declarations). # Must run AFTER the import replacement so the import line is not touched # again (it no longer contains "McpAsyncClientCustomizer" at this point). # ------------------------------------------------------------------------- - org.openrewrite.text.FindAndReplace: find: "McpAsyncClientCustomizer" replace: "McpClientCustomizer" filePattern: "**/*.java" # ------------------------------------------------------------------------- # Step 4 — replace simple-name occurrences of McpSyncClientCustomizer. # ------------------------------------------------------------------------- - org.openrewrite.text.FindAndReplace: find: "McpSyncClientCustomizer" replace: "McpClientCustomizer" filePattern: "**/*.java" --- ### Vector Stores/Spring Ai Azure Store/README (vector-stores/spring-ai-azure-store/README.md) [Azure AI Search Vector Store Documentation](https://docs.spring.io/spring-ai/reference/api/vectordbs/azure.html) --- ### Vector Stores/Spring Ai Cassandra Store/README (vector-stores/spring-ai-cassandra-store/README.md) [Apache Cassandra Vector Store Documentation](https://docs.spring.io/spring-ai/reference/api/vectordbs/apache-cassandra.html) --- ### Vector Stores/Spring Ai Chroma Store/README (vector-stores/spring-ai-chroma-store/README.md) [Chroma Vector Store Documentation](https://docs.spring.io/spring-ai/reference/api/vectordbs/chroma.html) --- ### Vector Stores/Spring Ai Coherence Store/README (vector-stores/spring-ai-coherence-store/README.md) [Oracle Coherence Vector Search Documentation](https://docs.oracle.com/) --- ### Vector Stores/Spring Ai Couchbase Store/README (vector-stores/spring-ai-couchbase-store/README.md) [Couchbase Vector Store Documentation](https://docs.spring.io/spring-ai/reference/1.0-SNAPSHOT/api/vectordbs/couchbase.html) --- ### Vector Stores/Spring Ai Gemfire Store/README (vector-stores/spring-ai-gemfire-store/README.md) [GemFire Vector Store Documentation](https://docs.spring.io/spring-ai/reference/api/vectordbs/gemfire.html) --- ### Vector Stores/Spring Ai Mariadb Store/README (vector-stores/spring-ai-mariadb-store/README.md) [MariaDB Vector Store Documentation](https://docs.spring.io/spring-ai/reference/api/vectordbs/mariadb.html) --- ### Vector Stores/Spring Ai Milvus Store/README (vector-stores/spring-ai-milvus-store/README.md) [Milvus Vector Store Documentation](https://docs.spring.io/spring-ai/reference/api/vectordbs/milvus.html) --- ### Vector Stores/Spring Ai Neo4j Store/README (vector-stores/spring-ai-neo4j-store/README.md) [Neo4j Vector Store Documentation](https://docs.spring.io/spring-ai/reference/api/vectordbs/neo4j.html) --- ### Vector Stores/Spring Ai Oracle Store/README (vector-stores/spring-ai-oracle-store/README.md) [Oracle AI Vector Search Documentation](https://docs.oracle.com/en/database/oracle/oracle-database/23/nfcoa/ai_vector_search.html) --- ### Vector Stores/Spring Ai Pgvector Store/README (vector-stores/spring-ai-pgvector-store/README.md) [PGvector Vector Store Documentation](https://docs.spring.io/spring-ai/reference/api/vectordbs/pgvector.html) --- ### Vector Stores/Spring Ai Pinecone Store/README (vector-stores/spring-ai-pinecone-store/README.md) [Pinecone Vector Store Documentation](https://docs.spring.io/spring-ai/reference/api/vectordbs/pinecone.html) --- ### Vector Stores/Spring Ai Qdrant Store/README (vector-stores/spring-ai-qdrant-store/README.md) # Qdrant Vector Store [Reference Documentation](https://docs.spring.io/spring-ai/reference/api/vectordbs/qdrant.html) ## Run locally ### Accessing the Web UI First, run the Docker container: ``` docker run -p 6333:6333 -p 6334:6334 \ -v $(pwd)/qdrant_storage:/qdrant/storage:z \ qdrant/qdrant ``` ### Security: Adding API Key to Qdrant Container To enhance security, you can add an API key to your Qdrant container using the environment variable. ``` -e QDRANT__SERVICE__API_KEY= ``` This ensures that only authorized users with the correct API key can access the Qdrant service. The GUI is available at http://localhost:6333/dashboard ## Qdrant references - https://qdrant.tech/documentation/interfaces/ - https://github.com/qdrant/java-client --- ### Vector Stores/Spring Ai Redis Semantic Cache/README (vector-stores/spring-ai-redis-semantic-cache/README.md) # Redis Semantic Cache for Spring AI This module provides a Redis-based implementation of semantic caching for Spring AI. ## Overview Semantic caching allows storing and retrieving chat responses based on the semantic similarity of user queries. This implementation uses Redis vector search capabilities to efficiently find similar queries and return cached responses. ## Features - Store chat responses with their associated queries in Redis - Retrieve responses based on semantic similarity - Support for time-based expiration of cached entries - Includes a ChatClient advisor for automatic caching - Built on Redis vector search technology ## Requirements - Redis Stack with Redis Query Engine and RedisJSON modules - Java 17 or later - Spring AI core dependencies - An embedding model for vector generation ## Usage ### Maven Configuration ```xml org.springframework.ai spring-ai-redis-semantic-cache ``` For Spring Boot applications, you can use the starter: ```xml org.springframework.ai spring-ai-starter-vector-store-redis-semantic-cache ``` ### Basic Usage ```java // Create Redis client RedisClient jedisClient = RedisClient.builder().hostAndPort("localhost", 6379).build(); // Create the embedding model EmbeddingModel embeddingModel = new OpenAiEmbeddingModel(apiKey); // Create the semantic cache SemanticCache semanticCache = DefaultSemanticCache.builder() .jedisClient(jedisClient) .embeddingModel(embeddingModel) .similarityThreshold(0.85) // Optional: adjust similarity threshold (0-1) .build(); // Create the cache advisor SemanticCacheAdvisor cacheAdvisor = SemanticCacheAdvisor.builder() .cache(semanticCache) .build(); // Use with ChatClient ChatResponse response = ChatClient.builder(chatModel) .build() .prompt("What is the capital of France?") .advisors(cacheAdvisor) // Add the advisor .call() .chatResponse(); ``` ### Direct Cache Usage You can also use the cache directly: ```java // Store a response semanticCache.set("What is the capital of France?", parisResponse); // Store with expiration semanticCache.set("What's the weather today?", weatherResponse, Duration.ofHours(1)); // Retrieve a semantically similar response Optional response = semanticCache.get("Tell me the capital city of France"); // Clear the cache semanticCache.clear(); ``` ## Configuration Options The `DefaultSemanticCache` can be configured with the following options: - `jedisClient` - The Redis client - `vectorStore` - Optional existing vector store to use - `embeddingModel` - The embedding model for vector generation - `similarityThreshold` - Threshold for determining similarity (0-1) - `indexName` - The name of the Redis search index - `prefix` - Key prefix for Redis documents ## Spring Boot Integration When using Spring Boot and the Redis Semantic Cache starter, the components will be automatically configured. You can customize behavior using properties in `application.properties` or `application.yml`: ```yaml spring: ai: vectorstore: redis: semantic-cache: host: localhost port: 6379 similarity-threshold: 0.85 index-name: semantic-cache ``` --- ### Vector Stores/Spring Ai Redis Store/README (vector-stores/spring-ai-redis-store/README.md) # Spring AI Redis Vector Store A Redis-based vector store implementation for Spring AI using Redis Stack with Redis Query Engine and RedisJSON. ## Documentation For comprehensive documentation, see the [Redis Vector Store Documentation](https://docs.spring.io/spring-ai/reference/api/vectordbs/redis.html). ## Features - Vector similarity search using KNN - Range-based vector search with radius threshold - Text-based search on TEXT fields - Support for multiple distance metrics (COSINE, L2, IP) - Multiple text scoring algorithms (BM25, TFIDF, etc.) - HNSW and FLAT vector indexing algorithms - Configurable metadata fields (TEXT, TAG, NUMERIC) - Filter expressions for advanced filtering - Batch processing support ## Usage ### KNN Search The standard similarity search returns the k-nearest neighbors: ```java // Create Redis client RedisClient jedisClient = RedisClient.builder().hostAndPort("localhost", 6379).build(); // Create the vector store RedisVectorStore vectorStore = RedisVectorStore.builder(jedisClient, embeddingModel) .indexName("my-index") .vectorAlgorithm(Algorithm.HNSW) .distanceMetric(DistanceMetric.COSINE) .build(); // Add documents vectorStore.add(List.of( new Document("content1", Map.of("category", "AI")), new Document("content2", Map.of("category", "DB")) )); // Search with KNN List results = vectorStore.similaritySearch( SearchRequest.builder() .query("AI and machine learning") .topK(5) .similarityThreshold(0.7) .filterExpression("category == 'AI'") .build() ); ``` ### Text Search The text search capability allows you to find documents based on keywords and phrases in TEXT fields: ```java // Search for documents containing specific text List textResults = vectorStore.searchByText( "machine learning", // search query "content", // field to search (must be TEXT type) 10, // limit "category == 'AI'" // optional filter expression ); ``` Text search supports: - Single word searches - Phrase searches with exact matching when `inOrder` is true - Term-based searches with OR semantics when `inOrder` is false - Stopword filtering to ignore common words - Multiple text scoring algorithms (BM25, TFIDF, DISMAX, etc.) Configure text search behavior at construction time: ```java RedisClient jedisClient = RedisClient.builder().hostAndPort("localhost", 6379).build(); RedisVectorStore vectorStore = RedisVectorStore.builder(jedisClient, embeddingModel) .textScorer(TextScorer.TFIDF) // Text scoring algorithm .inOrder(true) // Match terms in order .stopwords(Set.of("is", "a", "the", "and")) // Ignore common words .metadataFields(MetadataField.text("description")) // Define TEXT fields .build(); ``` ### Range Search The range search returns all documents within a specified radius: ```java // Search with radius List rangeResults = vectorStore.searchByRange( "AI and machine learning", // query 0.8, // radius (similarity threshold) "category == 'AI'" // optional filter expression ); ``` You can also set a default range threshold at construction time: ```java RedisClient jedisClient = RedisClient.builder().hostAndPort("localhost", 6379).build(); RedisVectorStore vectorStore = RedisVectorStore.builder(jedisClient, embeddingModel) .defaultRangeThreshold(0.8) // Set default threshold .build(); // Use default threshold List results = vectorStore.searchByRange("query"); ``` ## Configuration Options The Redis Vector Store supports multiple configuration options: ```java RedisClient jedisClient = RedisClient.builder().hostAndPort("localhost", 6379).build(); RedisVectorStore vectorStore = RedisVectorStore.builder(jedisClient, embeddingModel) .indexName("custom-index") // Redis index name .prefix("custom-prefix") // Redis key prefix .contentFieldName("content") // Field for document content .embeddingFieldName("embedding") // Field for vector embeddings .vectorAlgorithm(Algorithm.HNSW) // Vector algorithm (HNSW or FLAT) .distanceMetric(DistanceMetric.COSINE) // Distance metric .hnswM(32) // HNSW parameter for connections .hnswEfConstruction(100) // HNSW parameter for index building .hnswEfRuntime(50) // HNSW parameter for search .defaultRangeThreshold(0.8) // Default radius for range searches .textScorer(TextScorer.BM25) // Text scoring algorithm .inOrder(true) // Match terms in order .stopwords(Set.of("the", "and")) // Stopwords to ignore .metadataFields( // Metadata field definitions MetadataField.tag("category"), MetadataField.numeric("year"), MetadataField.text("description") ) .initializeSchema(true) // Auto-create index schema .build(); ``` ## Distance Metrics The Redis Vector Store supports three distance metrics: - **COSINE**: Cosine similarity (default) - **L2**: Euclidean distance - **IP**: Inner Product Each metric is automatically normalized to a 0-1 similarity score, where 1 is most similar. ## Text Scoring Algorithms For text search, several scoring algorithms are supported: - **BM25**: Modern version of TF-IDF with term saturation (default) - **TFIDF**: Classic term frequency-inverse document frequency - **BM25STD**: Standardized BM25 - **DISMAX**: Disjunction max - **DOCSCORE**: Document score Scores are normalized to a 0-1 range for consistency with vector similarity scores. --- ### Vector Stores/Spring Ai Weaviate Store/README (vector-stores/spring-ai-weaviate-store/README.md) [Weaviate Vector Store Documentation](https://docs.spring.io/spring-ai/reference/api/vectordbs/weaviate.html) --- ### Vector Stores/Spring Ai Weaviate Store/Src/Test/Resources/Docker Compose.Yml (vector-stores/spring-ai-weaviate-store/src/test/resources/docker-compose.yml) version: '3.4' services: weaviate: command: - --host - 0.0.0.0 - --port - '8080' - --scheme - http image: semitechnologies/weaviate:1.31.22 ports: - "8080:8080" restart: on-failure:0 environment: QUERY_DEFAULTS_LIMIT: 25 AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true' PERSISTENCE_DATA_PATH: '/var/lib/weaviate' DEFAULT_VECTORIZER_MODULE: 'none' CLUSTER_HOSTNAME: 'node1' --- ### .Github/PULL REQUEST TEMPLATE (.github/PULL_REQUEST_TEMPLATE.md) Thank you for taking time to contribute this pull request! You might have already read the [contributor guide][1], but as a reminder, please make sure to: * Add a Signed-off-by line to each commit (`git commit -s`) per the [DCO](https://spring.io/blog/2025/01/06/hello-dco-goodbye-cla-simplifying-contributions-to-spring#how-to-use-developer-certificate-of-origin) * Rebase your changes on the latest `main` branch and squash your commits * Add/Update unit tests as needed * Run a build and make sure all tests pass prior to submission For more details, please check the [contributor guide][1]. Thank you upfront! [1]: https://github.com/spring-projects/spring-ai/blob/main/CONTRIBUTING.adoc --- ### .Github/Release Files Spec.Json (.github/release-files-spec.json) { "files": [ { "aql": { "items.find": { "$and": [ { "@build.name": "${buildname}", "@build.number": "${buildnumber}", "path": {"$match": "org*"} }, { "$or": [ { "name": {"$match": "*.pom"} }, { "name": {"$match": "*.jar"} } ] } ] } }, "target": "nexus/" } ] } --- ### .Github/Workflow Generator.Yml (.github/workflow-generator.yml) workflow: generator: project: java: versions: primary: 17 workflows: release-train: build: env: COMMERCIAL_ARTIFACTORY_USERNAME: secrets.COMMERCIAL_ARTIFACTORY_USERNAME COMMERCIAL_ARTIFACTORY_PASSWORD: secrets.COMMERCIAL_ARTIFACTORY_PASSWORD COMMERCIAL_RELEASE_REPO_URL: vars.COMMERCIAL_RELEASE_REPO_URL test: env: COMMERCIAL_ARTIFACTORY_USERNAME: secrets.COMMERCIAL_ARTIFACTORY_USERNAME COMMERCIAL_ARTIFACTORY_PASSWORD: secrets.COMMERCIAL_ARTIFACTORY_PASSWORD COMMERCIAL_RELEASE_REPO_URL: vars.COMMERCIAL_RELEASE_REPO_URL --- ### .Github/Actions/Create Github Release/Action.Yml (.github/actions/create-github-release/action.yml) name: Create GitHub Release description: 'Create the release on GitHub with a changelog' inputs: commercial: description: 'Whether to generate the changelog for the commercial release' required: true draft: description: 'Whether to create the release as a draft' required: false default: 'false' latest: description: 'Whether the release is the latest release' required: false default: 'false' milestone: description: 'Name of the GitHub milestone for which a release will be created' required: true pre-release: description: 'Whether the release is a pre-release (a milestone or release candidate)' required: false default: 'false' token: description: 'Token to use for authentication with GitHub' required: true runs: using: composite steps: - name: Generate Changelog uses: spring-io/github-changelog-generator@f7d7a87a3e7c627ecb8c26cf086c38ac5a939721 #v0.0.14 with: config-file: ${{ inputs.commercial == 'true' && '.github/actions/create-github-release/changelog-generator-commercial.yml' || '.github/actions/create-github-release/changelog-generator-oss.yml' }} milestone: ${{ inputs.milestone }} token: ${{ inputs.token }} - name: Create GitHub Release shell: bash env: GITHUB_TOKEN: ${{ inputs.token }} TAG: ${{ format('v{0}', inputs.milestone) }} run: gh release create "$TAG" --title "$TAG" --verify-tag --notes-file changelog.md ${{ inputs.pre-release == 'true' && '--prerelease' || format('--latest={0}', inputs.latest) }} ${{ inputs.draft == 'true' && '--draft' || '' }} --- ### .Github/Actions/Create Github Release/Changelog Generator Commercial.Yml (.github/actions/create-github-release/changelog-generator-commercial.yml) changelog: issues: generate_links: false contributors: exclude: names: - "tzolov" - "sdeleuze" - "ilayaperumalg" - "ericbottard" - "sobychacko" - "dimitarproynov" --- ### .Github/Actions/Create Github Release/Changelog Generator Oss.Yml (.github/actions/create-github-release/changelog-generator-oss.yml) changelog: issues: generate_links: true contributors: exclude: names: - "tzolov" - "sdeleuze" - "ilayaperumalg" - "ericbottard" - "sobychacko" - "dimitarproynov" --- ### .Github/Actions/Do Autoconfigure Test/Action.Yml (.github/actions/do-autoconfigure-test/action.yml) name: "Run Spring AI Autoconfigure Integration Tests" description: "Run integration tests for all Spring AI auto-configuration modules" inputs: spring-ai-branch: description: "Spring AI branch being tested (used for branch-specific test conditions)" required: true default: "main" maven-properties: description: "Additional Maven properties to pass to the build" required: false default: "" spring-boot-version: description: "Spring Boot version to test against (leave empty to use the project default)" required: false default: "" runs: using: "composite" steps: - name: Check environment uses: actions/github-script@v7 with: script: | const env = ${{ toJson(env) }} const emptyEnvEntries = Object.entries(env).filter(e => e[1].length === 0) emptyEnvEntries.length > 0 && core.setFailed('Missing value for environment variable(s): ' + emptyEnvEntries.map(e => e[0]).join(', ')); - name: Run Spring AI Retry Autoconfigure test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/common/spring-ai-autoconfigure-retry \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Chat Observation test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/chat/observation/spring-ai-autoconfigure-model-chat-observation \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Embedding Observation test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/embedding/observation/spring-ai-autoconfigure-model-embedding-observation \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Image Observation test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/image/observation/spring-ai-autoconfigure-model-image-observation \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Chat Client test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/chat/client/spring-ai-autoconfigure-model-chat-client \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Neo4j Chat memory repository test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-neo4j \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Cassandra Chat memory repository test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-cassandra \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure JDBC Chat memory repository test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure MongoDB Chat memory repository test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-mongodb \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Redis Chat memory test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-redis \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Tooling test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/tool/spring-ai-autoconfigure-model-tool \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Anthropic Model test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/spring-ai-autoconfigure-model-anthropic \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure DeepSeek test if: ${{ inputs.spring-ai-branch == 'main' }} shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/spring-ai-autoconfigure-model-deepseek \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure ElevenLabs test if: ${{ inputs.spring-ai-branch == 'main' }} shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Google GenAI test if: ${{ inputs.spring-ai-branch == 'main' }} shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/spring-ai-autoconfigure-model-google-genai \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Azure OpenAI test if: ${{ inputs.spring-ai-branch == '1.0.x' || inputs.spring-ai-branch == '1.1.x' }} shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/spring-ai-autoconfigure-model-azure-openai \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Bedrock AI test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Huggingface test if: ${{ inputs.spring-ai-branch == '1.1.x' || inputs.spring-ai-branch == '1.0.x' }} shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/spring-ai-autoconfigure-model-huggingface \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Minimax test if: ${{ inputs.spring-ai-branch == '1.0.x' || inputs.spring-ai-branch == '1.1.x' }} shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/spring-ai-autoconfigure-model-minimax \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Mistral AI test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure OCI GenAI test if: ${{ inputs.spring-ai-branch == '1.1.x' || inputs.spring-ai-branch == '1.0.x' }} shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/spring-ai-autoconfigure-model-oci-genai \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Ollama test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/spring-ai-autoconfigure-model-ollama \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure OpenAI test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/spring-ai-autoconfigure-model-openai \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure PostgresML Embedding test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/spring-ai-autoconfigure-model-postgresml-embedding \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Stability AI test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/spring-ai-autoconfigure-model-stability-ai \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Transformers test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/spring-ai-autoconfigure-model-transformers \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Vertex AI test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure ZhipuAI test if: ${{ inputs.spring-ai-branch == '1.1.x' || inputs.spring-ai-branch == '1.0.x' }} shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/models/spring-ai-autoconfigure-model-zhipuai \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Azure vector store test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-azure \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Azure Cosmos DB test if: ${{ inputs.spring-ai-branch == '1.1.x' || inputs.spring-ai-branch == '1.0.x' }} shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-azure-cosmos-db \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Cassandra Vector Store test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Chroma Vector Store test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-chroma \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Couchbase Vector Store test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-couchbase \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure ElasticSearch Vector Store test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-elasticsearch \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure GemFire Vector Store test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-gemfire \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Mariadb Vector Store test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mariadb \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Milvus Vector Store test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-milvus \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure MongoDB Atlas Vector Store test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mongodb-atlas \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Neo4j Vector Store test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-neo4j \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Vector Store Observation test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-observation \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Opensearch Vector Store test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-opensearch \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Oracle Vector Store test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-oracle \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Pgvector test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-pgvector \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Pinecone Vector Store test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-pinecone \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Qdrant Vector Store test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-qdrant \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Redis Vector Store test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-redis \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Redis Semantic Cache Vector Store test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-redis-semantic-cache \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Typesense Vector Store test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-typesense \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure Weaviate Vector Store test shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-weaviate \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure MCP Client test if: ${{ inputs.spring-ai-branch == '1.0.x' }} shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/mcp/spring-ai-autoconfigure-mcp-client \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure MCP common Client test if: ${{ inputs.spring-ai-branch == 'main' }} shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-common \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure MCP HTTP Client test if: ${{ inputs.spring-ai-branch == 'main' }} shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-httpclient \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure MCP Webflux Client test if: ${{ inputs.spring-ai-branch == 'main' }} shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-webflux \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure MCP Server test if: ${{ inputs.spring-ai-branch == '1.0.x' }} shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/mcp/spring-ai-autoconfigure-mcp-server \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure MCP common Server test if: ${{ inputs.spring-ai-branch == 'main' }} shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/mcp/spring-ai-autoconfigure-mcp-server-common \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure MCP Webflux Server test if: ${{ inputs.spring-ai-branch == 'main' }} shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/mcp/spring-ai-autoconfigure-mcp-server-webflux \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify - name: Run Spring AI Autoconfigure MCP WebMVC Server test if: ${{ inputs.spring-ai-branch == 'main' }} shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl auto-configurations/mcp/spring-ai-autoconfigure-mcp-server-webmvc \ -Pintegration-tests ${{ inputs.maven-properties }} ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} -Dfailsafe.rerunFailingTestsCount=2 verify --- ### .Github/Actions/Do Integration Test/Action.Yml (.github/actions/do-integration-test/action.yml) name: "Run Spring AI Integration Test" description: "Run integration tests for a single Spring AI model module" inputs: model-name: description: "Spring AI model to integration test (e.g. ollama, anthropic, mistral-ai)" required: true maven-properties: description: "Additional Maven properties to pass to the build" required: false default: "" spring-boot-version: description: "Spring Boot version to test against (leave empty to use the project default)" required: false default: "" runs: using: "composite" steps: - name: Check environment uses: actions/github-script@v7 with: script: | const env = ${{ toJson(env) }} const emptyEnvEntries = Object.entries(env).filter(e => e[1].length === 0) emptyEnvEntries.length > 0 && core.setFailed('Missing value for environment variable(s): ' + emptyEnvEntries.map(e => e[0]).join(', ')); - name: Run ${{ inputs.model-name }} model tests shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl models/spring-ai-${{ inputs.model-name }} \ -Pintegration-tests \ ${{ inputs.maven-properties }} \ ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} \ -Dfailsafe.rerunFailingTestsCount=2 \ verify --- ### .Github/Actions/Do Multi Module Test/Action.Yml (.github/actions/do-multi-module-test/action.yml) name: "Run Spring AI Multi-Module Integration Tests" description: "Run integration tests for multiple Spring AI modules" inputs: modules: description: "Comma-separated list of modules to test" required: true maven-properties: description: "Additional Maven properties to pass to the build" required: false default: "" spring-boot-version: description: "Spring Boot version to test against (leave empty to use the project default)" required: false default: "" runs: using: "composite" steps: - name: Check environment uses: actions/github-script@v7 with: script: | const env = ${{ toJson(env) }} const emptyEnvEntries = Object.entries(env).filter(e => e[1].length === 0) emptyEnvEntries.length > 0 && core.setFailed('Missing value for environment variable(s): ' + emptyEnvEntries.map(e => e[0]).join(', ')); - name: Run integration tests shell: bash run: | echo 'Running with maven properties:' ${{ inputs.maven-properties }} ./mvnw --batch-mode -ntp --no-snapshot-updates \ -pl ${{ inputs.modules }} \ -Pintegration-tests \ ${{ inputs.maven-properties }} \ ${{ inputs.spring-boot-version != '' && format('-Dspring-boot.version={0}', inputs.spring-boot-version) || '' }} \ -Dfailsafe.rerunFailingTestsCount=2 \ verify --- ### .Github/Actions/Release Train Build/Action.Yml (.github/actions/release-train-build/action.yml) name: Build Release runs: using: composite steps: - name: Build Release shell: bash run: ./mvnw --batch-mode -ntp -PreleaseTrain --settings release-train-settings.xml -DaltDeploymentRepository="release-train::file://$(pwd)/deployment-repository" -Dmaven.test.skip deploy --- ### .Github/Actions/Release Train Test/Action.Yml (.github/actions/release-train-test/action.yml) name: Test Release runs: using: composite steps: - name: Test Release shell: bash run: ./mvnw --batch-mode -ntp -PreleaseTrain --settings release-train-settings.xml test --- ### .Github/ISSUE TEMPLATE/Bug Report (.github/ISSUE_TEMPLATE/bug_report.md) --- name: Bug report about: Create a bug report to help us improve the project title: '' labels: 'type: bug, status: waiting-for-triage' assignees: '' --- Please do a quick search on GitHub issues first, there might be already a duplicate issue for the one you are about to create. If the bug is trivial, just go ahead and create the issue. Otherwise, please take a few moments and fill in the following sections: **Bug description** A clear and concise description of what the bug is about. **Environment** Please provide as many details as possible: Spring AI version, Java version, which vector store you use if any, etc **Steps to reproduce** Steps to reproduce the issue. **Expected behavior** A clear and concise description of what you expected to happen. **Minimal Complete Reproducible example** Please provide a failing test or a minimal complete verifiable example that reproduces the issue. Bug reports that are reproducible will take priority in resolution over reports that are not reproducible. --- ### .Github/ISSUE TEMPLATE/Config.Yml (.github/ISSUE_TEMPLATE/config.yml) blank_issues_enabled: false contact_links: - name: Questions and Community Support url: https://stackoverflow.com/questions/tagged/spring-ai about: Please ask and answer questions on StackOverflow with the spring-ai tag --- ### .Github/ISSUE TEMPLATE/Feature Request (.github/ISSUE_TEMPLATE/feature_request.md) --- name: Feature request about: Suggest an idea for this project title: '' labels: 'status: waiting-for-triage, type: feature' assignees: '' --- Please do a quick search on GitHub issues first, the feature you are about to request might have already been requested. **Expected Behavior** **Current Behavior** **Context** --- ### .Github/ISSUE TEMPLATE/Miscellaneous (.github/ISSUE_TEMPLATE/miscellaneous.md) --- name: Miscellaneous about: Suggest an improvement for this project title: '' labels: 'status: waiting-for-triage' assignees: '' --- For anything other than bug reports and feature requests (performance, refactoring, etc), just go ahead and file the issue. Please provide as many details as possible. If you have a question or a support request, please open a new discussion on [GitHub Discussions](https://github.com/spring-projects/spring-ai/discussions) or ask a question on [StackOverflow](https://stackoverflow.com/questions/tagged/spring-ai). Please do **not** create issues on the [Issue Tracker](https://github.com/spring-projects/spring-ai/issues) for questions or support requests. We would like to keep the issue tracker **exclusively** for bug reports and feature requests. --- ### .Github/Workflows/Auto Cherry Pick.Yml (.github/workflows/auto-cherry-pick.yml) name: Auto Cherry-Pick on: push: branches: - main - '*.x' jobs: cherry-pick-commit: uses: spring-io/spring-github-workflows/.github/workflows/spring-cherry-pick.yml@v5 secrets: GH_ACTIONS_REPO_TOKEN: ${{ secrets.GH_ACTIONS_REPO_TOKEN }} --- ### .Github/Workflows/Backport Issue.Yml (.github/workflows/backport-issue.yml) name: Backport Bot on: issues: types: [labeled] pull_request: types: [labeled] push: branches: - '[0-9]+.[0-9]+.x' - 'main' jobs: backport-issue: permissions: contents: read issues: write pull-requests: write runs-on: ubuntu-latest steps: - name: Create Backport Issue uses: spring-io/backport-bot@v0.0.1 with: token: ${{ secrets.GITHUB_TOKEN }} --- ### .Github/Workflows/Build And Deploy Snapshot.Yml (.github/workflows/build-and-deploy-snapshot.yml) name: Build and Deploy Snapshot on: push: branches: - 'main' - '[0-9].[0-9].x' - '[0-9].[0-9].x-internal' schedule: - cron: '30 11 * * 1-5' # 12:30 PM CET / 6:30 AM workflow_dispatch: concurrency: group: ${{ github.workflow_ref }} cancel-in-progress: true jobs: build-all: name: Build all modules if: ${{ github.repository_owner == 'spring-projects' }} runs-on: ${{ vars.COMMERCIAL && vars.UBUNTU_SMALL || 'ubuntu-latest' }} steps: - name: Checkout source code uses: actions/checkout@v6 - name: Set up JDK uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Setup Maven Build-Cache (~/.m2/build-cache) if: ${{ github.event_name != 'schedule' }} uses: actions/cache@v5 with: path: ~/.m2/build-cache # See pr-check.yml for an explanation of the key format key: build-cache-${{ runner.os }}-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }} restore-keys: | build-cache-${{ runner.os }}-${{ hashFiles('**/pom.xml') }}- build-cache-${{ runner.os }}- - name: Build all modules with unit tests env: COMMERCIAL_ARTIFACTORY_USERNAME: "${{ secrets.COMMERCIAL_ARTIFACTORY_USERNAME }}" COMMERCIAL_ARTIFACTORY_PASSWORD: "${{ secrets.COMMERCIAL_ARTIFACTORY_PASSWORD }}" COMMERCIAL_SNAPSHOT_REPO_URL: "${{ vars.COMMERCIAL_SNAPSHOT_REPO_URL }}" COMMERCIAL_RELEASE_REPO_URL: "${{ vars.COMMERCIAL_RELEASE_REPO_URL }}" run: | ./mvnw ${{ vars.COMMERCIAL && '-s commercial-settings.xml -Pcommercial' || '' }} --batch-mode -ntp --update-snapshots clean install - name: Upload Spring-AI Built Artifacts uses: actions/upload-artifact@v6 with: name: build-artifacts path: ~/.m2/repository/org/springframework/ai retention-days: 1 # Intent is to share only with downstream jobs in this workflow - name: Purge Spring AI Built Artifacts # We don't want the setup-java m2 cache to capture our products, only our deps run: rm -fr ~/.m2/repository/org/springframework/ai test-ollama: name: Test Ollama if: ${{ github.repository_owner == 'spring-projects' }} runs-on: ${{ vars.COMMERCIAL && vars.UBUNTU_SMALL || 'ubuntu-latest' }} needs: build-all services: ollama: image: ollama/ollama:latest ports: - 11434:11434 env: OLLAMA_WITH_REUSE: true OLLAMA_AUTOCONF_TESTS_ENABLED: "true" steps: - name: Checkout source code uses: actions/checkout@v6 - name: Set up JDK uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Setup Maven Build-Cache (~/.m2/build-cache) uses: actions/cache@v5 if: ${{ github.event_name != 'schedule' }} with: path: ~/.m2/build-cache key: build-cache-${{ runner.os }}-ollama-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }} restore-keys: | build-cache-${{ runner.os }}-ollama-${{ hashFiles('**/pom.xml') }}- build-cache-${{ runner.os }}- - name: Download Spring-AI Built Artifacts uses: actions/download-artifact@v7 with: name: build-artifacts path: ~/.m2/repository/org/springframework/ai - name: Configure Testcontainers run: echo "testcontainers.reuse.enable=true" > $HOME/.testcontainers.properties - name: Test Ollama modules env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} COMMERCIAL_ARTIFACTORY_USERNAME: "${{ secrets.COMMERCIAL_ARTIFACTORY_USERNAME }}" COMMERCIAL_ARTIFACTORY_PASSWORD: "${{ secrets.COMMERCIAL_ARTIFACTORY_PASSWORD }}" COMMERCIAL_SNAPSHOT_REPO_URL: "${{ vars.COMMERCIAL_SNAPSHOT_REPO_URL }}" COMMERCIAL_RELEASE_REPO_URL: "${{ vars.COMMERCIAL_RELEASE_REPO_URL }}" run: | ./mvnw ${{ vars.COMMERCIAL && '-s commercial-settings.xml -Pcommercial' || '' }} --batch-mode -ntp --no-snapshot-updates \ -pl models/spring-ai-ollama,auto-configurations/models/spring-ai-autoconfigure-model-ollama \ -Pci-fast-integration-tests \ -Dfailsafe.rerunFailingTestsCount=3 \ verify test-openai: name: Test OpenAI if: ${{ github.repository_owner == 'spring-projects' }} runs-on: ${{ vars.COMMERCIAL && vars.UBUNTU_SMALL || 'ubuntu-latest' }} needs: build-all steps: - name: Checkout source code uses: actions/checkout@v6 - name: Set up JDK uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Setup Maven Build-Cache (~/.m2/build-cache) uses: actions/cache@v5 with: path: ~/.m2/build-cache key: build-cache-${{ runner.os }}-openai-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }} restore-keys: | build-cache-${{ runner.os }}-openai-${{ hashFiles('**/pom.xml') }}- build-cache-${{ runner.os }}- - name: Download Spring-AI Built Artifacts uses: actions/download-artifact@v7 with: name: build-artifacts path: ~/.m2/repository/org/springframework/ai - name: Configure Testcontainers run: echo "testcontainers.reuse.enable=true" > $HOME/.testcontainers.properties - name: Test OpenAI modules env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} COMMERCIAL_ARTIFACTORY_USERNAME: "${{ secrets.COMMERCIAL_ARTIFACTORY_USERNAME }}" COMMERCIAL_ARTIFACTORY_PASSWORD: "${{ secrets.COMMERCIAL_ARTIFACTORY_PASSWORD }}" COMMERCIAL_SNAPSHOT_REPO_URL: "${{ vars.COMMERCIAL_SNAPSHOT_REPO_URL }}" COMMERCIAL_RELEASE_REPO_URL: "${{ vars.COMMERCIAL_RELEASE_REPO_URL }}" run: | ./mvnw ${{ vars.COMMERCIAL && '-s commercial-settings.xml -Pcommercial' || '' }} --batch-mode -ntp --no-snapshot-updates \ -pl models/spring-ai-openai,auto-configurations/models/spring-ai-autoconfigure-model-openai \ -Pci-fast-integration-tests \ -Dfailsafe.rerunFailingTestsCount=3 \ verify test-remaining: name: Test Remaining (MCP, Google GenAI, Vertex AI Embedding, Chroma, PgVector) if: ${{ github.repository_owner == 'spring-projects' }} runs-on: ${{ vars.COMMERCIAL && vars.UBUNTU_SMALL || 'ubuntu-latest' }} needs: build-all steps: - name: Checkout source code uses: actions/checkout@v6 - name: Set up JDK uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Setup Maven Build-Cache (~/.m2/build-cache) uses: actions/cache@v5 with: path: ~/.m2/build-cache key: build-cache-${{ runner.os }}-other-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }} restore-keys: | build-cache-${{ runner.os }}-other-${{ hashFiles('**/pom.xml') }}- build-cache-${{ runner.os }}- - name: Download Spring-AI Built Artifacts uses: actions/download-artifact@v7 with: name: build-artifacts path: ~/.m2/repository/org/springframework/ai - name: Configure Testcontainers run: echo "testcontainers.reuse.enable=true" > $HOME/.testcontainers.properties - name: Test remaining modules env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} COMMERCIAL_ARTIFACTORY_USERNAME: "${{ secrets.COMMERCIAL_ARTIFACTORY_USERNAME }}" COMMERCIAL_ARTIFACTORY_PASSWORD: "${{ secrets.COMMERCIAL_ARTIFACTORY_PASSWORD }}" COMMERCIAL_SNAPSHOT_REPO_URL: "${{ vars.COMMERCIAL_SNAPSHOT_REPO_URL }}" COMMERCIAL_RELEASE_REPO_URL: "${{ vars.COMMERCIAL_RELEASE_REPO_URL }}" run: | ./mvnw ${{ vars.COMMERCIAL && '-s commercial-settings.xml -Pcommercial' || '' }} --batch-mode -ntp --no-snapshot-updates \ -pl models/spring-ai-google-genai, \ -pl auto-configurations/models/spring-ai-autoconfigure-model-google-genai, \ ${{ vars.COMMERCIAL && '-pl models/spring-ai-vertex-ai-embedding,' || '-pl mcp/mcp-annotations,' }} \ -pl mcp/common, \ -pl mcp/transport/mcp-spring-webflux, \ -pl mcp/transport/mcp-spring-webmvc, \ -pl auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-common, \ -pl auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-httpclient, \ -pl auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-webflux, \ -pl auto-configurations/mcp/spring-ai-autoconfigure-mcp-server-common, \ -pl auto-configurations/mcp/spring-ai-autoconfigure-mcp-server-webmvc, \ -pl auto-configurations/mcp/spring-ai-autoconfigure-mcp-server-webflux, \ -pl vector-stores/spring-ai-chroma-store, \ -pl vector-stores/spring-ai-pgvector-store, \ -pl spring-ai-integration-tests \ -Pci-fast-integration-tests \ -Dfailsafe.rerunFailingTestsCount=3 \ verify deploy-artifactory: name: Deploy to Artifactory if: ${{ github.repository_owner == 'spring-projects' && github.event_name != 'schedule' }} runs-on: ${{ vars.COMMERCIAL && vars.UBUNTU_SMALL || 'ubuntu-latest' }} needs: [build-all, test-ollama, test-openai, test-remaining] steps: - name: Checkout source code uses: actions/checkout@v6 - name: Set up JDK uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Setup Maven Build-Cache (~/.m2/build-cache) uses: actions/cache@v5 with: path: ~/.m2/build-cache key: build-cache-${{ runner.os }}-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }} restore-keys: | build-cache-${{ runner.os }}-${{ hashFiles('**/pom.xml') }}- build-cache-${{ runner.os }}- - name: Deploy to Artifactory env: ARTIFACTORY_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }} ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }} COMMERCIAL_ARTIFACTORY_USERNAME: "${{ secrets.COMMERCIAL_ARTIFACTORY_USERNAME }}" COMMERCIAL_ARTIFACTORY_PASSWORD: "${{ secrets.COMMERCIAL_ARTIFACTORY_PASSWORD }}" COMMERCIAL_SNAPSHOT_REPO_URL: "${{ vars.COMMERCIAL_SNAPSHOT_REPO_URL }}" COMMERCIAL_RELEASE_REPO_URL: "${{ vars.COMMERCIAL_RELEASE_REPO_URL }}" run: | ./mvnw ${{ vars.COMMERCIAL && '-s commercial-settings.xml -Pcommercial' || '-s settings.xml' }} --batch-mode -ntp -Dmaven.test.skip \ ${{ vars.COMMERCIAL && format('-DaltSnapshotDeploymentRepository=spring-enterprise-snapshot::{0}', vars.COMMERCIAL_SNAPSHOT_REPO_URL) || '' }} \ deploy --- ### .Github/Workflows/Dependency Ci Dashboard.Yml (.github/workflows/dependency-ci-dashboard.yml) name: Ecosystem CI Dashboard on: schedule: - cron: '15 6 * * *' # 06:15 UTC daily workflow_dispatch: permissions: issues: write contents: write jobs: update-dashboard: name: Update Ecosystem CI Dashboard runs-on: ubuntu-latest if: ${{ github.repository == 'spring-projects/spring-ai' }} steps: - name: Checkout source code uses: actions/checkout@v6 - name: Load configuration id: config run: | CONFIG=$(cat src/ecosystem-ci/ci-alert-config.json) echo "issue_number=$(echo "$CONFIG" | jq -r '.issue_number')" >> $GITHUB_OUTPUT echo "tracked_branch=$(echo "$CONFIG" | jq -r '.tracked_branch')" >> $GITHUB_OUTPUT echo "alert_after_days=$(echo "$CONFIG" | jq -r '.alert_after_days')" >> $GITHUB_OUTPUT echo "heartbeat_days=$(echo "$CONFIG" | jq -r '.heartbeat_days')" >> $GITHUB_OUTPUT echo "dependencies<> $GITHUB_OUTPUT echo "$CONFIG" | jq -c '.dependencies' >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT - name: Query CI status for all dependencies id: query-status env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} DEPENDENCIES: ${{ steps.config.outputs.dependencies }} TRACKED_BRANCH: ${{ steps.config.outputs.tracked_branch }} run: | RESULTS="[]" for row in $(echo "$DEPENDENCIES" | jq -r '.[] | @base64'); do _jq() { echo ${row} | base64 --decode | jq -r ${1} } OWNER=$(_jq '.owner') REPO=$(_jq '.repo') echo "Querying status for $OWNER/$REPO..." # Query workflow runs for the branch (most reliable for GitHub Actions) RUNS_RESPONSE=$(curl -s -H "Authorization: token $GH_TOKEN" \ -H "Accept: application/vnd.github+json" \ "https://api.github.com/repos/$OWNER/$REPO/actions/runs?branch=$TRACKED_BRANCH&per_page=10") # Find the most recent completed workflow run LATEST_RUN=$(echo "$RUNS_RESPONSE" | jq '[.workflow_runs[] | select(.status == "completed")] | .[0]') if [ "$LATEST_RUN" != "null" ] && [ -n "$LATEST_RUN" ]; then CONCLUSION=$(echo "$LATEST_RUN" | jq -r '.conclusion // "unknown"') COMMIT_SHA=$(echo "$LATEST_RUN" | jq -r '.head_sha // "unknown"' | head -c 7) COMMIT_DATE=$(echo "$LATEST_RUN" | jq -r '.created_at // ""') # Map conclusion to state case "$CONCLUSION" in "success") STATE="success" ;; "failure"|"timed_out"|"cancelled") STATE="failure" ;; *) STATE="unknown" ;; esac else # Check if there are any in-progress runs IN_PROGRESS=$(echo "$RUNS_RESPONSE" | jq '[.workflow_runs[] | select(.status == "in_progress" or .status == "queued")] | length') if [ "$IN_PROGRESS" -gt 0 ]; then STATE="pending" # Get commit from in-progress run COMMIT_SHA=$(echo "$RUNS_RESPONSE" | jq -r '.workflow_runs[0].head_sha // "unknown"' | head -c 7) COMMIT_DATE=$(echo "$RUNS_RESPONSE" | jq -r '.workflow_runs[0].created_at // ""') else STATE="unknown" # Fall back to HEAD commit info COMMIT_RESPONSE=$(curl -s -H "Authorization: token $GH_TOKEN" \ -H "Accept: application/vnd.github+json" \ "https://api.github.com/repos/$OWNER/$REPO/commits/$TRACKED_BRANCH") COMMIT_SHA=$(echo "$COMMIT_RESPONSE" | jq -r '.sha // "unknown"' | head -c 7) COMMIT_DATE=$(echo "$COMMIT_RESPONSE" | jq -r '.commit.committer.date // ""') fi fi RESULT=$(jq -n \ --arg owner "$OWNER" \ --arg repo "$REPO" \ --arg state "$STATE" \ --arg sha "$COMMIT_SHA" \ --arg date "$COMMIT_DATE" \ '{owner: $owner, repo: $repo, state: $state, sha: $sha, commit_date: $date}') RESULTS=$(echo "$RESULTS" | jq --argjson result "$RESULT" '. + [$result]') done echo "results<> $GITHUB_OUTPUT echo "$RESULTS" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT - name: Update dashboard and check alerts uses: actions/github-script@v7 env: RESULTS: ${{ steps.query-status.outputs.results }} ISSUE_NUMBER: ${{ steps.config.outputs.issue_number }} ALERT_AFTER_DAYS: ${{ steps.config.outputs.alert_after_days }} HEARTBEAT_DAYS: ${{ steps.config.outputs.heartbeat_days }} TRACKED_BRANCH: ${{ steps.config.outputs.tracked_branch }} with: script: | const results = JSON.parse(process.env.RESULTS); const issueNumber = parseInt(process.env.ISSUE_NUMBER); const alertAfterDays = parseInt(process.env.ALERT_AFTER_DAYS); const heartbeatDays = parseInt(process.env.HEARTBEAT_DAYS); const trackedBranch = process.env.TRACKED_BRANCH; const now = new Date(); const timestamp = now.toISOString(); // Status emoji mapping const statusEmoji = { 'success': ':white_check_mark:', 'failure': ':x:', 'pending': ':yellow_circle:', 'unknown': ':grey_question:' }; // Find dashboard comment (contains hidden state marker) const STATE_MARKER = ''; const comments = await github.paginate(github.rest.issues.listComments, { owner: context.repo.owner, repo: context.repo.repo, issue_number: issueNumber }); let dashboardComment = comments.find(c => c.body.includes(DASHBOARD_MARKER)); // Parse previous state from comment let previousState = {}; if (dashboardComment) { const stateMatch = dashboardComment.body.match(//s); if (stateMatch) { try { previousState = JSON.parse(stateMatch[1]); } catch (e) { console.log('Failed to parse previous state:', e); } } } // Update state with current results const newState = {}; const alertsNeeded = []; for (const result of results) { const key = `${result.owner}/${result.repo}`; const prevEntry = previousState[key] || {}; if (result.state === 'failure') { // Track when it first failed const failedSince = prevEntry.failedSince || timestamp; const failedDays = Math.floor((now - new Date(failedSince)) / (1000 * 60 * 60 * 24)); const lastAlerted = prevEntry.lastAlerted; newState[key] = { state: result.state, failedSince: failedSince, failedDays: failedDays, lastAlerted: lastAlerted }; // Check if we need to alert if (failedDays >= alertAfterDays) { // Only alert if we haven't alerted in the last heartbeat period const shouldAlert = !lastAlerted || (now - new Date(lastAlerted)) >= (heartbeatDays * 24 * 60 * 60 * 1000); if (shouldAlert) { alertsNeeded.push({ owner: result.owner, repo: result.repo, failedDays: failedDays, sha: result.sha }); newState[key].lastAlerted = timestamp; } } } else { // Not failing - clear failure tracking newState[key] = { state: result.state }; } } // Build dashboard table let dashboardTable = `| Repository | Status | Branch | Latest Commit | Last Run |\n`; dashboardTable += `|------------|--------|--------|---------------|----------|\n`; for (const result of results) { const key = `${result.owner}/${result.repo}`; const emoji = statusEmoji[result.state] || statusEmoji['unknown']; const stateEntry = newState[key]; let statusText = emoji; if (result.state === 'failure' && stateEntry.failedDays > 0) { statusText += ` (${stateEntry.failedDays}d)`; } const repoLink = `[${result.owner}/${result.repo}](https://github.com/${result.owner}/${result.repo})`; const commitLink = result.sha !== 'unknown' ? `[\`${result.sha}\`](https://github.com/${result.owner}/${result.repo}/commit/${result.sha})` : 'N/A'; const actionsLink = `[${trackedBranch}](https://github.com/${result.owner}/${result.repo}/actions?query=branch%3A${trackedBranch})`; // Format date as YYYY-MM-DD const lastRun = result.commit_date ? new Date(result.commit_date).toISOString().split('T')[0] : 'N/A'; dashboardTable += `| ${repoLink} | ${statusText} | ${actionsLink} | ${commitLink} | ${lastRun} |\n`; } // Build dashboard comment body const stateJson = JSON.stringify(newState); const dashboardBody = `${DASHBOARD_MARKER} ## Ecosystem CI Dashboard **Last updated:** ${timestamp} ${dashboardTable} ### Legend - :white_check_mark: All checks passing - :x: CI failing (days in parentheses) - :yellow_circle: Checks in progress - :grey_question: Status unknown ### Alert Policy - Alerts are posted when a dependency has been failing for **${alertAfterDays}+ days** - Subscribe to this issue to receive CI failure notifications ${STATE_MARKER}${stateJson}--> `.split('\n').map(line => line.trim()).join('\n'); // Update or create dashboard comment if (dashboardComment) { await github.rest.issues.updateComment({ owner: context.repo.owner, repo: context.repo.repo, comment_id: dashboardComment.id, body: dashboardBody }); console.log('Updated dashboard comment'); } else { await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: issueNumber, body: dashboardBody }); console.log('Created dashboard comment'); } // Post alert comments if needed for (const alert of alertsNeeded) { const alertBody = `:rotating_light: **CI Alert**: [${alert.owner}/${alert.repo}](https://github.com/${alert.owner}/${alert.repo}) has been failing for **${alert.failedDays} days** - **Branch:** ${trackedBranch} - **Latest commit:** [\`${alert.sha}\`](https://github.com/${alert.owner}/${alert.repo}/commit/${alert.sha}) - **CI Status:** [View Actions](https://github.com/${alert.owner}/${alert.repo}/actions?query=branch%3A${trackedBranch}) Please investigate and fix the CI failure.`; await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: issueNumber, body: alertBody }); console.log(`Posted alert for ${alert.owner}/${alert.repo}`); } // Set outputs for wiki update core.setOutput('dashboard_table', dashboardTable); core.setOutput('timestamp', timestamp); core.setOutput('alert_after_days', alertAfterDays); - name: Update Wiki Dashboard env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} RESULTS: ${{ steps.query-status.outputs.results }} TRACKED_BRANCH: ${{ steps.config.outputs.tracked_branch }} ALERT_AFTER_DAYS: ${{ steps.config.outputs.alert_after_days }} run: | # Configure git git config --global user.name "github-actions[bot]" git config --global user.email "github-actions[bot]@users.noreply.github.com" # Clone wiki repo WIKI_DIR=$(mktemp -d) git clone "https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.wiki.git" "$WIKI_DIR" # Generate wiki page content TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ") # Status emoji mapping for wiki (GitHub wiki renders these) cat > "$WIKI_DIR/Ecosystem-CI-Dashboard.md" << 'WIKI_HEADER' # Ecosystem CI Dashboard This dashboard monitors the CI health of Spring AI ecosystem dependencies. WIKI_HEADER echo "**Last updated:** $TIMESTAMP" >> "$WIKI_DIR/Ecosystem-CI-Dashboard.md" echo "" >> "$WIKI_DIR/Ecosystem-CI-Dashboard.md" # Build table echo "| Repository | Status | Branch | Latest Commit | Last Run |" >> "$WIKI_DIR/Ecosystem-CI-Dashboard.md" echo "|------------|--------|--------|---------------|----------|" >> "$WIKI_DIR/Ecosystem-CI-Dashboard.md" echo "$RESULTS" | jq -r '.[] | @base64' | while read row; do OWNER=$(echo "$row" | base64 --decode | jq -r '.owner') REPO=$(echo "$row" | base64 --decode | jq -r '.repo') STATE=$(echo "$row" | base64 --decode | jq -r '.state') SHA=$(echo "$row" | base64 --decode | jq -r '.sha') COMMIT_DATE=$(echo "$row" | base64 --decode | jq -r '.commit_date') case "$STATE" in "success") EMOJI=":white_check_mark:" ;; "failure") EMOJI=":x:" ;; "pending") EMOJI=":yellow_circle:" ;; *) EMOJI=":grey_question:" ;; esac REPO_LINK="[$OWNER/$REPO](https://github.com/$OWNER/$REPO)" COMMIT_LINK="[\`$SHA\`](https://github.com/$OWNER/$REPO/commit/$SHA)" ACTIONS_LINK="[$TRACKED_BRANCH](https://github.com/$OWNER/$REPO/actions?query=branch%3A$TRACKED_BRANCH)" # Format date as YYYY-MM-DD if [ -n "$COMMIT_DATE" ] && [ "$COMMIT_DATE" != "null" ]; then LAST_RUN=$(echo "$COMMIT_DATE" | cut -d'T' -f1) else LAST_RUN="N/A" fi echo "| $REPO_LINK | $EMOJI | $ACTIONS_LINK | $COMMIT_LINK | $LAST_RUN |" >> "$WIKI_DIR/Ecosystem-CI-Dashboard.md" done cat >> "$WIKI_DIR/Ecosystem-CI-Dashboard.md" << WIKI_FOOTER ## Legend - :white_check_mark: All checks passing - :x: CI failing - :yellow_circle: Checks in progress - :grey_question: Status unknown ## Alert Policy Alerts are posted to [Issue #${{ steps.config.outputs.issue_number }}](https://github.com/${{ github.repository }}/issues/${{ steps.config.outputs.issue_number }}) when a dependency has been failing for **${ALERT_AFTER_DAYS}+ days**. Subscribe to that issue to receive CI failure notifications. ## Monitored Repositories The following repositories are monitored as part of the Spring AI ecosystem: WIKI_FOOTER echo "$RESULTS" | jq -r '.[] | "- [`\(.owner)/\(.repo)`](https://github.com/\(.owner)/\(.repo))"' >> "$WIKI_DIR/Ecosystem-CI-Dashboard.md" cat >> "$WIKI_DIR/Ecosystem-CI-Dashboard.md" << 'WIKI_END' --- *This page is automatically updated by the [Ecosystem CI Dashboard workflow](https://github.com/spring-projects/spring-ai/actions/workflows/dependency-ci-dashboard.yml).* WIKI_END # Commit and push wiki changes cd "$WIKI_DIR" git add Ecosystem-CI-Dashboard.md if git diff --staged --quiet; then echo "No changes to wiki" else git commit -m "Update Ecosystem CI Dashboard - $TIMESTAMP" git push echo "Wiki updated successfully" fi --- ### .Github/Workflows/Deploy Docs.Yml (.github/workflows/deploy-docs.yml) name: Deploy Docs run-name: ${{ github.event_name == 'workflow_dispatch' && 'Deploy Docs (Build)' || 'Deploy Docs (Dispatcher)' }} on: workflow_dispatch: permissions: actions: write jobs: build: runs-on: ${{ vars.COMMERCIAL && vars.UBUNTU_SMALL || 'ubuntu-latest' }} if: ${{ github.repository_owner == 'spring-projects' }} steps: - name: Dispatch (full build) env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: gh workflow run deploy-docs.yml -r docs-build --repo ${{ github.repository }} --- ### .Github/Workflows/Deploy Javadoc.Yml (.github/workflows/deploy-javadoc.yml) name: Deploy Javadoc on: push: tags: - 'v*' workflow_dispatch: permissions: contents: read jobs: deploy-javadoc: name: Deploy Javadoc if: ${{ github.repository_owner == 'spring-projects' }} runs-on: ${{ vars.COMMERCIAL && vars.UBUNTU_SMALL || 'ubuntu-latest' }} steps: - name: Check Out uses: actions/checkout@v4 - name: Set Up Java uses: actions/setup-java@v4 with: java-version: '17' distribution: 'liberica' - name: Generate Javadoc (commercial) if: ${{ vars.COMMERCIAL }} shell: bash env: COMMERCIAL_RELEASE_REPO_URL: ${{ vars.COMMERCIAL_RELEASE_REPO_URL }} COMMERCIAL_ARTIFACTORY_PASSWORD: ${{ secrets.COMMERCIAL_ARTIFACTORY_PASSWORD }} COMMERCIAL_ARTIFACTORY_USERNAME: ${{ secrets.COMMERCIAL_ARTIFACTORY_USERNAME }} COMMERCIAL_SNAPSHOT_REPO_URL: ${{ vars.COMMERCIAL_SNAPSHOT_REPO_URL }} USW1_USERNAME: ${{ secrets.COMMERCIAL_ARTIFACTORY_RO_USERNAME }} USW1_PASSWORD: ${{ secrets.COMMERCIAL_ARTIFACTORY_RO_PASSWORD }} run: ./mvnw -s commercial-settings.xml --batch-mode -ntp javadoc:aggregate-jar - name: Generate Javadoc (OSS) if: ${{ !vars.COMMERCIAL }} run: ./mvnw --batch-mode -ntp javadoc:aggregate-jar - name: Capture project version run: echo PROJECT_VERSION=$(./mvnw ${{ vars.COMMERCIAL && '-s commercial-settings.xml' || '' }} help:evaluate -Dexpression=project.version --quiet -DforceStdout) >> $GITHUB_ENV - name: Extract Javadoc if: ${{ vars.COMMERCIAL }} run: | mkdir -p target/javadoc-site/${PROJECT_VERSION}/api unzip target/spring-ai-parent-${PROJECT_VERSION}-javadoc.jar -d target/javadoc-site/${PROJECT_VERSION}/api - name: Authenticate to GCP if: ${{ vars.COMMERCIAL }} uses: google-github-actions/auth@v2.1.0 with: credentials_json: ${{ secrets.COMMERCIAL_DOCS_GCP_BUCKET_JSON }} - name: Upload Javadoc to GCP (commercial) if: ${{ vars.COMMERCIAL }} uses: google-github-actions/upload-cloud-storage@v2.1.0 with: path: target/javadoc-site destination: ${{ secrets.COMMERCIAL_DOCS_HOST }}/spring-ai/docs/ parent: false - name: Setup SSH key (OSS) if: ${{ !vars.COMMERCIAL }} run: | mkdir "$HOME/.ssh" echo "${{ secrets.DOCS_SSH_KEY }}" > "$HOME/.ssh/key" chmod 600 "$HOME/.ssh/key" echo "${{ secrets.DOCS_SSH_HOST_KEY }}" > "$HOME/.ssh/known_hosts" - name: Deploy Javadoc via SSH (OSS) if: ${{ !vars.COMMERCIAL }} run: | ssh -i $HOME/.ssh/key ${{ secrets.DOCS_USERNAME }}@${{ secrets.DOCS_HOST }} "cd ${{ secrets.DOCS_PATH }} && rm -fr $PROJECT_VERSION && mkdir -p $PROJECT_VERSION" scp -i $HOME/.ssh/key target/spring-ai-parent-${PROJECT_VERSION}-javadoc.jar ${{ secrets.DOCS_USERNAME }}@${{ secrets.DOCS_HOST }}:${{ secrets.DOCS_PATH }}/$PROJECT_VERSION ssh -i $HOME/.ssh/key ${{ secrets.DOCS_USERNAME }}@${{ secrets.DOCS_HOST }} "cd ${{ secrets.DOCS_PATH }}/${PROJECT_VERSION} && unzip spring-ai-parent-${PROJECT_VERSION}-javadoc.jar -d api && rm spring-ai-parent-${PROJECT_VERSION}-javadoc.jar" --- ### .Github/Workflows/Github Release.Yml (.github/workflows/github-release.yml) name: GitHub Release run-name: "GitHub Release (${{ inputs.version }})" on: workflow_dispatch: inputs: version: description: "Enter the release version (e.g., 1.2.3)." required: true latest: description: "Whether to mark the release as the latest one." type: boolean required: false default: false draft: description: "Whether to create the release as a draft." type: boolean required: false default: false permissions: contents: read concurrency: group: ${{ github.workflow }}-${{ inputs.version }} jobs: create-github-release: name: Create GitHub Release runs-on: ubuntu-latest steps: - name: Check Out Code uses: actions/checkout@v6 - name: Create GitHub Release uses: ./.github/actions/create-github-release with: commercial: ${{ vars.COMMERCIAL }} draft: ${{ inputs.draft }} latest: ${{ inputs.latest }} milestone: ${{ inputs.version }} pre-release: ${{ contains(inputs.version, '-') }} token: ${{ secrets.GH_ACTIONS_REPO_TOKEN }} --- ### .Github/Workflows/Mcp Integration Tests.Yml (.github/workflows/mcp-integration-tests.yml) name: MCP Integration Tests on: pull_request: push: branches: - 'main' - '[0-9].[0-9].x' workflow_dispatch: inputs: runner: description: 'Runner label to use (e.g. UBUNTU_SMALL, ubuntu-latest). Leave empty to use the default.' required: false default: '' type: string jobs: mcp-it: name: MCP integration tests runs-on: ${{ inputs.runner != '' && inputs.runner || (vars.COMMERCIAL && vars.UBUNTU_SMALL || 'ubuntu-latest') }} steps: - name: Checkout source code uses: actions/checkout@v6 - name: Set up JDK uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Setup Maven Build-Cache (~/.m2/build-cache) if: ${{ false }} # Disable until test flakiness has been resolved uses: actions/cache@v4 with: path: ~/.m2/build-cache # See pr-check.yml for an explanation of the key format key: build-cache-${{ runner.os }}-mcp-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }} restore-keys: | build-cache-${{ runner.os }}-mcp-${{ hashFiles('**/pom.xml') }}- build-cache-${{ runner.os }}- - name: Build with Maven and run integration tests run: | ./mvnw --batch-mode -ntp verify -Pintegration-tests -am -pl "mcp/transport/mcp-spring-webflux,mcp/transport/mcp-spring-webmvc" --- ### .Github/Workflows/Pr Check.Yml (.github/workflows/pr-check.yml) name: PR Check on: pull_request: jobs: build: name: Build branch runs-on: ubuntu-latest if: ${{ github.repository_owner == 'spring-projects' }} steps: - name: Checkout source code uses: actions/checkout@v6 - name: Set up JDK uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Setup Maven Build-Cache (~/.m2/build-cache) uses: actions/cache@v5 with: path: ~/.m2/build-cache # See https://github.com/actions/cache/blob/main/tips-and-workarounds.md#update-a-cache # We need to incrementally save the contents of the build-cache directory, even if there was a hit prior to the build # Cached restored from restore-keys are restored using the latest one first, so this is a good compromise key: build-cache-${{ runner.os }}-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }} restore-keys: | build-cache-${{ runner.os }}-${{ hashFiles('**/pom.xml') }}- build-cache-${{ runner.os }}- - name: Run tests run: | ./mvnw -ntp -B -U package --- ### .Github/Workflows/Release Train Build.Yml (.github/workflows/release-train-build.yml) # This file was auto-generated by github-actions-workflow-generator 0.0.6. Do not edit. # To update it, modify .github/workflow-generator.yml as needed and re-run the generator. name: "Release Train – Build" run-name: "${{ inputs.callback-ref }} – Build" "on": workflow_dispatch: inputs: callback: description: "Repository to which a callback should be made upon completion" required: true type: "string" callback-ref: description: "Ref in the callback repository to which a callback should be made upon completion" required: true type: "string" release-train-maven-repository-url: description: "URL of a Maven repository to be used to resolve artifacts of projects earlier in the train" required: true type: "string" permissions: contents: "read" concurrency: group: "${{ github.workflow }}-${{ github.ref }}" jobs: build-release: name: "Build Release" runs-on: ${{ vars.UBUNTU_SMALL || 'ubuntu-latest' }} steps: - name: "Prevent Re-runs" id: "prevent-re-runs" run: |- if [ "$GITHUB_RUN_ATTEMPT" -gt 1 ]; then echo "Re-runs are prohibited. Use the 'Release Train – Retry' workflow to retry build failures" exit 1 fi - name: "Set up Java" id: "set-up-java" uses: "actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95" # v5.6.0 with: distribution: "liberica" java-version: "17" - name: "Check Out Code" id: "check-out-code" uses: "actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0" # v7.0.0 - name: "Build Release" id: "build-release" uses: "./.github/actions/release-train-build" env: COMMERCIAL_ARTIFACTORY_PASSWORD: "${{ secrets.COMMERCIAL_ARTIFACTORY_PASSWORD }}" COMMERCIAL_ARTIFACTORY_USERNAME: "${{ secrets.COMMERCIAL_ARTIFACTORY_USERNAME }}" COMMERCIAL_RELEASE_REPO_URL: "${{ vars.COMMERCIAL_RELEASE_REPO_URL }}" RELEASE_TRAIN_MAVEN_REPOSITORY_PASSWORD: "${{ secrets.RELEASE_TRAIN_PARTICIPANT_MAVEN_REPOSITORY_PASSWORD }}" RELEASE_TRAIN_MAVEN_REPOSITORY_URL: "${{ inputs.release-train-maven-repository-url }}" RELEASE_TRAIN_MAVEN_REPOSITORY_USERNAME: "${{ secrets.RELEASE_TRAIN_PARTICIPANT_MAVEN_REPOSITORY_USERNAME }}" - name: "Upload Deployment Repository" id: "upload-deployment-repository" uses: "actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a" # v7.0.1 with: name: "deployment-repository" path: "deployment-repository/**" - name: "Upload Deployment Spec" id: "upload-deployment-spec" uses: "actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a" # v7.0.1 with: archive: "false" if-no-files-found: "ignore" name: "deployment-spec" path: ".github/actions/release-train-build/deployment-spec.yml" - name: "Save Build System Caches" id: "save-build-system-caches" uses: "actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9" # v6.1.0 with: key: "release-train-${{ inputs.callback-ref }}-${{ github.ref_name }}" path: "~/.m2/repository" - name: "Send Callback" id: "send-callback" if: "${{ !cancelled() }}" env: GH_TOKEN: "${{ secrets.RELEASE_TRAIN_PARTICIPANT_GITHUB_TOKEN }}" run: |- gh workflow run callback \ --repo ${{ inputs.callback }} \ --ref ${{ inputs.callback-ref }} \ --field commit-hash=${{ steps.check-out-code.outputs.commit }} \ --field deployment-repository-artifact-identifier=${{ steps.upload-deployment-repository.outputs.artifact-id }} \ --field deployment-spec-artifact-identifier=${{ steps.upload-deployment-spec.outputs.artifact-id }} \ --field release-branch=${{ github.ref_name }} \ --field release-repository=${{ github.repository }} \ --field result=${{ job.status == 'success' && 'built' || 'build-failed' }} \ --field workflow-run-url=${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} --- ### .Github/Workflows/Release Train Join.Yml (.github/workflows/release-train-join.yml) # This file was auto-generated by github-actions-workflow-generator 0.0.6. Do not edit. # To update it, modify .github/workflow-generator.yml as needed and re-run the generator. name: "Release Train – Join" run-name: "${{ inputs.release-train }} – Join" "on": workflow_dispatch: inputs: deployment-destination: description: "Destination to which the release should be deployed" options: - "Maven Central" - "Spring Enterprise" required: true type: "choice" release-train: description: "Release train" required: true type: "string" release-train-repository: default: "spring-io/release-train" description: "Release train repository" required: true type: "string" permissions: contents: "none" jobs: join-release-train: name: "Join Release Train" runs-on: "ubuntu-latest" steps: - name: "Join Release Train" id: "join-release-train" env: GH_TOKEN: "${{ secrets.RELEASE_TRAIN_PARTICIPANT_GITHUB_TOKEN }}" run: |- run_url=$( gh workflow run join \ --repo ${{ inputs.release-train-repository }} \ --ref ${{ inputs.release-train }} \ --field commit-hash=${{ github.sha }} \ --field deployment-destination=${{ inputs.deployment-destination == 'Maven Central' && 'maven-central' || 'spring-enterprise' }} \ --field release-branch=${{ github.ref_name }} \ --field release-repository=${{ github.repository }} ) echo "Dispatched workflow run. Waiting for $run_url to complete." run_id=${run_url##*/} watch_exit_code=0 gh run watch $run_id --repo ${{ inputs.release-train-repository }} --exit-status --interval=3 > /dev/null 2>&1 || watch_exit_code=$? if [[ $watch_exit_code -eq 0 ]]; then echo "Workflow run succeeded." else echo "Workflow run failed." fi exit $watch_exit_code --- ### .Github/Workflows/Release Train Leave.Yml (.github/workflows/release-train-leave.yml) # This file was auto-generated by github-actions-workflow-generator 0.0.6. Do not edit. # To update it, modify .github/workflow-generator.yml as needed and re-run the generator. name: "Release Train – Leave" run-name: "${{ inputs.release-train }} – Leave" "on": workflow_dispatch: inputs: release-train: description: "Release train" required: true type: "string" release-train-repository: default: "spring-io/release-train" description: "Release train repository" required: true type: "string" permissions: contents: "none" jobs: leave: name: "Leave" runs-on: "ubuntu-latest" steps: - name: "Leave" id: "leave" env: GH_TOKEN: "${{ secrets.RELEASE_TRAIN_PARTICIPANT_GITHUB_TOKEN }}" run: |- run_url=$( gh workflow run leave \ --repo ${{ inputs.release-train-repository }} \ --ref ${{ inputs.release-train }} \ --field release-branch=${{ github.ref_name }} \ --field release-repository=${{ github.repository }} ) echo "Dispatched workflow run. Waiting for $run_url to complete." run_id=${run_url##*/} watch_exit_code=0 gh run watch $run_id --repo ${{ inputs.release-train-repository }} --exit-status --interval=3 > /dev/null 2>&1 || watch_exit_code=$? if [[ $watch_exit_code -eq 0 ]]; then echo "Workflow run succeeded." else echo "Workflow run failed." fi exit $watch_exit_code --- ### .Github/Workflows/Release Train Ready.Yml (.github/workflows/release-train-ready.yml) # This file was auto-generated by github-actions-workflow-generator 0.0.6. Do not edit. # To update it, modify .github/workflow-generator.yml as needed and re-run the generator. name: "Release Train – Ready" run-name: "${{ inputs.release-train }} – Ready" "on": workflow_dispatch: inputs: release-train: description: "Release train" required: true type: "string" release-train-repository: default: "spring-io/release-train" description: "Release train repository" required: true type: "string" permissions: contents: "none" jobs: ready: name: "Ready" runs-on: "ubuntu-latest" steps: - name: "Ready" id: "ready" env: GH_TOKEN: "${{ secrets.RELEASE_TRAIN_PARTICIPANT_GITHUB_TOKEN }}" run: |- run_url=$( gh workflow run ready \ --repo ${{ inputs.release-train-repository }} \ --ref ${{ inputs.release-train }} \ --field commit-hash=${{ github.sha }} \ --field release-branch=${{ github.ref_name }} \ --field release-repository=${{ github.repository }} ) echo "Dispatched workflow run. Waiting for $run_url to complete." run_id=${run_url##*/} watch_exit_code=0 gh run watch $run_id --repo ${{ inputs.release-train-repository }} --exit-status --interval=3 > /dev/null 2>&1 || watch_exit_code=$? if [[ $watch_exit_code -eq 0 ]]; then echo "Workflow run succeeded." else echo "Workflow run failed." fi exit $watch_exit_code --- ### .Github/Workflows/Release Train Retry.Yml (.github/workflows/release-train-retry.yml) # This file was auto-generated by github-actions-workflow-generator 0.0.6. Do not edit. # To update it, modify .github/workflow-generator.yml as needed and re-run the generator. name: "Release Train – Retry" run-name: "${{ inputs.release-train }} – Retry" "on": workflow_dispatch: inputs: release-train: description: "Release train" required: true type: "string" release-train-repository: default: "spring-io/release-train" description: "Release train repository" required: true type: "string" permissions: contents: "none" jobs: trigger-retry: name: "Trigger Retry" runs-on: "ubuntu-latest" steps: - name: "Trigger Retry" id: "trigger-retry" env: GH_TOKEN: "${{ secrets.RELEASE_TRAIN_PARTICIPANT_GITHUB_TOKEN }}" run: |- gh workflow run retry \ --repo ${{ inputs.release-train-repository }} \ --ref ${{ inputs.release-train }} \ --field release-branch=${{ github.ref_name }} \ --field release-repository=${{ github.repository }} --- ### .Github/Workflows/Release Train Test.Yml (.github/workflows/release-train-test.yml) # This file was auto-generated by github-actions-workflow-generator 0.0.6. Do not edit. # To update it, modify .github/workflow-generator.yml as needed and re-run the generator. name: "Release Train – Test" run-name: "${{ inputs.callback-ref }} – Test" "on": workflow_dispatch: inputs: callback: description: "Repository to which a callback should be made upon completion" required: true type: "string" callback-ref: description: "Ref in the callback repository to which a callback should be made upon completion" required: true type: "string" release-train-maven-repository-url: description: "URL of a Maven repository to be used to resolve artifacts of projects earlier in the train" required: true type: "string" permissions: contents: "read" concurrency: group: "${{ github.workflow }}-${{ github.ref }}" jobs: test-release: name: "Test Release" runs-on: ${{ vars.UBUNTU_SMALL || 'ubuntu-latest' }} steps: - name: "Prevent Re-runs" id: "prevent-re-runs" run: |- if [ "$GITHUB_RUN_ATTEMPT" -gt 1 ]; then echo "Re-runs are prohibited. Use the 'Release Train – Retry' workflow to retry test failures" exit 1 fi - name: "Set up Java" id: "set-up-java" uses: "actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95" # v5.6.0 with: distribution: "liberica" java-version: "17" - name: "Check Out Code" id: "check-out-code" uses: "actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0" # v7.0.0 - name: "Restore Build System Caches" id: "restore-build-system-caches" uses: "actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9" # v6.1.0 with: key: "release-train-${{ inputs.callback-ref }}-${{ github.ref_name }}" path: "~/.m2/repository" - name: "Test Release" id: "test-release" uses: "./.github/actions/release-train-test" env: COMMERCIAL_ARTIFACTORY_PASSWORD: "${{ secrets.COMMERCIAL_ARTIFACTORY_PASSWORD }}" COMMERCIAL_ARTIFACTORY_USERNAME: "${{ secrets.COMMERCIAL_ARTIFACTORY_USERNAME }}" COMMERCIAL_RELEASE_REPO_URL: "${{ vars.COMMERCIAL_RELEASE_REPO_URL }}" RELEASE_TRAIN_MAVEN_REPOSITORY_PASSWORD: "${{ secrets.RELEASE_TRAIN_PARTICIPANT_MAVEN_REPOSITORY_PASSWORD }}" RELEASE_TRAIN_MAVEN_REPOSITORY_URL: "${{ inputs.release-train-maven-repository-url }}" RELEASE_TRAIN_MAVEN_REPOSITORY_USERNAME: "${{ secrets.RELEASE_TRAIN_PARTICIPANT_MAVEN_REPOSITORY_USERNAME }}" - name: "Send Callback" id: "send-callback" if: "${{ !cancelled() }}" env: GH_TOKEN: "${{ secrets.RELEASE_TRAIN_PARTICIPANT_GITHUB_TOKEN }}" run: |- gh workflow run callback \ --repo ${{ inputs.callback }} \ --ref ${{ inputs.callback-ref }} \ --field commit-hash=${{ steps.check-out-code.outputs.commit }} \ --field release-branch=${{ github.ref_name }} \ --field release-repository=${{ github.repository }} \ --field result=${{ job.status == 'success' && 'tested' || 'test-failed' }} \ --field workflow-run-url=${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - name: "Upload Build System Reports" id: "upload-build-system-reports" if: "${{ failure() }}" uses: "actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a" # v7.0.1 with: name: "build-system-reports" path: |- **/target/surefire-reports **/target/failsafe-reports --- ### .Github/Workflows/Spring Ai Dependency Updates.Yml (.github/workflows/spring-ai-dependency-updates.yml) name: Dependency Updates on: schedule: - cron: '0 7 * * 1' # 07:00 UTC every Monday workflow_dispatch: jobs: dependency-updates: name: List dependency updates runs-on: ubuntu-latest if: ${{ github.repository_owner == 'spring-projects' }} steps: - name: Checkout source code uses: actions/checkout@v6 - name: Set up JDK uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Check for dependency updates run: | ./mvnw --batch-mode -ntp \ versions:display-dependency-updates \ -DprocessDependencyManagementTransitive=false \ -DallowSnapshots=false \ -Dversions.outputFile=$(pwd)/dependency-updates.txt \ -Dversions.logOutput=false - name: Publish job summary run: | # Parse the versions-maven-plugin output into artifact|current|latest rows. # Lines come in two formats: # single-line: " groupId:artifact ..... current -> latest" # wrapped: " groupId:artifact ..." (artifact too long) # " current -> latest" awk ' /->/ { split($0, parts, " -> ") latest = parts[2] gsub(/^[ \t]+|[ \t\r\n]+$/, "", latest) n = split(parts[1], words, " ") current = words[n] if (pending != "") { print pending "|" current "|" latest pending = "" } else { artifact = words[1] if (index(artifact, ":") > 0) print artifact "|" current "|" latest } next } /^\s+[a-z].*:.*\.\.\.$/ { split($0, words, " ") pending = words[1] next } { pending = "" } ' dependency-updates.txt \ | grep -v '^org\.springframework\.ai:' \ | grep -v '|\${project\.version}|' \ | grep -v '|\${.*}|' \ | grep -v '^ch\.qos\.logback:' \ | grep -v '^co\.elastic\.clients:' \ | grep -v '^com\.couchbase\.client:' \ | grep -v '^com\.fasterxml\.jackson\.' \ | grep -v '^com\.google\.code\.gson:' \ | grep -v '^com\.microsoft\.onnxruntime:' \ | grep -v '^com\.zaxxer:HikariCP' \ | grep -v '^io\.grpc:' \ | grep -v '^io\.rest-assured:json-path' \ | grep -v '^io\.rest-assured:rest-assured\b' \ | grep -v '^jakarta\.servlet:' \ | grep -v '^jakarta\.validation:' \ | grep -v '^net\.bytebuddy:' \ | grep -v '^org\.apache\.httpcomponents\.client5:httpclient5' \ | grep -v '^org\.apache\.tomcat\.embed:' \ | grep -v '^org\.assertj:' \ | grep -v '^org\.hsqldb:' \ | grep -v '^org\.jetbrains\.kotlin:' \ | grep -v '^org\.junit\.jupiter:' \ | grep -v '^org\.mariadb\.jdbc:' \ | grep -v '^org\.neo4j\.driver:neo4j-java-driver' \ | grep -v '^org\.postgresql:' \ | grep -v '^org\.skyscreamer:' \ | grep -v '^redis\.clients:' \ | grep -v '^tools\.jackson\.' \ | sort -u \ > filtered-updates.txt echo "## Dependency Updates Available" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "> Versions already managed by imported BOMs (Spring Boot, DJL, MCP, REST Assured) are excluded from the report." >> $GITHUB_STEP_SUMMARY echo "> All updates require manual verification and integration testing before adoption." >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY if [ ! -s filtered-updates.txt ]; then echo "All dependencies are up to date." >> $GITHUB_STEP_SUMMARY else echo "| Dependency | Current | Latest |" >> $GITHUB_STEP_SUMMARY echo "|-----------|---------|--------|" >> $GITHUB_STEP_SUMMARY while IFS='|' read -r artifact current latest; do echo "| \`$artifact\` | $current | **$latest** |" >> $GITHUB_STEP_SUMMARY done < filtered-updates.txt fi - name: Upload full dependency update report if: always() uses: actions/upload-artifact@v6 with: name: dependency-updates-report path: dependency-updates.txt retention-days: 1 --- ### .Github/Workflows/Spring Ai Integration Tests.Yml (.github/workflows/spring-ai-integration-tests.yml) name: Spring AI Integration Tests run-name: Spring AI Integration Tests on: workflow_dispatch: inputs: test_suites: description: 'Test suites to run (comma-separated: ollama, anthropic, azure-openai, mistral-ai, elevenlabs, bedrock, deepseek, google-genai, vectorstores, autoconfigure, spring-ai-integration, docker-compose, testcontainers). Leave empty to run all.' required: false default: '' type: string exclude_test_suites: description: 'Test suites to exclude (comma-separated). Takes precedence over test_suites.' required: false default: '' type: string springBootVersion: description: 'Spring Boot version to test against (leave empty to use the project default)' required: false default: '' type: string runner: description: 'Runner label to use for all jobs (e.g. UBUNTU_SMALL, ubuntu-latest, ubuntu24-2-8-OSS). Leave empty to use the default.' required: false default: '' type: string schedule: - cron: '0 4 * * 1,3,5' # Mon, Wed, Fri at 4 AM UTC jobs: build-all: name: Build all modules if: ${{ github.repository_owner == 'spring-projects' }} runs-on: ${{ inputs.runner != '' && inputs.runner || (vars.COMMERCIAL && vars.UBUNTU_SMALL || 'ubuntu-latest') }} steps: - name: Checkout source code uses: actions/checkout@v6 - name: Set up JDK uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Build all modules env: COMMERCIAL_ARTIFACTORY_USERNAME: "${{ secrets.COMMERCIAL_ARTIFACTORY_USERNAME }}" COMMERCIAL_ARTIFACTORY_PASSWORD: "${{ secrets.COMMERCIAL_ARTIFACTORY_PASSWORD }}" COMMERCIAL_SNAPSHOT_REPO_URL: "${{ vars.COMMERCIAL_SNAPSHOT_REPO_URL }}" COMMERCIAL_RELEASE_REPO_URL: "${{ vars.COMMERCIAL_RELEASE_REPO_URL }}" run: | ./mvnw ${{ vars.COMMERCIAL && '-s commercial-settings.xml -Pcommercial' || '' }} --batch-mode -ntp --update-snapshots clean install -DskipTests \ ${{ inputs.springBootVersion != '' && format('-Dspring-boot.version={0}', inputs.springBootVersion) || '' }} - name: Upload Spring AI built artifacts uses: actions/upload-artifact@v6 with: name: build-artifacts path: ~/.m2/repository/org/springframework/ai retention-days: 1 - name: Purge Spring AI built artifacts run: rm -fr ~/.m2/repository/org/springframework/ai test-ollama: needs: build-all if: ${{ (github.event_name == 'schedule' || inputs.test_suites == '' || contains(inputs.test_suites, 'ollama')) && !contains(inputs.exclude_test_suites || '', 'ollama') }} runs-on: ${{ inputs.runner != '' && inputs.runner || (vars.COMMERCIAL && vars.UBUNTU_MEDIUM || 'ubuntu-latest') }} services: ollama: image: ollama/ollama:latest ports: - 11434:11434 env: OLLAMA_WITH_REUSE: true steps: - name: Checkout source code uses: actions/checkout@v6 - name: Set up JDK uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Download Spring AI built artifacts uses: actions/download-artifact@v7 with: name: build-artifacts path: ~/.m2/repository/org/springframework/ai - name: Configure Testcontainers run: | mkdir -p $HOME echo "testcontainers.reuse.enable = true" >> $HOME/.testcontainers.properties - name: Integration Test uses: ./.github/actions/do-integration-test with: model-name: ollama maven-properties: "-Dskip.model.ollama=false" spring-boot-version: ${{ inputs.springBootVersion }} test-anthropic: needs: build-all if: ${{ (github.event_name == 'schedule' || inputs.test_suites == '' || contains(inputs.test_suites, 'anthropic')) && !contains(inputs.exclude_test_suites || '', 'anthropic') }} runs-on: ${{ inputs.runner != '' && inputs.runner || (vars.COMMERCIAL && vars.UBUNTU_SMALL || 'ubuntu-latest') }} env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} steps: - name: Check secret id: secret_check if: ${{ env.ANTHROPIC_API_KEY != '' }} run: echo "Secret exists" - name: Checkout source code if: steps.secret_check.conclusion == 'success' uses: actions/checkout@v6 - name: Set up JDK if: steps.secret_check.conclusion == 'success' uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Download Spring AI built artifacts if: steps.secret_check.conclusion == 'success' uses: actions/download-artifact@v7 with: name: build-artifacts path: ~/.m2/repository/org/springframework/ai - name: Integration Test if: steps.secret_check.conclusion == 'success' uses: ./.github/actions/do-integration-test with: model-name: anthropic spring-boot-version: ${{ inputs.springBootVersion }} test-azure-openai: needs: build-all if: ${{ (github.event_name == 'schedule' || inputs.test_suites == '' || contains(inputs.test_suites, 'azure-openai')) && !contains(inputs.exclude_test_suites || '', 'azure-openai') }} runs-on: ${{ inputs.runner != '' && inputs.runner || (vars.COMMERCIAL && vars.UBUNTU_SMALL || 'ubuntu-latest') }} env: AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }} AZURE_OPENAI_ENDPOINT: ${{ secrets.AZURE_OPENAI_ENDPOINT }} AZURE_OPENAI_TRANSCRIPTION_API_KEY: ${{ secrets.AZURE_OPENAI_TRANSCRIPTION_API_KEY }} AZURE_OPENAI_TRANSCRIPTION_ENDPOINT: ${{ secrets.AZURE_OPENAI_TRANSCRIPTION_ENDPOINT }} AZURE_OPENAI_IMAGE_API_KEY: ${{ secrets.AZURE_OPENAI_IMAGE_API_KEY }} AZURE_OPENAI_IMAGE_ENDPOINT: ${{ secrets.AZURE_OPENAI_IMAGE_ENDPOINT }} steps: - name: Check secrets id: secret_check if: ${{ env.AZURE_OPENAI_API_KEY != '' && env.AZURE_OPENAI_ENDPOINT != '' && env.AZURE_OPENAI_TRANSCRIPTION_API_KEY != '' && env.AZURE_OPENAI_TRANSCRIPTION_ENDPOINT != '' && env.AZURE_OPENAI_IMAGE_API_KEY != '' && env.AZURE_OPENAI_IMAGE_ENDPOINT != '' }} run: echo "Secrets exist" - name: Checkout source code if: steps.secret_check.conclusion == 'success' uses: actions/checkout@v6 - name: Set up JDK if: steps.secret_check.conclusion == 'success' uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Download Spring AI built artifacts if: steps.secret_check.conclusion == 'success' uses: actions/download-artifact@v7 with: name: build-artifacts path: ~/.m2/repository/org/springframework/ai - name: Integration Test if: steps.secret_check.conclusion == 'success' uses: ./.github/actions/do-integration-test with: model-name: azure-openai spring-boot-version: ${{ inputs.springBootVersion }} test-mistral-ai: needs: build-all if: ${{ (github.event_name == 'schedule' || inputs.test_suites == '' || contains(inputs.test_suites, 'mistral-ai')) && !contains(inputs.exclude_test_suites || '', 'mistral-ai') }} runs-on: ${{ inputs.runner != '' && inputs.runner || (vars.COMMERCIAL && vars.UBUNTU_SMALL || 'ubuntu-latest') }} env: MISTRAL_AI_API_KEY: ${{ secrets.MISTRAL_AI_API_KEY }} steps: - name: Check secrets id: secret_check if: ${{ env.MISTRAL_AI_API_KEY != '' }} run: echo "Secrets exist" - name: Checkout source code uses: actions/checkout@v6 - name: Set up JDK uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Download Spring AI built artifacts uses: actions/download-artifact@v7 with: name: build-artifacts path: ~/.m2/repository/org/springframework/ai - name: Integration Test uses: ./.github/actions/do-integration-test with: model-name: mistral-ai spring-boot-version: ${{ inputs.springBootVersion }} test-elevenlabs: needs: build-all if: ${{ (github.event_name == 'schedule' || inputs.test_suites == '' || contains(inputs.test_suites, 'elevenlabs')) && !contains(inputs.exclude_test_suites || '', 'elevenlabs') }} runs-on: ${{ inputs.runner != '' && inputs.runner || (vars.COMMERCIAL && vars.UBUNTU_SMALL || 'ubuntu-latest') }} env: ELEVEN_LABS_API_KEY: ${{ secrets.ELEVEN_LABS_API_KEY }} steps: - name: Check secrets id: secret_check if: ${{ env.ELEVEN_LABS_API_KEY != '' }} run: echo "Secrets exist" - name: Checkout source code uses: actions/checkout@v6 - name: Set up JDK uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Download Spring AI built artifacts uses: actions/download-artifact@v7 with: name: build-artifacts path: ~/.m2/repository/org/springframework/ai - name: Integration Test uses: ./.github/actions/do-integration-test with: model-name: elevenlabs spring-boot-version: ${{ inputs.springBootVersion }} test-bedrock: needs: build-all if: ${{ (github.event_name == 'schedule' || inputs.test_suites == '' || contains(inputs.test_suites, 'bedrock')) && !contains(inputs.exclude_test_suites || '', 'bedrock') }} runs-on: ${{ inputs.runner != '' && inputs.runner || (vars.COMMERCIAL && vars.UBUNTU_SMALL || 'ubuntu-latest') }} env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} steps: - name: Check secrets id: secret_check if: ${{ env.AWS_ACCESS_KEY_ID != '' && env.AWS_SECRET_ACCESS_KEY != '' }} run: echo "Secrets exist" - name: Checkout source code if: steps.secret_check.conclusion == 'success' uses: actions/checkout@v6 - name: Set up JDK if: steps.secret_check.conclusion == 'success' uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Download Spring AI built artifacts if: steps.secret_check.conclusion == 'success' uses: actions/download-artifact@v7 with: name: build-artifacts path: ~/.m2/repository/org/springframework/ai - name: Integration Test if: steps.secret_check.conclusion == 'success' uses: ./.github/actions/do-multi-module-test with: modules: models/spring-ai-bedrock,models/spring-ai-bedrock-converse spring-boot-version: ${{ inputs.springBootVersion }} test-deepseek: needs: build-all if: ${{ (github.event_name == 'schedule' || inputs.test_suites == '' || contains(inputs.test_suites, 'deepseek')) && !contains(inputs.exclude_test_suites || '', 'deepseek') }} runs-on: ${{ inputs.runner != '' && inputs.runner || (vars.COMMERCIAL && vars.UBUNTU_SMALL || 'ubuntu-latest') }} env: DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }} steps: - name: Check secret id: secret_check if: ${{ env.DEEPSEEK_API_KEY != '' }} run: echo "Secret exists" - name: Checkout source code if: steps.secret_check.conclusion == 'success' uses: actions/checkout@v6 - name: Set up JDK if: steps.secret_check.conclusion == 'success' uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Download Spring AI built artifacts if: steps.secret_check.conclusion == 'success' uses: actions/download-artifact@v7 with: name: build-artifacts path: ~/.m2/repository/org/springframework/ai - name: Integration Test if: steps.secret_check.conclusion == 'success' uses: ./.github/actions/do-integration-test with: model-name: deepseek spring-boot-version: ${{ inputs.springBootVersion }} test-google-genai: needs: build-all if: ${{ (github.event_name == 'schedule' || inputs.test_suites == '' || contains(inputs.test_suites, 'google-genai')) && !contains(inputs.exclude_test_suites || '', 'google-genai') }} runs-on: ${{ inputs.runner != '' && inputs.runner || (vars.COMMERCIAL && vars.UBUNTU_SMALL || 'ubuntu-latest') }} env: GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} steps: - name: Check secret id: secret_check if: ${{ env.GOOGLE_API_KEY != '' }} run: echo "Secret exists" - name: Checkout source code if: steps.secret_check.conclusion == 'success' uses: actions/checkout@v6 - name: Set up JDK if: steps.secret_check.conclusion == 'success' uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Download Spring AI built artifacts if: steps.secret_check.conclusion == 'success' uses: actions/download-artifact@v7 with: name: build-artifacts path: ~/.m2/repository/org/springframework/ai - name: Integration Test if: steps.secret_check.conclusion == 'success' uses: ./.github/actions/do-integration-test with: model-name: google-genai spring-boot-version: ${{ inputs.springBootVersion }} test-vectorstores: needs: build-all if: ${{ (github.event_name == 'schedule' || inputs.test_suites == '' || contains(inputs.test_suites, 'vectorstores')) && !contains(inputs.exclude_test_suites || '', 'vectorstores') }} runs-on: ${{ inputs.runner != '' && inputs.runner || (vars.COMMERCIAL && vars.UBUNTU_MEDIUM || 'ubuntu-latest') }} services: ollama: image: ollama/ollama:latest ports: - 11434:11434 env: DOCKER_QUIET: 1 # Suppresses Docker CLI progress output TESTCONTAINERS_QUIET: true # Additional quieting for testcontainers OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} MISTRAL_AI_API_KEY: ${{ secrets.MISTRAL_AI_API_KEY }} OLLAMA_TESTS_ENABLED: true steps: - name: Check secrets id: secret_check if: ${{ env.OPENAI_API_KEY != '' && env.MISTRAL_AI_API_KEY != '' }} run: echo "Secrets exist" - name: Checkout source code uses: actions/checkout@v6 - name: Set up JDK uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Download Spring AI built artifacts uses: actions/download-artifact@v7 with: name: build-artifacts path: ~/.m2/repository/org/springframework/ai - name: Configure Testcontainers run: | mkdir -p $HOME echo "testcontainers.reuse.enable = true" >> $HOME/.testcontainers.properties - name: Integration Test uses: ./.github/actions/do-multi-module-test with: modules: vector-stores/spring-ai-azure-store,vector-stores/spring-ai-bedrock-knowledgebase-store,vector-stores/spring-ai-cassandra-store,vector-stores/spring-ai-chroma-store,vector-stores/spring-ai-coherence-store,vector-stores/spring-ai-couchbase-store,vector-stores/spring-ai-elasticsearch-store,vector-stores/spring-ai-gemfire-store,vector-stores/spring-ai-mariadb-store,vector-stores/spring-ai-milvus-store,vector-stores/spring-ai-mongodb-atlas-store,vector-stores/spring-ai-neo4j-store,vector-stores/spring-ai-opensearch-store,vector-stores/spring-ai-oracle-store,vector-stores/spring-ai-pgvector-store,vector-stores/spring-ai-pinecone-store,vector-stores/spring-ai-qdrant-store,vector-stores/spring-ai-redis-semantic-cache,vector-stores/spring-ai-redis-store,${{ vars.COMMERCIAL && 'vector-stores/spring-ai-s3-vector-store,' || '' }}vector-stores/spring-ai-typesense-store,vector-stores/spring-ai-weaviate-store spring-boot-version: ${{ inputs.springBootVersion }} test-autoconfigure: needs: build-all if: ${{ (github.event_name == 'schedule' || inputs.test_suites == '' || contains(inputs.test_suites, 'autoconfigure')) && !contains(inputs.exclude_test_suites || '', 'autoconfigure') }} runs-on: ${{ inputs.runner != '' && inputs.runner || (vars.COMMERCIAL && vars.UBUNTU_MEDIUM || 'ubuntu-latest') }} env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }} AZURE_OPENAI_ENDPOINT: ${{ secrets.AZURE_OPENAI_ENDPOINT }} ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} steps: - name: Checkout source code uses: actions/checkout@v6 - name: Set up JDK uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Download Spring AI built artifacts uses: actions/download-artifact@v7 with: name: build-artifacts path: ~/.m2/repository/org/springframework/ai - name: Autoconfigure Test uses: ./.github/actions/do-autoconfigure-test with: spring-ai-branch: ${{ github.ref_name }} spring-boot-version: ${{ inputs.springBootVersion }} test-spring-ai-integration: needs: build-all if: ${{ (github.event_name == 'schedule' || inputs.test_suites == '' || contains(inputs.test_suites, 'spring-ai-integration')) && !contains(inputs.exclude_test_suites || '', 'spring-ai-integration') }} runs-on: ${{ inputs.runner != '' && inputs.runner || (vars.COMMERCIAL && vars.UBUNTU_SMALL || 'ubuntu-latest') }} env: DOCKER_QUIET: 1 # Suppresses Docker CLI progress output TESTCONTAINERS_QUIET: true # Additional quieting for testcontainers OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} steps: - name: Check secrets id: secret_check if: ${{ env.OPENAI_API_KEY != '' }} run: echo "Secrets exist" - name: Checkout source code uses: actions/checkout@v6 - name: Set up JDK uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Download Spring AI built artifacts uses: actions/download-artifact@v7 with: name: build-artifacts path: ~/.m2/repository/org/springframework/ai - name: Configure Testcontainers run: | mkdir -p $HOME echo "testcontainers.reuse.enable = true" >> $HOME/.testcontainers.properties - name: Integration Test uses: ./.github/actions/do-multi-module-test with: modules: spring-ai-integration-tests spring-boot-version: ${{ inputs.springBootVersion }} test-docker-compose: needs: build-all if: ${{ (github.event_name == 'schedule' || inputs.test_suites == '' || contains(inputs.test_suites, 'docker-compose')) && !contains(inputs.exclude_test_suites || '', 'docker-compose') }} runs-on: ${{ inputs.runner != '' && inputs.runner || (vars.COMMERCIAL && vars.UBUNTU_SMALL || 'ubuntu-latest') }} env: DOCKER_QUIET: 1 # Suppresses Docker CLI progress output TESTCONTAINERS_QUIET: true # Additional quieting for testcontainers steps: - name: Checkout source code uses: actions/checkout@v6 - name: Set up JDK uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Download Spring AI built artifacts uses: actions/download-artifact@v7 with: name: build-artifacts path: ~/.m2/repository/org/springframework/ai - name: Configure Testcontainers run: | mkdir -p $HOME echo "testcontainers.reuse.enable = true" >> $HOME/.testcontainers.properties - name: Integration Test uses: ./.github/actions/do-multi-module-test with: modules: spring-ai-spring-boot-docker-compose spring-boot-version: ${{ inputs.springBootVersion }} test-testcontainers: needs: build-all if: ${{ (github.event_name == 'schedule' || inputs.test_suites == '' || contains(inputs.test_suites, 'testcontainers')) && !contains(inputs.exclude_test_suites || '', 'testcontainers') }} runs-on: ${{ inputs.runner != '' && inputs.runner || (vars.COMMERCIAL && vars.UBUNTU_MEDIUM || 'ubuntu24-2-8-OSS') }} env: DOCKER_QUIET: 1 # Suppresses Docker CLI progress output TESTCONTAINERS_QUIET: true # Additional quieting for testcontainers steps: - name: Checkout source code uses: actions/checkout@v6 - name: Set up JDK uses: actions/setup-java@v5 with: java-version: '17' distribution: 'liberica' cache: 'maven' - name: Download Spring AI built artifacts uses: actions/download-artifact@v7 with: name: build-artifacts path: ~/.m2/repository/org/springframework/ai - name: Configure Testcontainers run: | mkdir -p $HOME echo "testcontainers.reuse.enable = true" >> $HOME/.testcontainers.properties - name: Integration Test uses: ./.github/actions/do-multi-module-test with: modules: spring-ai-spring-boot-testcontainers spring-boot-version: ${{ inputs.springBootVersion }} ---