Initial commit for HK2 doc. pages.

Signed-off-by: Ed Bratt <ed.bratt@oracle.com>
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..cb1ad47
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,30 @@
+/Gemfile.lock
+/_site/
+/class-model/
+/consolidatedbundle-maven-plugin/
+/dependency-verifier/
+/dependency-visualizer/
+/examples/
+/external/
+/guice-bridge/
+/hk2-api/
+/hk2-configuration/
+/hk2-core/
+/hk2-extras/
+/hk2-inhabitant-generator/
+/hk2-jmx/
+/hk2-locator/
+/hk2-maven/
+/hk2-metadata-generator/
+/hk2-runlevel/
+/hk2-testing/
+/hk2-utils/
+/hk2/
+/osgi-resource-locator/
+/osgi/
+/osgiversion-maven-plugin/
+/spring-bridge
+/javadocs/
+/.jekyll-metadata
+/assets/
+/_layouts/
diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
new file mode 100644
index 0000000..5f7dd5b
--- /dev/null
+++ b/docs/CONTRIBUTING.md
@@ -0,0 +1,43 @@
+# Contributing to Jakarta Enterprise Beans
+
+Thanks for your interest in this project.
+
+## Project description
+
+Jakarta Enterprise Beans is an architecture for the development and deployment of
+component-based business applications.
+
+* https://projects.eclipse.org/projects/ee4j.ejb
+
+## Developer resources
+
+Information regarding source code management, builds, coding standards, and
+more.
+
+* https://projects.eclipse.org/projects/ee4j.ejb/developer
+
+The project maintains the following source code repositories
+
+* https://github.com/eclipse-ee4j/ejb-api
+
+## Eclipse Contributor Agreement
+
+Before your contribution can be accepted by the project team contributors must
+electronically sign the Eclipse Contributor Agreement (ECA).
+
+* http://www.eclipse.org/legal/ECA.php
+
+Commits that are provided by non-committers must have a Signed-off-by field in
+the footer indicating that the author is aware of the terms by which the
+contribution has been provided to the project. The non-committer must
+additionally have an Eclipse Foundation account and must have a signed Eclipse
+Contributor Agreement (ECA) on file.
+
+For more information, please see the Eclipse Committer Handbook:
+https://www.eclipse.org/projects/handbook/#resources-commit
+
+## Contact
+
+Contact the project developers via the project's "dev" list.
+
+*
diff --git a/docs/Gemfile b/docs/Gemfile
new file mode 100644
index 0000000..da482a6
--- /dev/null
+++ b/docs/Gemfile
@@ -0,0 +1,3 @@
+source 'https://rubygems.org'
+gem 'github-pages', group: :jekyll_plugins
+gem 'jekyll-sitemap', group: :jekyll_plugins
\ No newline at end of file
diff --git a/docs/LICENSE.md b/docs/LICENSE.md
new file mode 100644
index 0000000..5de3d1b
--- /dev/null
+++ b/docs/LICENSE.md
@@ -0,0 +1,637 @@
+# Eclipse Public License - v 2.0
+
+        THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+        PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION
+        OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+    1. DEFINITIONS
+
+    "Contribution" means:
+
+      a) in the case of the initial Contributor, the initial content
+         Distributed under this Agreement, and
+
+      b) in the case of each subsequent Contributor: 
+         i) changes to the Program, and 
+         ii) additions to the Program;
+      where such changes and/or additions to the Program originate from
+      and are Distributed by that particular Contributor. A Contribution
+      "originates" from a Contributor if it was added to the Program by
+      such Contributor itself or anyone acting on such Contributor's behalf.
+      Contributions do not include changes or additions to the Program that
+      are not Modified Works.
+
+    "Contributor" means any person or entity that Distributes the Program.
+
+    "Licensed Patents" mean patent claims licensable by a Contributor which
+    are necessarily infringed by the use or sale of its Contribution alone
+    or when combined with the Program.
+
+    "Program" means the Contributions Distributed in accordance with this
+    Agreement.
+
+    "Recipient" means anyone who receives the Program under this Agreement
+    or any Secondary License (as applicable), including Contributors.
+
+    "Derivative Works" shall mean any work, whether in Source Code or other
+    form, that is based on (or derived from) the Program and for which the
+    editorial revisions, annotations, elaborations, or other modifications
+    represent, as a whole, an original work of authorship.
+
+    "Modified Works" shall mean any work in Source Code or other form that
+    results from an addition to, deletion from, or modification of the
+    contents of the Program, including, for purposes of clarity any new file
+    in Source Code form that contains any contents of the Program. Modified
+    Works shall not include works that contain only declarations,
+    interfaces, types, classes, structures, or files of the Program solely
+    in each case in order to link to, bind by name, or subclass the Program
+    or Modified Works thereof.
+
+    "Distribute" means the acts of a) distributing or b) making available
+    in any manner that enables the transfer of a copy.
+
+    "Source Code" means the form of a Program preferred for making
+    modifications, including but not limited to software source code,
+    documentation source, and configuration files.
+
+    "Secondary License" means either the GNU General Public License,
+    Version 2.0, or any later versions of that license, including any
+    exceptions or additional permissions as identified by the initial
+    Contributor.
+
+    2. GRANT OF RIGHTS
+
+      a) Subject to the terms of this Agreement, each Contributor hereby
+      grants Recipient a non-exclusive, worldwide, royalty-free copyright
+      license to reproduce, prepare Derivative Works of, publicly display,
+      publicly perform, Distribute and sublicense the Contribution of such
+      Contributor, if any, and such Derivative Works.
+
+      b) Subject to the terms of this Agreement, each Contributor hereby
+      grants Recipient a non-exclusive, worldwide, royalty-free patent
+      license under Licensed Patents to make, use, sell, offer to sell,
+      import and otherwise transfer the Contribution of such Contributor,
+      if any, in Source Code or other form. This patent license shall
+      apply to the combination of the Contribution and the Program if, at
+      the time the Contribution is added by the Contributor, such addition
+      of the Contribution causes such combination to be covered by the
+      Licensed Patents. The patent license shall not apply to any other
+      combinations which include the Contribution. No hardware per se is
+      licensed hereunder.
+
+      c) Recipient understands that although each Contributor grants the
+      licenses to its Contributions set forth herein, no assurances are
+      provided by any Contributor that the Program does not infringe the
+      patent or other intellectual property rights of any other entity.
+      Each Contributor disclaims any liability to Recipient for claims
+      brought by any other entity based on infringement of intellectual
+      property rights or otherwise. As a condition to exercising the
+      rights and licenses granted hereunder, each Recipient hereby
+      assumes sole responsibility to secure any other intellectual
+      property rights needed, if any. For example, if a third party
+      patent license is required to allow Recipient to Distribute the
+      Program, it is Recipient's responsibility to acquire that license
+      before distributing the Program.
+
+      d) Each Contributor represents that to its knowledge it has
+      sufficient copyright rights in its Contribution, if any, to grant
+      the copyright license set forth in this Agreement.
+
+      e) Notwithstanding the terms of any Secondary License, no
+      Contributor makes additional grants to any Recipient (other than
+      those set forth in this Agreement) as a result of such Recipient's
+      receipt of the Program under the terms of a Secondary License
+      (if permitted under the terms of Section 3).
+
+    3. REQUIREMENTS
+
+    3.1 If a Contributor Distributes the Program in any form, then:
+
+      a) the Program must also be made available as Source Code, in
+      accordance with section 3.2, and the Contributor must accompany
+      the Program with a statement that the Source Code for the Program
+      is available under this Agreement, and informs Recipients how to
+      obtain it in a reasonable manner on or through a medium customarily
+      used for software exchange; and
+
+      b) the Contributor may Distribute the Program under a license
+      different than this Agreement, provided that such license:
+         i) effectively disclaims on behalf of all other Contributors all
+         warranties and conditions, express and implied, including
+         warranties or conditions of title and non-infringement, and
+         implied warranties or conditions of merchantability and fitness
+         for a particular purpose;
+
+         ii) effectively excludes on behalf of all other Contributors all
+         liability for damages, including direct, indirect, special,
+         incidental and consequential damages, such as lost profits;
+
+         iii) does not attempt to limit or alter the recipients' rights
+         in the Source Code under section 3.2; and
+
+         iv) requires any subsequent distribution of the Program by any
+         party to be under a license that satisfies the requirements
+         of this section 3.
+
+    3.2 When the Program is Distributed as Source Code:
+
+      a) it must be made available under this Agreement, or if the
+      Program (i) is combined with other material in a separate file or
+      files made available under a Secondary License, and (ii) the initial
+      Contributor attached to the Source Code the notice described in
+      Exhibit A of this Agreement, then the Program may be made available
+      under the terms of such Secondary Licenses, and
+
+      b) a copy of this Agreement must be included with each copy of
+      the Program.
+
+    3.3 Contributors may not remove or alter any copyright, patent,
+    trademark, attribution notices, disclaimers of warranty, or limitations
+    of liability ("notices") contained within the Program from any copy of
+    the Program which they Distribute, provided that Contributors may add
+    their own appropriate notices.
+
+    4. COMMERCIAL DISTRIBUTION
+
+    Commercial distributors of software may accept certain responsibilities
+    with respect to end users, business partners and the like. While this
+    license is intended to facilitate the commercial use of the Program,
+    the Contributor who includes the Program in a commercial product
+    offering should do so in a manner which does not create potential
+    liability for other Contributors. Therefore, if a Contributor includes
+    the Program in a commercial product offering, such Contributor
+    ("Commercial Contributor") hereby agrees to defend and indemnify every
+    other Contributor ("Indemnified Contributor") against any losses,
+    damages and costs (collectively "Losses") arising from claims, lawsuits
+    and other legal actions brought by a third party against the Indemnified
+    Contributor to the extent caused by the acts or omissions of such
+    Commercial Contributor in connection with its distribution of the Program
+    in a commercial product offering. The obligations in this section do not
+    apply to any claims or Losses relating to any actual or alleged
+    intellectual property infringement. In order to qualify, an Indemnified
+    Contributor must: a) promptly notify the Commercial Contributor in
+    writing of such claim, and b) allow the Commercial Contributor to control,
+    and cooperate with the Commercial Contributor in, the defense and any
+    related settlement negotiations. The Indemnified Contributor may
+    participate in any such claim at its own expense.
+
+    For example, a Contributor might include the Program in a commercial
+    product offering, Product X. That Contributor is then a Commercial
+    Contributor. If that Commercial Contributor then makes performance
+    claims, or offers warranties related to Product X, those performance
+    claims and warranties are such Commercial Contributor's responsibility
+    alone. Under this section, the Commercial Contributor would have to
+    defend claims against the other Contributors related to those performance
+    claims and warranties, and if a court requires any other Contributor to
+    pay any damages as a result, the Commercial Contributor must pay
+    those damages.
+
+    5. NO WARRANTY
+
+    EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
+    PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED 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. Each Recipient is solely responsible for determining the
+    appropriateness of using and distributing the Program and assumes all
+    risks associated with its exercise of rights under this Agreement,
+    including but not limited to the risks and costs of program errors,
+    compliance with applicable laws, damage to or loss of data, programs
+    or equipment, and unavailability or interruption of operations.
+
+    6. DISCLAIMER OF LIABILITY
+
+    EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
+    PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS
+    SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
+    PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+    ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
+    EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
+    POSSIBILITY OF SUCH DAMAGES.
+
+    7. GENERAL
+
+    If any provision of this Agreement is invalid or unenforceable under
+    applicable law, it shall not affect the validity or enforceability of
+    the remainder of the terms of this Agreement, and without further
+    action by the parties hereto, such provision shall be reformed to the
+    minimum extent necessary to make such provision valid and enforceable.
+
+    If Recipient institutes patent litigation against any entity
+    (including a cross-claim or counterclaim in a lawsuit) alleging that the
+    Program itself (excluding combinations of the Program with other software
+    or hardware) infringes such Recipient's patent(s), then such Recipient's
+    rights granted under Section 2(b) shall terminate as of the date such
+    litigation is filed.
+
+    All Recipient's rights under this Agreement shall terminate if it
+    fails to comply with any of the material terms or conditions of this
+    Agreement and does not cure such failure in a reasonable period of
+    time after becoming aware of such noncompliance. If all Recipient's
+    rights under this Agreement terminate, Recipient agrees to cease use
+    and distribution of the Program as soon as reasonably practicable.
+    However, Recipient's obligations under this Agreement and any licenses
+    granted by Recipient relating to the Program shall continue and survive.
+
+    Everyone is permitted to copy and distribute copies of this Agreement,
+    but in order to avoid inconsistency the Agreement is copyrighted and
+    may only be modified in the following manner. The Agreement Steward
+    reserves the right to publish new versions (including revisions) of
+    this Agreement from time to time. No one other than the Agreement
+    Steward has the right to modify this Agreement. The Eclipse Foundation
+    is the initial Agreement Steward. The Eclipse Foundation may assign the
+    responsibility to serve as the Agreement Steward to a suitable separate
+    entity. Each new version of the Agreement will be given a distinguishing
+    version number. The Program (including Contributions) may always be
+    Distributed subject to the version of the Agreement under which it was
+    received. In addition, after a new version of the Agreement is published,
+    Contributor may elect to Distribute the Program (including its
+    Contributions) under the new version.
+
+    Except as expressly stated in Sections 2(a) and 2(b) above, Recipient
+    receives no rights or licenses to the intellectual property of any
+    Contributor under this Agreement, whether expressly, by implication,
+    estoppel or otherwise. All rights in the Program not expressly granted
+    under this Agreement are reserved. Nothing in this Agreement is intended
+    to be enforceable by any entity that is not a Contributor or Recipient.
+    No third-party beneficiary rights are created under this Agreement.
+
+    Exhibit A - Form of Secondary Licenses Notice
+
+    "This Source Code may also be made available under the following 
+    Secondary Licenses when the conditions for such availability set forth 
+    in the Eclipse Public License, v. 2.0 are satisfied: {name license(s),
+    version(s), and exceptions or additional permissions here}."
+
+      Simply including a copy of this Agreement, including this Exhibit A
+      is not sufficient to license the Source Code under Secondary Licenses.
+
+      If it is not possible or desirable to put the notice in a particular
+      file, then You may include the notice in a location (such as a LICENSE
+      file in a relevant directory) where a recipient would be likely to
+      look for such a notice.
+
+      You may add additional accurate notices of copyright ownership.
+
+---
+
+##    The GNU General Public License (GPL) Version 2, June 1991
+
+    Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+    51 Franklin Street, Fifth Floor
+    Boston, MA 02110-1335
+    USA
+
+    Everyone is permitted to copy and distribute verbatim copies
+    of this license document, but changing it is not allowed.
+
+    Preamble
+
+    The licenses for most software are designed to take away your freedom to
+    share and change it. By contrast, the GNU General Public License is
+    intended to guarantee your freedom to share and change free software--to
+    make sure the software is free for all its users. This General Public
+    License applies to most of the Free Software Foundation's software and
+    to any other program whose authors commit to using it. (Some other Free
+    Software Foundation software is covered by the GNU Library General
+    Public License instead.) You can apply it to your programs, too.
+
+    When we speak of free software, we are referring to freedom, not price.
+    Our General Public Licenses are designed to make sure that you have the
+    freedom to distribute copies of free software (and charge for this
+    service if you wish), that you receive source code or can get it if you
+    want it, that you can change the software or use pieces of it in new
+    free programs; and that you know you can do these things.
+
+    To protect your rights, we need to make restrictions that forbid anyone
+    to deny you these rights or to ask you to surrender the rights. These
+    restrictions translate to certain responsibilities for you if you
+    distribute copies of the software, or if you modify it.
+
+    For example, if you distribute copies of such a program, whether gratis
+    or for a fee, you must give the recipients all the rights that you have.
+    You must make sure that they, too, receive or can get the source code.
+    And you must show them these terms so they know their rights.
+
+    We protect your rights with two steps: (1) copyright the software, and
+    (2) offer you this license which gives you legal permission to copy,
+    distribute and/or modify the software.
+
+    Also, for each author's protection and ours, we want to make certain
+    that everyone understands that there is no warranty for this free
+    software. If the software is modified by someone else and passed on, we
+    want its recipients to know that what they have is not the original, so
+    that any problems introduced by others will not reflect on the original
+    authors' reputations.
+
+    Finally, any free program is threatened constantly by software patents.
+    We wish to avoid the danger that redistributors of a free program will
+    individually obtain patent licenses, in effect making the program
+    proprietary. To prevent this, we have made it clear that any patent must
+    be licensed for everyone's free use or not licensed at all.
+
+    The precise terms and conditions for copying, distribution and
+    modification follow.
+
+    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+    0. This License applies to any program or other work which contains a
+    notice placed by the copyright holder saying it may be distributed under
+    the terms of this General Public License. The "Program", below, refers
+    to any such program or work, and a "work based on the Program" means
+    either the Program or any derivative work under copyright law: that is
+    to say, a work containing the Program or a portion of it, either
+    verbatim or with modifications and/or translated into another language.
+    (Hereinafter, translation is included without limitation in the term
+    "modification".) Each licensee is addressed as "you".
+
+    Activities other than copying, distribution and modification are not
+    covered by this License; they are outside its scope. The act of running
+    the Program is not restricted, and the output from the Program is
+    covered only if its contents constitute a work based on the Program
+    (independent of having been made by running the Program). Whether that
+    is true depends on what the Program does.
+
+    1. You may copy and distribute verbatim copies of the Program's source
+    code as you receive it, in any medium, provided that you conspicuously
+    and appropriately publish on each copy an appropriate copyright notice
+    and disclaimer of warranty; keep intact all the notices that refer to
+    this License and to the absence of any warranty; and give any other
+    recipients of the Program a copy of this License along with the Program.
+
+    You may charge a fee for the physical act of transferring a copy, and
+    you may at your option offer warranty protection in exchange for a fee.
+
+    2. You may modify your copy or copies of the Program or any portion of
+    it, thus forming a work based on the Program, and copy and distribute
+    such modifications or work under the terms of Section 1 above, provided
+    that you also meet all of these conditions:
+
+        a) You must cause the modified files to carry prominent notices
+        stating that you changed the files and the date of any change.
+
+        b) You must cause any work that you distribute or publish, that in
+        whole or in part contains or is derived from the Program or any part
+        thereof, to be licensed as a whole at no charge to all third parties
+        under the terms of this License.
+
+        c) If the modified program normally reads commands interactively
+        when run, you must cause it, when started running for such
+        interactive use in the most ordinary way, to print or display an
+        announcement including an appropriate copyright notice and a notice
+        that there is no warranty (or else, saying that you provide a
+        warranty) and that users may redistribute the program under these
+        conditions, and telling the user how to view a copy of this License.
+        (Exception: if the Program itself is interactive but does not
+        normally print such an announcement, your work based on the Program
+        is not required to print an announcement.)
+
+    These requirements apply to the modified work as a whole. If
+    identifiable sections of that work are not derived from the Program, and
+    can be reasonably considered independent and separate works in
+    themselves, then this License, and its terms, do not apply to those
+    sections when you distribute them as separate works. But when you
+    distribute the same sections as part of a whole which is a work based on
+    the Program, the distribution of the whole must be on the terms of this
+    License, whose permissions for other licensees extend to the entire
+    whole, and thus to each and every part regardless of who wrote it.
+
+    Thus, it is not the intent of this section to claim rights or contest
+    your rights to work written entirely by you; rather, the intent is to
+    exercise the right to control the distribution of derivative or
+    collective works based on the Program.
+
+    In addition, mere aggregation of another work not based on the Program
+    with the Program (or with a work based on the Program) on a volume of a
+    storage or distribution medium does not bring the other work under the
+    scope of this License.
+
+    3. You may copy and distribute the Program (or a work based on it,
+    under Section 2) in object code or executable form under the terms of
+    Sections 1 and 2 above provided that you also do one of the following:
+
+        a) Accompany it with the complete corresponding machine-readable
+        source code, which must be distributed under the terms of Sections 1
+        and 2 above on a medium customarily used for software interchange; or,
+
+        b) Accompany it with a written offer, valid for at least three
+        years, to give any third party, for a charge no more than your cost
+        of physically performing source distribution, a complete
+        machine-readable copy of the corresponding source code, to be
+        distributed under the terms of Sections 1 and 2 above on a medium
+        customarily used for software interchange; or,
+
+        c) Accompany it with the information you received as to the offer to
+        distribute corresponding source code. (This alternative is allowed
+        only for noncommercial distribution and only if you received the
+        program in object code or executable form with such an offer, in
+        accord with Subsection b above.)
+
+    The source code for a work means the preferred form of the work for
+    making modifications to it. For an executable work, complete source code
+    means all the source code for all modules it contains, plus any
+    associated interface definition files, plus the scripts used to control
+    compilation and installation of the executable. However, as a special
+    exception, the source code distributed need not include anything that is
+    normally distributed (in either source or binary form) with the major
+    components (compiler, kernel, and so on) of the operating system on
+    which the executable runs, unless that component itself accompanies the
+    executable.
+
+    If distribution of executable or object code is made by offering access
+    to copy from a designated place, then offering equivalent access to copy
+    the source code from the same place counts as distribution of the source
+    code, even though third parties are not compelled to copy the source
+    along with the object code.
+
+    4. You may not copy, modify, sublicense, or distribute the Program
+    except as expressly provided under this License. Any attempt otherwise
+    to copy, modify, sublicense or distribute the Program is void, and will
+    automatically terminate your rights under this License. However, parties
+    who have received copies, or rights, from you under this License will
+    not have their licenses terminated so long as such parties remain in
+    full compliance.
+
+    5. You are not required to accept this License, since you have not
+    signed it. However, nothing else grants you permission to modify or
+    distribute the Program or its derivative works. These actions are
+    prohibited by law if you do not accept this License. Therefore, by
+    modifying or distributing the Program (or any work based on the
+    Program), you indicate your acceptance of this License to do so, and all
+    its terms and conditions for copying, distributing or modifying the
+    Program or works based on it.
+
+    6. Each time you redistribute the Program (or any work based on the
+    Program), the recipient automatically receives a license from the
+    original licensor to copy, distribute or modify the Program subject to
+    these terms and conditions. You may not impose any further restrictions
+    on the recipients' exercise of the rights granted herein. You are not
+    responsible for enforcing compliance by third parties to this License.
+
+    7. If, as a consequence of a court judgment or allegation of patent
+    infringement or for any other reason (not limited to patent issues),
+    conditions are imposed on you (whether by court order, agreement or
+    otherwise) that contradict the conditions of this License, they do not
+    excuse you from the conditions of this License. If you cannot distribute
+    so as to satisfy simultaneously your obligations under this License and
+    any other pertinent obligations, then as a consequence you may not
+    distribute the Program at all. For example, if a patent license would
+    not permit royalty-free redistribution of the Program by all those who
+    receive copies directly or indirectly through you, then the only way you
+    could satisfy both it and this License would be to refrain entirely from
+    distribution of the Program.
+
+    If any portion of this section is held invalid or unenforceable under
+    any particular circumstance, the balance of the section is intended to
+    apply and the section as a whole is intended to apply in other
+    circumstances.
+
+    It is not the purpose of this section to induce you to infringe any
+    patents or other property right claims or to contest validity of any
+    such claims; this section has the sole purpose of protecting the
+    integrity of the free software distribution system, which is implemented
+    by public license practices. Many people have made generous
+    contributions to the wide range of software distributed through that
+    system in reliance on consistent application of that system; it is up to
+    the author/donor to decide if he or she is willing to distribute
+    software through any other system and a licensee cannot impose that choice.
+
+    This section is intended to make thoroughly clear what is believed to be
+    a consequence of the rest of this License.
+
+    8. If the distribution and/or use of the Program is restricted in
+    certain countries either by patents or by copyrighted interfaces, the
+    original copyright holder who places the Program under this License may
+    add an explicit geographical distribution limitation excluding those
+    countries, so that distribution is permitted only in or among countries
+    not thus excluded. In such case, this License incorporates the
+    limitation as if written in the body of this License.
+
+    9. The Free Software Foundation may publish revised and/or new
+    versions of the General Public License from time to time. Such new
+    versions will be similar in spirit to the present version, but may
+    differ in detail to address new problems or concerns.
+
+    Each version is given a distinguishing version number. If the Program
+    specifies a version number of this License which applies to it and "any
+    later version", you have the option of following the terms and
+    conditions either of that version or of any later version published by
+    the Free Software Foundation. If the Program does not specify a version
+    number of this License, you may choose any version ever published by the
+    Free Software Foundation.
+
+    10. If you wish to incorporate parts of the Program into other free
+    programs whose distribution conditions are different, write to the
+    author to ask for permission. For software which is copyrighted by the
+    Free Software Foundation, write to the Free Software Foundation; we
+    sometimes make exceptions for this. Our decision will be guided by the
+    two goals of preserving the free status of all derivatives of our free
+    software and of promoting the sharing and reuse of software generally.
+
+    NO WARRANTY
+
+    11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
+    WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+    EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+    OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND,
+    EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+    ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
+    YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+    NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+    12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+    WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+    AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
+    DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
+    DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
+    (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
+    INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
+    THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR
+    OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+    END OF TERMS AND CONDITIONS
+
+    How to Apply These Terms to Your New Programs
+
+    If you develop a new program, and you want it to be of the greatest
+    possible use to the public, the best way to achieve this is to make it
+    free software which everyone can redistribute and change under these terms.
+
+    To do so, attach the following notices to the program. It is safest to
+    attach them to the start of each source file to most effectively convey
+    the exclusion of warranty; and each file should have at least the
+    "copyright" line and a pointer to where the full notice is found.
+
+        One line to give the program's name and a brief idea of what it does.
+        Copyright (C) <year> <name of author>
+
+        This program is free software; you can redistribute it and/or modify
+        it under the terms of the GNU General Public License as published by
+        the Free Software Foundation; either version 2 of the License, or
+        (at your option) any later version.
+
+        This program is distributed in the hope that it will be useful, but
+        WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+        General Public License for more details.
+
+        You should have received a copy of the GNU General Public License
+        along with this program; if not, write to the Free Software
+        Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
+
+    Also add information on how to contact you by electronic and paper mail.
+
+    If the program is interactive, make it output a short notice like this
+    when it starts in an interactive mode:
+
+        Gnomovision version 69, Copyright (C) year name of author
+        Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type
+        `show w'. This is free software, and you are welcome to redistribute
+        it under certain conditions; type `show c' for details.
+
+    The hypothetical commands `show w' and `show c' should show the
+    appropriate parts of the General Public License. Of course, the commands
+    you use may be called something other than `show w' and `show c'; they
+    could even be mouse-clicks or menu items--whatever suits your program.
+
+    You should also get your employer (if you work as a programmer) or your
+    school, if any, to sign a "copyright disclaimer" for the program, if
+    necessary. Here is a sample; alter the names:
+
+        Yoyodyne, Inc., hereby disclaims all copyright interest in the
+        program `Gnomovision' (which makes passes at compilers) written by
+        James Hacker.
+
+        signature of Ty Coon, 1 April 1989
+        Ty Coon, President of Vice
+
+    This General Public License does not permit incorporating your program
+    into proprietary programs. If your program is a subroutine library, you
+    may consider it more useful to permit linking proprietary applications
+    with the library. If this is what you want to do, use the GNU Library
+    General Public License instead of this License.
+
+---
+
+## CLASSPATH EXCEPTION
+
+    Linking this library statically or dynamically with other modules is
+    making a combined work based on this library.  Thus, the terms and
+    conditions of the GNU General Public License version 2 cover the whole
+    combination.
+
+    As a special exception, the copyright holders of this library give you
+    permission to link this library with independent modules to produce an
+    executable, regardless of the license terms of these independent
+    modules, and to copy and distribute the resulting executable under
+    terms of your choice, provided that you also meet, for each linked
+    independent module, the terms and conditions of the license of that
+    module.  An independent module is a module which is not derived from or
+    based on this library.  If you modify this library, you may extend this
+    exception to your version of the library, but you are not obligated to
+    do so.  If you do not wish to do so, delete this exception statement
+    from your version.
diff --git a/docs/_config.yml b/docs/_config.yml
new file mode 100644
index 0000000..5fab2d2
--- /dev/null
+++ b/docs/_config.yml
@@ -0,0 +1,17 @@
+remote_theme: eclipsefdn/jekyll-theme-eclipsefdn
+
+title: GlassFish HK2 - Dependency Injection Kernel
+description: A light-weight and dynamic dependency injection framework
+
+# sidebar links url
+links:
+  download: https://repo1.maven.org/maven2/org/glassfish/hk2/
+  source: https://github.com/eclipse-ee4j/glassfish-hk2
+  mailinglist: https://accounts.eclipse.org/mailing-list/glassfish-dev
+  #javadocs:
+  #docs:
+  #faq:
+  #hide_issuetracker: true #set explicitly to 'true' if you don't want to have the issue tracker link displayed
+
+gems:
+  - jekyll-sitemap
diff --git a/docs/aop-default.md b/docs/aop-default.md
new file mode 100644
index 0000000..b49f1e1
--- /dev/null
+++ b/docs/aop-default.md
@@ -0,0 +1,214 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+* TOC
+{:toc}
+
+# Default Interception Service Implementation
+
+In the hk2-extras module there is a default implementation of the [InterceptionService][interceptionservice] which
+uses annotations to determine what services are to be intercepted and which interceptors should
+be used.  This page describes this default implementation.
+
+## Indicating Services to be Intercepted
+
+All services to be intercepted by this implementation must be annotated with the
+[Intercepted][intercepted] qualifier.  The [Intercepted][intercepted] qualifier may
+only be placed on classes.  Here is an example of a service that can used method or
+constructor interception when using the default [InterceptionService][interceptionservice]
+implementation:
+
+```java
+@Service
+@Intercepted
+public class MyService {
+  // Can be intercepted
+  @Inject
+  public MyService(ServiceLocator locator) {
+  }
+  
+  // Can be intercepted
+  public boolean goEagles() {
+    return true;
+  }
+}
+```
+
+## Indicating Interceptors
+
+A class that wishes to be used as a method or constructor interceptor must adhere to the
+following rules:
+
++ must be an hk2 service
++ must implement either [MethodInterceptor][methodinterceptor] or [ConstructorInterceptor][constructorinterceptor]
++ must advertise [MethodInterceptor][methodinterceptor] or [ConstructorInterceptor][constructorinterceptor] as one of its contracts
++ must be annotated with the [Interceptor][interceptor] qualifier
+
+Since [MethodInterceptor][methodinterceptor] and [ConstructorInterceptor][constructorinterceptor] are API from
+the AopAlliance, they are not naturally marked with [Contract][contract].  Therefore it is often the case
+when doing automatic analysis of contracts that the [ContractsProvided][contractsprovided] annotation
+must be used to ensure that the standard AopAlliance interface is included in the set of
+contracts.  Here is an example of a method interceptor:
+
+```java
+@Service
+@Interceptor
+@ContractsProvided({MyMethodInterceptor.class, MethodInterceptor.class})
+public class MyMethodInterceptor implements MethodInterceptor {
+  // ...
+}
+```
+
+Here is an example of a constructor interceptor:
+
+```java
+@Service
+@Interceptor
+@ContractsProvided({MyConstructorInterceptor.class, ConstructorInterceptor.class})
+public class MyConstructorInterceptor implements ConstructorInterceptor {
+  // ...
+}
+```
+
+## Interception Bindings
+
+We must still be able to associate intercepted things such as constructors and methods of intercepted services
+with the specific interceptors.  This is done by using the [InterceptionBinder][interceptionbinder]
+annotation.  The [InterceptionBinder][interceptionbinder] is placed on user defined annotations to indicate
+that the annotation is meant to associate an interceptor and the thing to be intercepted.
+
+For example, if the user has a security interceptor, they might define their annotation like this:
+
+```java
+@Inherited
+@InterceptionBinder
+@Target({TYPE, METHOD, CONSTRUCTOR})
+@Retention(RUNTIME)
+@Documented
+public @interface Secure {
+}
+```
+
+They would then put that annotation both on the security interceptor like so:
+
+```java
+@Service
+@Interceptor
+@ContractsProvided({ConstructorInterceptor.class, MethodInterceptor.class})
+@Secure
+public class SecurityInterceptor implements MethodInterceptor, ConstructorInterceptor {
+  // ...
+}
+```
+
+Then any method or constructor on an intercepted service that needs to be secure
+would add the @Secure annotation as well:
+
+```java
+@Service
+@Intercepted
+public class KernelSanders {
+
+  @Secure
+  public KernelSanders() {
+    // Lets make some chicken!
+  }
+
+  @Secure
+  public String getSecretFormula() {
+    return secretFormula;
+  }
+}
+```
+
+The user annotation that is marked with [InterceptionBinder][interceptionbinder] can
+also be placed on the service that is intercepted in order to indicate that all
+methods (and the construtor which hk2 will call) should be intercepted by interceptors
+with matching annotations.  For example if the user annotation is this:
+
+```java
+@Inherited
+@InterceptionBinder
+@Target({TYPE, METHOD, CONSTRUCTOR})
+@Retention(RUNTIME)
+@Documented
+public @interface Trace {
+}
+```
+
+Then the intercepted service can put Trace at the class level to indicate that all
+methods should be traced:
+
+```java
+@Service
+@Intercepted
+@Trace
+public class LoudService {
+}
+```
+
+If there is a corresponding interceptor that is marked with the Trace annotation then all
+methods and/or constructors of the LoudService will be traced.
+
+Also, annotations marked with [InterceptionBinder][interceptionbinder] are transitive.
+So services marked with the following annotation will invoke interceptors with both the
+Secure and Trace annotations:
+
+```java
+@Inherited
+@InterceptionBinder
+@Trace @Secure
+@Target({TYPE, METHOD, CONSTRUCTOR})
+@Retention(RUNTIME)
+@Documented
+public @interface SecurelyTraceable {
+}
+```
+
+## Interceptor Ordering and Customization
+
+Normally interceptors will run in their natural HK2 ordering (based on Rank and serivce/locator id)
+but sometimes it is convenient to re-order the interceptors based on some external configuration. 
+It may also be convenient to add or remove interceptors that will run with some method or
+constructor.  The default implementation of the interception service has defined its own plugin service
+named the [InterceptorOrderingService][interceptororderingservice] that allows users to add, modify
+or remove the set of intereceptors that would normally be run on a method or constructor.
+
+The methods of the [InterceptorOrderingService][interceptororderingservice] are supplied with
+the list of interceptors that would be run on the given Method or Constructor.  The
+implementations of those methods can either return the list as-is (or return null) or they can
+return their own list with a set of interceptors that should be run instead (and in what order).
+If there are more than one implementation of the [InterceptorOrderingService][interceptororderingservice]
+then all implementations are run in hk2 ranking order with the results of the previous service
+being given to the next service.  In this way chains of interceptor ordering modifiers can be used together.
+
+## Getting it all started
+
+In order to enable the default implementation of the [InterceptionService][interceptionservice]
+you will need to use the enableDefaultInterceptorServiceImplementation method of
+the [ExtrasUtilities][extrasutilities] class.  You will also need to include the hk2-extras module
+on your classpath.
+
+[interceptionservice]: apidocs/org/glassfish/hk2/api/InterceptionService.html
+[intercepted]: apidocs/org/glassfish/hk2/extras/interception/Intercepted.html
+[interceptor]: apidocs/org/glassfish/hk2/extras/interception/Interceptor.html
+[methodinterceptor]: http://aopalliance.sourceforge.net/doc/org/aopalliance/intercept/MethodInterceptor.html
+[constructorinterceptor]: http://aopalliance.sourceforge.net/doc/org/aopalliance/intercept/ConstructorInterceptor.html
+[contract]: apidocs/org/jvnet/hk2/annotations/Contract.html
+[contractsprovided]: apidocs/org/glassfish/hk2/api/ContractsProvided.html
+[extrasutilities]: apidocs/org/glassfish/hk2/extras/ExtrasUtilities.html
+[interceptionbinder]: apidocs/org/glassfish/hk2/extras/interception/InterceptionBinder.html
+[interceptororderingservice]: apidocs/org/glassfish/hk2/extras/interception/InterceptorOrderingService.html
diff --git a/docs/aop-example.md b/docs/aop-example.md
new file mode 100644
index 0000000..c42453f
--- /dev/null
+++ b/docs/aop-example.md
@@ -0,0 +1,427 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+* TOC
+{:toc}
+
+# Aspect Oriented Programming (AOP) Example
+
+This example illustrates how to use Aspect Oriented Programming (AOP) with HK2
+services.
+
+AOP is generally used for cross-cutting concerns such as security or transactions.
+This example will illustrate how you can use
+AOP in HK2 in order to elegantly solve these sorts of issues.
+
+HK2 AOP allows you to use [AOP Alliance][aopalliance] [method][methodinterceptors]
+and [constructor][constructorinterceptors] interceptors with most
+services that HK2 constructs.  This example will present simple caching
+interceptors to illustrate how to write interceptors and then use those
+interceptors with HK2 services.
+
+## Caching Interceptors
+
+The method interceptor shown here assumes that the methods it will be used with
+take one input parameter and return some sort of result.  When the method is called
+with an input parameter it has already seen the interceptor will not call the underlying
+method, but will instead find the previous result in the cache and return it.  This saves
+the method from performing the same calculation over again.  Here is the code for the
+method interceptor:
+
+```java
+public class CachingMethodInterceptor implements MethodInterceptor {
+    private final HashMap<CacheKey, Object> cache = new HashMap<CacheKey, Object>();
+
+    public Object invoke(MethodInvocation invocation) throws Throwable {
+        Object args[] = invocation.getArguments();
+        if (args.length != 1) {
+            return invocation.proceed();
+        }
+        
+        Object arg = args[0];
+        if (arg == null) {
+            return invocation.proceed();
+        }
+        
+        Method m = invocation.getMethod();
+        CacheKey key = new CacheKey(m.getDeclaringClass().getName(), m.getName(), arg);
+        
+        if (!cache.containsKey(key)) {
+            Object retVal = invocation.proceed();
+            
+            cache.put(key, retVal);
+            
+            return retVal;
+        }
+        
+        // Found it in the cache!  Do not call the method
+        return cache.get(key);
+    }
+}
+```
+
+The cache is the HashMap field named cache.  After some defensive checking
+the interceptor creates a CacheKey from the input parameters.  The interceptor then
+checks to see if the cache contains the corresponding key.  If the cache does not contain the corresponding
+key then it goes ahead and calls the underlying method with the call to proceed, saving the output.  
+The method interceptor then puts that key and the result into the cache.  However if it does find the
+CacheKey in the cache then it just returns the result *without* calling the proceed method, and thus the
+underlying method on the service will NOT get called.
+
+Here is the code for the CacheKey, which is an immutable object composed of the name of the class,
+the name of the method called, and the argument sent to the method:
+
+```java
+public class CacheKey {
+    private final String className;
+    private final String methodName;
+    private final Object input;
+    
+    public CacheKey(String className, String methodName, Object input) {
+        this.className = className;
+        this.methodName = methodName;
+        this.input = input;
+    }
+    
+    public int hashCode() {
+        return className.hashCode() ^ methodName.hashCode() ^ input.hashCode();
+    }
+    
+    public boolean equals(Object o) {
+        if (o == null) return false;
+        if (!(o instanceof CacheKey)) return false;
+        CacheKey other = (CacheKey) o;
+        
+        if (!other.className.equals(className)) return false;
+        if (!other.methodName.equals(methodName)) return false;
+        return other.input.equals(input);
+    }
+}
+```
+
+The CacheKey has an appropriate hashCode and equals method for objects that will be used as
+a key in a HashMap.  The CacheKey will also bin be used in the constructor interceptor.
+
+The constructor interceptor works exactly the same as the method interceptor, although the effect
+it has on the service is somewhat different than the effect it has on the method, since
+a constructor controls creation of the instance of the class.  Here is the constructor interceptor:
+
+```java
+public class CachingConstructorInterceptor implements ConstructorInterceptor {
+    private final HashMap<CacheKey, Object> cache = new HashMap<CacheKey, Object>();
+
+    public Object construct(ConstructorInvocation invocation) throws Throwable {
+        Object args[] = invocation.getArguments();
+        if (args.length != 1) {
+            return invocation.proceed();
+        }
+        
+        Object arg = args[0];
+        if (arg == null) {
+            return invocation.proceed();
+        }
+        
+        Constructor<?> c = invocation.getConstructor();
+        CacheKey key = new CacheKey(c.getDeclaringClass().getName(), "<init>", arg);
+        
+        if (!cache.containsKey(key)) {
+            Object retVal = invocation.proceed();
+            
+            cache.put(key, retVal);
+            
+            return retVal;
+        }
+        
+        // Found it in the cache!  Do not call the method
+        return cache.get(key);
+    }
+```
+
+This code should look familiar, as it follows exactly the same pattern as the method interceptor.
+This interceptor will only work on constructors with one input parameter and will short-circuit
+the creation of a new object by returning the value in the cache (assuming one is found).  If
+no corresponding object is found in the cache then a new object will be created with the call
+to proceed.
+
+Both the method and constructor interceptors use no HK2 API and can therefore be used in any
+AOP alliance system.  However there is nothing preventing writers of AOP alliance interceptors
+from using HK2 services as AOP alliance interceptors, in which case they could do things like inject
+transaction or security managers.
+
+### Using Interceptors in HK2
+
+In order to use AOP Alliance interceptors in HK2 an instance of the [InterceptionService][interceptionservice]
+must be added to the HK2 registry.  An implementation of [InterceptionService][interceptionservice] must be in
+the Singleton scope.  It has the job of determining which HK2 services ([ActiveDescriptors][activedescriptor])
+are candidates to use interception and then to specify exactly which methods and constructors of those
+services should be intercepted.
+
+This example uses an annotation called Cache that when placed on a method or constructor indicates
+that that method or constructor should be intercepted with the caching interceptor.  This is the definition
+of the Cache annotation:
+
+```java
+@Retention(RUNTIME)
+@Target( { METHOD, CONSTRUCTOR })
+public @interface Cache {
+}
+```
+
+The example [InterceptionService][interceptionservice] is named HK2InterceptionService and is in
+the Singleton scope, as must all implementations of [InterceptionService][interceptionservice].  When
+HK2 creates a new service it will look through all of the implementations of
+[InterceptionService][interceptionservice] looking for ones that are appropriate for the services'
+[ActiveDescriptor][activedescriptor].  If the [ActiveDescriptor][activedescriptor] passes through the filter
+returned by the [InterceptionService][interceptionservice] then all the methods of that service
+will be given to the [InterceptionService][interceptionservice] in order to determine what method
+interceptors should be called for that method.  The single constructor that HK2 would normally use
+will also be given to the [InterceptionService][interceptionservice] in order to determine what
+constructor interceptors should be called for that constructor.
+
+The example [InterceptionService][interceptionservice] inspects the input methods and constructors to see if
+they are annotated with @Cache, and if they are it returns the caching interceptors described in the
+previous section.  The filter that the example [InterceptionService][interceptionservice] uses to select HK2
+services is the [BuilderHelper][builderhelper] allFilter, since any method or constructor might
+be a candidate for caching.  Here is the code for the example caching HK2
+[InterceptionService][interceptionservice]:
+
+```java
+@Service
+public class HK2InterceptionService implements InterceptionService {
+    private final static MethodInterceptor METHOD_INTERCEPTOR = new CachingMethodInterceptor();
+    private final static ConstructorInterceptor CONSTRUCTOR_INTERCEPTOR = new CachingConstructorInterceptor();
+    
+    private final static List<MethodInterceptor> METHOD_LIST = Collections.singletonList(METHOD_INTERCEPTOR);
+    private final static List<ConstructorInterceptor> CONSTRUCTOR_LIST = Collections.singletonList(CONSTRUCTOR_INTERCEPTOR);
+
+    public Filter getDescriptorFilter() {
+        return BuilderHelper.allFilter();
+    }
+
+    public List<MethodInterceptor> getMethodInterceptors(Method method) {
+        if (method.isAnnotationPresent(Cache.class)) {
+            return METHOD_LIST;
+        }
+        
+        return null;
+    }
+
+    public List<ConstructorInterceptor> getConstructorInterceptors(
+            Constructor<?> constructor) {
+        if (constructor.isAnnotationPresent(Cache.class)) {
+            return CONSTRUCTOR_LIST;
+        }
+        
+        return null;
+    }
+}
+```
+
+In the next section we will use our caching annotation and the caching interceptors on an example
+set of services.
+
+### Using @Cache on Methods
+
+The runner project under examples/caching in the HK2 source tree contains an example of method and
+constructor injection using the system described in the above secion (which is under examples/caching/system).
+It also contains unit tests to ensure that everything in the example is working as expected.
+
+The ExpensiveMethods class has a method on it that performs an expensive operation.  The expensive method
+counts the number of times it has been called so that the class can easily demonstrate that the caching code
+has worked.
+
+```java
+@Service @Singleton
+public class ExpensiveMethods {
+    private int timesCalled = 0;
+    
+    @Cache
+    public int veryExpensiveCalculation(int input) {
+        timesCalled++;
+        return input + 1;
+    }
+    
+    public int getNumTimesCalled() {
+        return timesCalled;
+    }
+    
+    public void clear() {
+        timesCalled = 0;
+    }
+}
+```
+
+The ExpensiveMethods service is in the Singleton scope and hence will get created once.  However, the
+method named veryExpensiveCalculation will only get called once per input integer.  So if the method
+is called ten times with an input parameter of 1 the method on ExpensiveMethods will only get called once.  The
+output from that call will be saved in the cache and every other time the method is called by the application
+the returned value will come from the cache rather than calling the method again.  This can be seen
+with the test code:
+
+```java
+    @Test
+    public void testMethodsAreIntercepted() {
+        ExpensiveMethods expensiveMethods = testLocator.getService(ExpensiveMethods.class);
+        
+        // Now call the expensive method
+        int result = expensiveMethods.veryExpensiveCalculation(1);
+        Assert.assertEquals(2, result);
+        
+        // The expensive method should have been called
+        Assert.assertEquals(1, expensiveMethods.getNumTimesCalled());
+        
+        // Now call the expensive method ten more times
+        for (int i = 0; i < 10; i++) {
+            result = expensiveMethods.veryExpensiveCalculation(1);
+            Assert.assertEquals(2, result);
+        }
+        
+        // But the expensive call was never made again, since the result was cached!
+        Assert.assertEquals(1, expensiveMethods.getNumTimesCalled());
+    }
+```
+
+### Using @Cache on a Constructor
+
+Caching on a constructor can limit the number of times a service is created.  The example
+class called ExpensiveConstructor is in the PerLookup scope.  However, since @Cache has been
+place on its constructor, it will in fact only get created when different input parameters are given
+to the constructor.  Static fields are used in ExpensiveConstructor to keep track of how many times
+the service has been created.  Here is the ExpensiveConstructor service:
+
+```java
+@Service @PerLookup
+public class ExpensiveConstructor {
+    private static int numTimesConstructed;
+    private final int multiplier;
+    
+    @Inject @Cache
+    public ExpensiveConstructor(int multiplier) {
+        // Very expensive operation
+        this.multiplier = multiplier * 2;
+        numTimesConstructed++;
+    }
+    
+    public int getComputation() {
+        return multiplier;
+    }
+    
+    public static void clear() {
+        numTimesConstructed = 0;
+    }
+    
+    public static int getNumTimesConstructed() {
+        return numTimesConstructed;
+    }
+}
+```
+
+The ExpensiveConstructor class takes an integer input parameter.  In order to create an integer input
+that can change values there is an implementation of [Factory][factory] called InputFactory which produces
+integers.  The provide method of InputFactory changes the value it returns based on how it
+is currently configured.  Here is the code for InputFactory:
+
+```java
+@Service
+public class InputFactory implements Factory<Integer> {
+    private int input;
+
+    @PerLookup
+    public Integer provide() {
+        return input;
+    }
+
+    public void dispose(Integer instance) {
+    }
+    
+    public void setInput(int input) {
+        this.input = input;
+    }
+}
+```
+
+The test code for this demonstrates how to change the input parameter for the
+ExpensiveConstructor service.  The test then uses the static methods to show that
+the service is only created when the input parameter changes, even though
+the service is in the PerLookup scope.
+
+```java
+    @Test
+    public void testConstructorsAreIntercepted() {
+        InputFactory inputFactory = testLocator.getService(InputFactory.class);
+        inputFactory.setInput(2);
+        
+        ExpensiveConstructor instanceOne = testLocator.getService(ExpensiveConstructor.class);
+        
+        int computation = instanceOne.getComputation();
+        Assert.assertEquals(4, computation);
+        
+        Assert.assertEquals(1, ExpensiveConstructor.getNumTimesConstructed());
+        
+        ExpensiveConstructor instanceTwo = testLocator.getService(ExpensiveConstructor.class);
+        
+        computation = instanceTwo.getComputation();
+        Assert.assertEquals(4, computation);
+        
+        // Amazingly, the object was NOT recreated:
+        Assert.assertEquals(1, ExpensiveConstructor.getNumTimesConstructed());
+        
+        // Further proof that it was not recreated:
+        Assert.assertTrue(instanceOne == instanceTwo);
+        
+        // Now change the input parameter
+        inputFactory.setInput(8);
+        
+        ExpensiveConstructor instanceThree = testLocator.getService(ExpensiveConstructor.class);
+        
+        computation = instanceThree.getComputation();
+        Assert.assertEquals(16, computation);
+        
+        Assert.assertFalse(instanceOne.equals(instanceThree));
+    }
+```
+
+### AOP Requirements
+
+In order to use method interceptors proxies are used.  Therefore services that use method interceptors
+must not be final nor have any final methods.  Proxies must be supported on the platform on which
+hk2 is running.  Constructor interception does NOT use proxies so these limitations do not extend to
+constructor injection.  Any method to be intercepted must be public, protected or package visibility.
+Private methods will not be intercepted.  Constructors to be intercepted can have any visibility.
+
+The proxies created for method interception (as opposed to those created for
+proxiable scopes) do not implement the [ProxyCtl][proxyctl] interface.  Instead they implement the
+[AOPProxyCtl][aopproxyctl] interface, which allows access to the underlying descriptor for the service
+whose instance was proxied.
+
+Interception in general is only supported when HK2 is constructing the services itself.  In particular
+services created via a [Factory][factory] can not use AOP nor can services that come from third-parties.
+Any constant service can not use interception as HK2 did not create the service.
+
+### Conclusion
+
+HK2 AOP can be used to solve many cross-cutting concerns.  Because it uses AOP Alliance interceptors
+the interceptors developed for other systems may be appropriate in HK2 as well.
+
+[aopalliance]: http://aopalliance.sourceforge.net/
+[methodinterceptors]: http://aopalliance.sourceforge.net/doc/org/aopalliance/intercept/MethodInterceptor.html
+[constructorinterceptors]: http://aopalliance.sourceforge.net/doc/org/aopalliance/intercept/ConstructorInterceptor.html
+[interceptionservice]: apidocs/org/glassfish/hk2/api/InterceptionService.html
+[factory]: apidocs/org/glassfish/hk2/api/Factory.html
+[activedescriptor]: apidocs/org/glassfish/hk2/api/ActiveDescriptor.html
+[builderhelper]: apidocs/org/glassfish/hk2/utilities/BuilderHelper.html
+[proxyctl]: apidocs/org/glassfish/hk2/api/ProxyCtl.html
+[aopproxyctl]: apidocs/org/glassfish/hk2/api/AOPProxyCtl.html
diff --git a/docs/api-overview.md b/docs/api-overview.md
new file mode 100644
index 0000000..182add5
--- /dev/null
+++ b/docs/api-overview.md
@@ -0,0 +1,363 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+* TOC
+{:toc}
+
+# API Overview
+
+## Compatibility
+
+This page describes the HK2 2.0 API, which was originally based on JSR-330 standard annotations.
+Also, Habitat has been replaced with a new interface called [ServiceLocator][servicelocator].
+
+## Introduction
+
+HK2 is a declarative framework for services using annotations like [@Contract][contract] and [@Service][service].
+However, it is possible to use programmatic APIs to precisely control the services and bindings available within the Services registry.
+
+## ServiceLocator
+
+ The most fundamental service in HK2 is the [ServiceLocator][servicelocator].
+ The [ServiceLocator][servicelocator] represents the registry where services
+ are looked up and where information about services (known as [Descriptors][descriptor]) are bound into the registry.
+ The [ServiceLocator][servicelocator] itself is represented as a service in its
+ own registry;  it is always the first service bound into its own registry.
+ 
+[ServiceLocators][servicelocator] are named uniquely in a JVM and each has a unique locator ID.
+It is possible to create or find [ServiceLocators][servicelocator] using the
+[ServiceLocatorFactory][servicelocatorfactory].
+The [ServiceLocatorFactory][servicelocatorfactory] will normally use a default
+implementation of [ServiceLocatorGenerator][servicelocatorgenerator] specified in META-INF/services.
+The default implementation can be changed by having a different META-INF/services 
+specification of the implementation of [ServiceLocatorGenerator][servicelocatorgenerator]
+earlier in the classpath than the provided implementation.
+An implementation of [ServiceLocatorGenerator][servicelocatorgenerator] can also
+be given directly to the [ServiceLocatorFactory][servicelocatorfactory] create method.
+
+Once you have created a [ServiceLocator][servicelocator] with the
+[ServiceLocatorFactory][servicelocatorfactory] it will contain at least three services:
+ 
+- Itself (see [ServiceLocator][servicelocator])
+- The default JSR-330 resolver (see [InjectionResolver][injectionresolver])
+- A service for configuring further services (see [DynamicConfigurationService][dynamicconfigurationservice])
+
+## Adding in your own services
+
+While the three services in your [ServiceLocator][servicelocator] are nice, they hardly constitute
+a useful system.  What is needed is all of your services, in order to make it useful.  Also please note that this section assumes that
+you are not using the upper level system that automatically reads in the descriptions of your services and populate
+[ServiceLocators][servicelocator] for you.  For information on how that system works see
+[here][gettingstarted].
+
+You add your own service by using the [DynamicConfigurationService][dynamicconfigurationservice].
+[DynamicConfigurationService][dynamicconfigurationservice] is one of the set of services automatically
+added to every [ServiceLocator][servicelocator].  You can get that service by simply looking
+it up:
+ 
+``` java
+    public void initialize() {
+        ServiceLocatorFactory factory = ServiceLocatorFactory.getInstance();
+        
+        ServiceLocator locator = factory.create("HelloWorld");
+        
+        DynamicConfigurationService dcs = locator.getService(DynamicConfigurationService.class);
+        
+        ...
+    }
+```
+
+You use the [DynamicConfigurationService][dynamicconfigurationservice] to create [DynamicConfiguration][dynamicconfiguration] instances.
+The [DynamicConfiguration][dynamicconfiguration] interface has a few methods for binding in descriptions of your services.
+ 
+In order to bind in services you need to first create a description of your service.  A description of your service
+gives information about the service, such as the name of the implementation class, and the name of the classes or
+interfaces which the service should be available to be looked up as, and other information.  In general, any implementation
+of [Descriptor][descriptor] can be used, but we have provided at least two mechanisms
+for creating [Descriptors][descriptor] that you might want to use.  We will go through
+those mechanisms in the next two sections, and then come back to adding in your own descriptor to your newly created [ServiceLocator][servicelocator].
+ 
+### BuilderHelper Binding EDSL
+
+An EDSL is an Embedded Domain Specific Language that allows you to build up objects specific to your particular domain.  In this
+case we provide an EDSL for building Descriptors.
+
+Lets take an example.  Suppose I wanted to tell the system about a service of mine that has implementation class
+com.acme.internal.WidgetImpl which implements the com.acme.Widget contract (interface) and which is in the
+PerLookup scope (which means a new instance of WidgetImpl will be provided for every injection point).  Here is how a descriptor
+that contains all of that information can be built up using our EDSL:
+ 
+``` java
+    public Descriptor createWidgetDescriptor() {
+        return BuilderHelper.link("com.acme.internal.WidgetImpl").
+                         to("com.acme.Widget").
+                         in("org.glassfish.api.PerLookup").
+                         build();
+    }
+```
+
+The [BuilderHelper][builderhelper] link method creates a [DescriptorBuilder][descriptorbuilder].
+The [DescriptorBuilder][descriptorbuilder] then creates more and more specific versions of itself
+as you fill in the data with calls to "to" or "in" or "qualifiedBy".
+
+Finally, when you are finished filling in all the details of your service, you call build in order to
+produce a [Descriptor][descriptor] that can be used in a bind call of [DynamicConfiguration][dynamicconfiguration].
+
+It is interesting to note that the build call of [DescriptorBuilder][descriptorbuilder] produces a [DescriptorImpl][descriptorimpl].
+A [DescriptorImpl][descriptorimpl] is nothing more than a convenience implementation of [Descriptor][descriptor] that has settable fields.
+Hence, if your code wanted to use the EDSL to produce a basic [Descriptor][descriptor] and then further customize it with the
+added methods of [DescriptorImpl][descriptorimpl] it could do so.
+ 
+### DescriptorImpl
+
+Rather than create your own implementation of [Descriptor][descriptor] we have provided
+an implementation of [Descriptor][descriptor] called [DescriptorImpl][descriptorimpl].
+This implementation has convenient methods for setting all of the fields of [Descriptor][descriptor].
+It should be noted that the bind API of [DynamicConfiguration][dynamicconfiguration]
+will make a deep copy of whatever [Descriptor][descriptor] is passed to it, and
+that the underlying implementation of the HK2 API never uses the [DescriptorImpl][descriptorimpl] class directly.
+It is purely there as a convenience class for those who wish to provide their own [Descriptors][descriptor].
+
+Here is an example that achieves the same [Descriptor][descriptor] as the example
+in the previous section but uses the [DescriptorImpl][descriptorimpl] to do it:
+ 
+``` java
+    public Descriptor createWidgetDescriptor() {
+        DescriptorImpl retVal = new DescriptorImpl();
+        
+        retVal.setImplementation("com.acme.internal.WidgetImpl");
+        retVal.addAdvertisedContract("com.acme.internal.WidgetImpl");
+        retVal.addAdvertisedContract("com.acme.Widget");
+        retVal.setScope("org.glassfish.api.PerLookup");
+        
+        return retVal;
+    }
+```
+
+One interesting thing to notice in the above code is that we added the implementation class as an advertisedContract.
+This was done automatically for us in the [BuilderHelper][builderhelper] case, but needed to be explicitly done in this case.
+ 
+### Binding a Descriptor into a ServiceLocator
+
+Now that we have seen two simple ways to create a [Descriptor][descriptor] lets take a
+look at how we bind that descriptor into our [ServiceLocator][servicelocator].
+Here is an example:
+ 
+``` java
+    public void initialize() {
+        ServiceLocatorFactory factory = ServiceLocatorFactory.getInstance();
+        
+        ServiceLocator locator = factory.create("HelloWorld");
+        
+        DynamicConfigurationService dcs = locator.getService(DynamicConfigurationService.class);
+        
+        DynamicConfiguration config = dcs.createDynamicConfiguration();
+        
+        config.bind(createWidgetDescriptor());
+        
+        config.commit();
+    }
+```
+
+The method createWidgetDescriptor is from the preceding examples.
+In the above code we call the createDynamicConfiguration method of [DynamicConfigurationService][dynamicconfigurationservice].
+This creates an instance of [DynamicConfiguration][dynamicconfiguration].
+To use a [DynamicConfiguration][dynamiccondfiguration] you call the bind or unbind methods until you
+are happy with the change and then you call commit to make the changes occur for real in the system.  If you do not call
+commit none of the changes you added to the [DynamicConfiguration][dynamicconfiguration] instance will be made to the system.
+ 
+That is all there is to it!  The services you add in this manner can now be looked up or injected into other services or
+generally manipulated through all of the other methods in [ServiceLocator][servicelocator].
+
+### Convenience methods for adding services
+
+There are several convenience methods that we have added to simplify the task of adding descriptors to a service
+locator.  These are encapsulated in the [ServiceLocatorUtilities][servicelocatorutilities] class.
+
+If you already have a service class and you would like for hk2 to automatically analyze the class and add
+it to a locator then you can use the [addClasses][addclasses] method.
+
+If you already have an instance of a service and you would like hk2 to automatically analyze the class of the
+service and add it to a locator then you can use the [addOneConstant][addoneconstant] method
+
+If you already have a descriptor for a service and you would like hk2 to add it to a locator then you can use
+the [addOneDescriptor][addonedescriptor] addOneDescriptor method
+ 
+### Looking up services
+
+There are several mechanisms for looking up services in HK2.  The simplest is to just call getService method of
+[ServiceLocator][servicelocator] with the class of the service you are interested in:
+ 
+``` java
+  Widget widget = locator.getService(Widget.class);
+```
+
+The type passed in can be any implementation class or interface with which the service was bound with as an advertisable
+contract.  If there is no Widget that can be found in the system then the getService method will return null.  If there
+are more than one Widget (e.g. Widget is an interface that can have many implementations) then the best Widget will
+be returned from the getService method.
+
+Services are sorted by (in order) the service ranking, the largest locator id
+(so that services in children are picked before services in parents) and
+smallest service id (so that older services are picked prior to newer
+services). 
+Therefore the best instance of a service is a service with the highest
+ranking or largest service locator id or the lowest service id.
+The ranking of a service is found in its [Descriptor][descriptor] and can be changed at any time at run time.
+The locator id of a service is a system assigned value for the [Descriptor][descriptor] when it is bound into the [ServiceLocator][servicelocator] and is the
+id of that [ServiceLocator][servicelocator].
+The service id of a service is a system assigned value for the [Descriptor][descriptor] when it is bound into the [ServiceLocator][servicelocator].
+The system assigned value is a monotonically increasing value.
+Thus if two services have the same ranking the best service will be associated with the oldest [Descriptor][descriptor] bound into the system.
+ 
+### Looking up services by name
+
+Services can be qualified in many ways, but the most common is to have a name associated with the service.  Hence, in
+our Widget example if there are several Widgets in the system but each has a different name we can find our particular
+Widget like this:
+
+``` java
+    public Widget getNamedWidget(String name) {
+        return locator.getService(Widget.class, name);
+    }
+```
+
+The given name is used to further qualify the specific Widget that was bound into the system.
+ 
+### Looking up services with qualifiers
+
+If your services have qualifiers you can look them up via the qualifiers.  In order to do this you can use 
+the [AnnotationLiteral][annotationliteral] in order to create concrete implementations of your annotations. 
+Lets see how this would be done.  Suppose you have a qualifier called Blue, defined like this:
+
+``` java
+@Qualifier
+@Retention(RUNTIME)
+@Target( { TYPE, METHOD, FIELD, PARAMETER })
+public @interface Blue {
+}
+```
+
+Normally you wouldn't implement Blue, but in this case you do need an implementation in order to be able to
+look it up.  You do that by providing an implement of Blue that extends [AnnotationLiteral][annotationliteral]:
+
+``` java
+public class BlueImpl extends AnnotationLiteral<Blue> implements Blue {
+}
+```
+
+You can now use this BlueImpl to look up your qualified Widget in a [ServiceLocator][servicelocator] like this:
+ 
+``` java
+    Widget widget = locator.getService(Widget.class, new BlueImpl());
+```
+
+This will get the Widget that has been qualified with @Blue.
+ 
+### Getting all services
+
+You may also want to get all of the services that have advertised a certain contract.  You can do this like this:
+ 
+``` java
+    List<Widget> widgetList = locator.getAllServices(Widget.class);
+```
+
+The list returned will have as many Widgets that could be found in the system.  It is important to note in this case that all
+of the Widgets will have been classloaded when you use this call, so if classloading performance is important to you be careful
+of using the getAllServices method.  Instead, consider using the getAllServiceHandles or getDescriptors method.
+ 
+### Getting service descriptors
+
+If you want to look up service descriptors rather than the services themselves you can use the getDescriptor or
+getBestDescriptor methods on [ServiceLocator][servicelocator].  The getDescriptor
+and getBestDescriptor methods will never cause classloading to occur, so it is safe to use in environments where
+classloading can be an issue.
+ 
+The getDescriptor methods on [ServiceLocator][servicelocator] use a [Fitler][filter] to determine which [Descriptors][descriptor] to return.
+You can implement your own [Filter][filter] or you can use one of the [Filter][filter] implementations provided by [BuilderHelper][builderhelper].
+The most common case is to use an [IndexedFilter][indexedfilter] provided by [BuildHelper][builderhelper], like this:
+ 
+```java
+  IndexedFilter widgetFilter = BuilderHelper.createContractFilter(Widget.class.getName());
+  
+  List<ActiveDescriptor<?>> widgetDescriptors = locator.getDescriptors(widgetFilter);
+```
+
+Using an [IndexedFilter][indexedfilter] can greatly improve the search time for your [Descriptors][descriptor].
+ 
+### Unmanaged Creation, Injection and Lifecycle
+
+There are times when you would like to have an object created, injected or have its lifecycle methods called by HK2, but
+not have that Object be explicitly managed by HK2.  The [ServiceLocator][serviceLocator] has methods that suit this case.
+These methods will inspect the class or object given and will attempt to perform the requested operations, without keeping track or managing
+those objects in any way.
+ 
+The first method is the create method, which will attempt to create an instance of the given class using the dependency injection
+rules of HK2:
+
+```java
+  Widget widget = locator.create(WidgetImpl.class);
+```
+
+It is important to note that the only references to other beans that will have been initialized when this returns are those necessary
+to perform constructor injection.  Hence any @Inject fields or @Inject initializer methods will NOT have been initialized when this
+method returns.
+ 
+If you already have an object, and would like for its @Inject fields and @Inject initializer methods to get filled in, you can
+use the inject method:
+
+```java
+  locator.inject(widget);
+```
+
+The object given will be analyzed and all of the fields and methods will be injected upon return.  However, any postConstruct
+method on the object will not have been called yet.  That can be done with the postConstruct method:
+ 
+```java
+  locator.postConstruct(widget);
+```
+
+This method call will find the postConstruct method on widget and call it.  Once the user is finished with the object, they can force
+the preDestroy to be called on it by using the preDestroy method:
+ 
+```java
+  locator.preDestroy(widget);
+```
+
+This sequence can be very useful when there is some special processing that needs to happen and the user does not want to have HK2 manage
+the objects themselves.
+ 
+[builderhelper]: apidocs/org/glassfish/hk2/utilities/BuilderHelper.html
+[servicelocator]: apidocs/org/glassfish/hk2/api/ServiceLocator.html
+[filter]: apidocs/org/glassfish/hk2/api/Filter.html
+[descriptor]: apidocs/org/glassfish/hk2/api/Descriptor.html
+[indexedfilter]: apidocs/org/glassfish/hk2/api/IndexedFilter.html
+[annotationlitteral]: apidocs/org/glassfish/hk2/AnnotationLiteral.html
+[dynamicconfigurationservice]: apidocs/org/glassfish/hk2/api/DynamicConfigurationService.html
+[dynamicconfiguration]: apidocs/org/glassfish/hk2/api/DynamicConfiguration.html
+[descriptorimpl]: apidocs/org/glassfish/hk2/utilities/DescriptorImpl.html
+[injectionresolver]: apidocs/org/glassfish/hk2/api/InjectionResolver.html
+[servicelocatorfactory]: apidocs/org/glassfish/hk2/api/ServiceLocatorFactory.html
+[servicelocatorgenerator]: apidocs/org/glassfish/extension/api/ServiceLocatorGenerator.html
+[descriptorbuilder]: apidocs/org/glassfish/hk2/utilities/DescriptorBuilder.html
+[contract]: apidocs/org/jvnet/hk2/annotations/Contract.html
+[service]: apidocs/org/jvnet/hk2/annotations/Service.html
+[annotationliteral]: apidocs/org/glassfish/hk2/api/AnnotationLiteral.html
+[servicelocatorutilities]: apidocs/org/glassfish/hk2/utilities/ServiceLocatorUtilities.html
+[addclasses]: apidocs/org/glassfish/hk2/utilities/ServiceLocatorUtilities.html#addClasses%28org.glassfish.hk2.api.ServiceLocator,java.lang.Class...%29
+[addoneconstant]: apidocs/org/glassfish/hk2/utilities/ServiceLocatorUtilities.html#addOneConstant%28org.glassfish.hk2.api.ServiceLocator,java.lang.Object%29
+[addonedescriptor]: apidocs/org/glassfish/hk2/utilities/ServiceLocatorUtilities.html#addOneDescriptor%28org.glassfish.hk2.api.ServiceLocator,org.glassfish.hk2.api.Descriptor%29
+[gettingstarted]: getting-started.html#Automatic_Service_Population
diff --git a/docs/configuration-example.md b/docs/configuration-example.md
new file mode 100644
index 0000000..337aa12
--- /dev/null
+++ b/docs/configuration-example.md
@@ -0,0 +1,624 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+* TOC
+{:toc}
+
+# Configuration Example
+
+This page shows an example of how to use the HK2 configuration service in order to inject
+values into HK2 services from a properties file.  It is designed to show how end users
+would interact with the system, and as such does not demonstrate how the internals of the
+configuration system interact with each other.
+
+The example itself is of a fake web server, which server has three ports it can open: an
+admin port, a SSL port and a normal HTTP port.  The SSL port and HTTP port can be dynamically
+changed while the web server is up and running, but the admin port cannot.  The web server
+can also be associated with one or more SSL certificates and private keys, which are themselves
+configured.  In this specific example the web server is associated with two SSL certificates.
+
+## The Web Server
+
+Lets first take a look at the Web Server.  The Web Server service implements this HK2 [Contract][contract]:
+
+```java
+@Contract 
+public interface WebServer {
+    /**
+     * Gets the name of this web server
+     */
+    public String getName();
+    
+    /**
+     * Opens the admin port, and returns the number
+     * of the port open
+     */
+    public int openAdminPort();
+    
+    /**
+     * Opens the SSL port, and returns the number
+     * of the port open
+     */
+    public int openSSLPort();
+    
+    /**
+     * Opens the non-SSL port, and returns the number
+     * of the port open
+     */
+    public int openPort();
+    
+    /**
+     * Gets the current admin port, or -1
+     * if the port is not open
+     */
+    public int getAdminPort();
+    
+    /**
+     * Gets the current SSL port, or -1
+     * if the port is not open
+     */
+    public int getSSLPort();
+    
+    /**
+     * Gets the current HTTP port, or -1
+     * if the port is not open
+     */
+    public int getPort();
+    
+    /**
+     * Gets the list of certificates that are
+     * used by this web server
+     * 
+     * @return A non-null but possibly empty set
+     * of Files pointing to the public certificates
+     * of the web server
+     */
+    public List<File> getCertificates(); 
+}
+```
+
+Several fields of the WebServer are meant to be configured from an external source.  In this example that source will be
+a properties file, which we will look at in detail later.  All the configuration properties of the WebServer are encapsulated
+in a WebServerBean, which you can see here:
+
+```java
+/**
+ * This bean describes a WebServer
+ */
+public class WebServerBean {
+    private String name;
+    private String address;
+    private int adminPort;
+    private int sslPort;
+    private int port;
+    
+    /**
+     * @return the name
+     */
+    public String getName() {
+        return name;
+    }
+    /**
+     * @param name the name to set
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+    /**
+     * @return the address
+     */
+    public String getAddress() {
+        return address;
+    }
+    /**
+     * @param address the address to set
+     */
+    public void setAddress(String address) {
+        this.address = address;
+    }
+    /**
+     * @return the adminPort
+     */
+    public int getAdminPort() {
+        return adminPort;
+    }
+    /**
+     * @param adminPort the adminPort to set
+     */
+    public void setAdminPort(int adminPort) {
+        this.adminPort = adminPort;
+    }
+    /**
+     * @return the sslPort
+     */
+    public int getSSLPort() {
+        return sslPort;
+    }
+    /**
+     * @param sslPort the sslPort to set
+     */
+    public void setSSLPort(int sslPort) {
+        this.sslPort = sslPort;
+    }
+    /**
+     * @return the port
+     */
+    public int getPort() {
+        return port;
+    }
+    /**
+     * @param sshPort the port to set
+     */
+    public void setPort(int port) {
+        this.port = port;
+    }
+}
+```
+
+The implementation of the WebServer contract is the WebServerImpl.  The WebServerImpl is in the @ConfiguredBy scope, and injects
+several fields from the WebServerBean.  The interesting parts of this code can be seen below.  You can find the full source for
+this code [here][webserverimpl].
+
+```java
+@Service @ConfiguredBy("WebServerBean")
+public class WebServerImpl implements WebServer {
+    @Configured
+    private String name;
+    
+    @Configured
+    private int adminPort;
+    private int openAdminPort = -1;
+    
+    @Configured(dynamicity=Configured.Dynamicity.FULLY_DYNAMIC)
+    private String address;
+    
+    private int sslPort;
+    private int openSSLPort = -1;
+    private int port;
+    private int openPort = -1;
+    
+    private boolean opened = false;
+    
+    /**
+     * These are configured services that can be used to get other
+     * variable information about the WebServer.  In this case
+     * it is getting information about the certificates that
+     * this server can use for SSL
+     */
+    @Inject
+    private IterableProvider<SSLCertificateService> certificates;
+    
+    /**
+     * This method is called to set the port and sshPort.  It is guaranteed that
+     * the server will not have these ports open at the time this method is called.
+     * That is guaranteed since the ports are not open until the postConstruct method
+     * is called on boot, and it is only called between the startDynamicConfiguration
+     * and finishDynamicConfiguration methods when a dynamic configuration change is
+     * made
+     * 
+     * @param sshPort The sshPort to use
+     * @param port The port to use
+     */
+    @SuppressWarnings("unused")
+    private void setUserPorts(
+            @Configured(value="SSLPort", dynamicity=Configured.Dynamicity.FULLY_DYNAMIC) int sslPort,
+            @Configured(value="port", dynamicity=Configured.Dynamicity.FULLY_DYNAMIC) int port) {
+        this.sslPort = sslPort;
+        this.port = port;
+        
+        if (opened) {
+            openSSLPort = sslPort;
+            openPort = port;
+        }
+    }
+    
+    @PostConstruct
+    private void postConstruct() {
+        opened = true;
+    }
+    
+    @PreDestroy
+    private void preDestroy() {
+        openPort = -1;
+        openSSLPort = -1;
+        openAdminPort = -1;
+    }
+    
+    // ... (uninteresting code)
+    
+    /* (non-Javadoc)
+     * @see org.glassfish.examples.configuration.webserver.WebServer#getCertificates()
+     */
+    @Override
+    public List<File> getCertificates() {
+        LinkedList<File> retVal = new LinkedList<File>();
+        
+        for (SSLCertificateService certService : certificates) {
+            retVal.add(certService.getCertificate());
+        }
+        
+        return retVal;
+    }
+}
+```
+
+The above implementation of the WebServer contract is an HK2 [Service][service], and it is in the [ConfiguredBy][configuredby] scope.  The
+[ConfiguredBy][configuredby] annotation requires the name of the type upon which instances of the service are based, in this case
+&quot;WebServerBean&quot;.  This implies that for every instance of the type &quot;WebServerBean&quot; found in the HK2 management
+[Hub][hub] a new instance of the WebServerImpl class will be created.  Lets now look at the interesting fields and methods of the
+WebServerImpl.
+
+The first configured parameter is a field called &quot;name&quot;.  In theory there could be several web servers configured, each with a different name.  In
+this example we don't do that, but the ability to do so is there.  The admin port is also configured, like this:
+
+```java
+    @Configured
+    private int adminPort;
+```
+
+By putting [@Configured][configured] on the field, that tells the HK2 configuration system to look for a getter named getAdminPort 
+on the bean, and to get the value for the adminPort from that property.  By the time the postConstruct method of the WebServerImpl
+has been called it is guaranteed that this field will have been filled in.  Notice that the [@Configured][configured] annotation did
+not take a value here, instead taking the name of the property from the name of the field.  In contrast consider this method, which
+sets the ssl and http ports of the server:
+
+```java
+    private void setUserPorts(
+            @Configured(value="SSLPort", dynamicity=Configured.Dynamicity.FULLY_DYNAMIC) int sslPort,
+            @Configured(value="port", dynamicity=Configured.Dynamicity.FULLY_DYNAMIC) int port) {
+        this.sslPort = sslPort;
+        this.port = port;
+        
+        if (opened) {
+            openSSLPort = sslPort;
+            openPort = port;
+        }
+    }
+```
+
+There are several interesting things to notice about this method.  One thing is that we had to put @Configured on all the parameters
+that were to come from beans.  If there had been other parameters on this method they would have been filled in with hk2 services
+like a normal hk2 initializer method. Another interesting thing is to notice that we set the dynamicity of the configured fields
+to FULLY_DYNAMIC.  This means that if either of these two fields change, this method will get called with the new values.  The
+dynamicity value of all @Configured annotated parameters on a method must be the same.  One other subtle thing to notice is that
+unlike a normal HK2 intialization method, this method can now get called AFTER the postConstruct method has been called.  In fact,
+this method works slightly different depending on whether it has been called before or after the postConstruct method.
+
+Any HK2 service can also injected into WebServerImpl.  This includes other configured services.  For example, in the WebServerImpl
+there is this injection point:
+
+```java
+    @Inject
+    private IterableProvider<SSLCertificateService> certificates;
+```
+
+Let us look in detail at the SSLCertificateService to more fully understand the above usage.
+
+## The SSLCertificateService
+
+SSLCertificateService is an HK2 service that deals with SSL certificates.  This is the full implementation of the service: 
+
+```java
+@Service @ConfiguredBy("SSLCertificateBean")
+public class SSLCertificateService {
+    @Configured("$bean")
+    private SSLCertificateBean certificateBean;
+    
+    /**
+     * Returns the location of the public certificate
+     * 
+     * @return The public certificate for this SSL service
+     */
+    public File getCertificate() {
+        return certificateBean.getCertificateLocation();
+    }
+
+}
+```
+
+Like the WebServerImpl this service is in the [@ConfiguredBy][configuredby] scope.  Instances of this service will be created for each instance
+of type &quot;SSLCertificateBean&quot; found in the [Hub][hub].  Look at the [@Configured][configured] injection point:
+
+```java
+    @Configured("$bean")
+    private SSLCertificateBean certificateBean;
+```
+
+In this case the [@Configured][configured] annotation has a value of &quot;$bean&quot;.  When a [@Configured][configured] annotation has a
+value of &quot;$bean&quot; it means to inject the whole bean rather than a value from the bean.  The code for the SSLCertificateBean will
+be found below in the discussion about how the property file is translated into beans.  Here is the injection point in the WebServerImpl:
+
+```java
+    @Inject
+    private IterableProvider<SSLCertificateService> certificates;
+```
+
+This injection point will be able to get all of the configured SSKCertificateService instances created.  So if there are two SSLCertificateBeans
+in the [Hub][hub] then this iterator will return two SSLCertificateServices.
+
+## Configuring the Services
+
+This example has a specific configuration that it will read and then modify to ensure that the system is working properly.  The initial
+property file for the example can be found here:
+
+```java
+WebServerBean.Acme.name=Acme
+WebServerBean.Acme.address=localhost
+WebServerBean.Acme.adminPort=7070
+WebServerBean.Acme.sslPort=81
+WebServerBean.Acme.port=80
+
+SSLCertificateBean.Corporate.certificateLocation=Corporatex509.cert
+SSLCertificateBean.Corporate.secretKeyLocation=Corporate.pem
+
+SSLCertificateBean.HR.certificateLocation=HRx509.cert
+SSLCertificateBean.HR.secretKeyLocation=HR.pem
+```
+
+The way the HK2 Properties interpreter works is that property keys have three parts, which is the type name followed by the instance name
+followed by the parameter name.  So the above properties file means to add an instance of the WebServerBean named &quot;Acme&quot; to the
+[Hub][hub] with the properties given.  Also add two instances of the SSLCertificateBean, one named &quot;Corporate&quot; and one
+named &quot;HR&quot; also with the given properties.
+
+Properties are generally strings, but the HK2 Properties interpreter is able to translate those strings to the types found in the associated
+JavaBeans.  This includes being able to translate the String if the type associated with that parameter name has a public constructor that
+takes a string.  For example, consider the SSLCertificateBean:
+
+```java
+public class SSLCertificateBean {
+    private File certificateLocation;
+    private File secretKeyLocation;
+    /**
+     * @return the certificateLocation
+     */
+    public File getCertificateLocation() {
+        return certificateLocation;
+    }
+    /**
+     * @param certificateLocation the certificateLocation to set
+     */
+    public void setCertificateLocation(File certificateLocation) {
+        this.certificateLocation = certificateLocation;
+    }
+    /**
+     * @return the secretKeyLocation
+     */
+    public File getSecretKeyLocation() {
+        return secretKeyLocation;
+    }
+    /**
+     * @param secretKeyLocation the secretKeyLocation to set
+     */
+    public void setSecretKeyLocation(File secretKeyLocation) {
+        this.secretKeyLocation = secretKeyLocation;
+    }
+}
+```
+
+The SSLCertificateBean has File as the type for both the &quot;secretKeyLocation&quot; and &quot;CertificateLocation&quot; parameters.  HK2
+knows how to translate the strings in the properties file because File has a public constructor that takes a string, which is what
+it uses to fill in the fields of this bean.
+
+In order to read the properties file into the [Hub][hub] this example uses the [PropertyFileService][propertyfileservice].
+The [PropertyFileService][propertyfileservice] is used to create [PropertyFileHandle][propertyfilehandle] instances.  This
+is how the test code reads the above property file into the [Hub][hub]:
+
+```java
+        Properties configuration = new Properties();
+        
+        URL configURL = getClass().getClassLoader().getResource("config.prop");
+        InputStream configStream = configURL.openConnection().getInputStream();
+        try {
+            // Read the property file
+            configuration.load(configStream);
+        }
+        finally {
+            configStream.close();
+        }
+        
+        // In order to read the Properties object into HK2 we need to get a PropertyFileHandle
+        PropertyFileService propertyFileService = locator.getService(PropertyFileService.class);
+        PropertyFileHandle propertyFileHandle = propertyFileService.createPropertyHandleOfAnyType();
+        
+        // Now read the configuration into hk2
+        propertyFileHandle.readProperties(configuration);
+```
+
+The reason for using a [PropertyFileHandle][propertyfilehandle] is because the handle keeps the state
+of the property file the last time it was read.  In this way if the property file is modified
+and read in again the propertyFileHandle would know which values had changed, which instances
+were added and which instances were removed (which is the difficult part of the whole
+thing!).
+
+## Dynamic changes
+
+In this example we simply modify the Properties object itself rather than reading a second file for
+simplicity.  This is the test code that changes the properties and then tells hk2 about the
+changes:
+
+```java
+        // Change the ports so that they look like this in the properties file:
+        // adminPort = 8082
+        // sslPort = 8081
+        // port = 8080
+        configuration.put("WebServerBean.Acme.adminPort", "8082");
+        configuration.put("WebServerBean.Acme.sslPort", "8081");
+        configuration.put("WebServerBean.Acme.port", "8080");
+        
+        // Tell hk2 about the change
+        propertyFileHandle.readProperties(configuration);
+```
+
+The propertyFileHandle will notice the changes and inform the [Hub][hub], which will then notify the backing
+WebServerImpl about the modified dynamic properties.  Even though the adminPort has changed the WebServerImpl
+will NOT be notified about that parameter changing because that field is NOT marked as being dynamic.
+
+## Initialization and setup
+
+In order to use the various parts of the HK2 configuration subsystem they must be initialized.  This is
+done via static methods on helper classes.  This is the test initialization code (junit @Before block):
+
+```java
+        // Enable HK2 service integration
+        ConfigurationUtilities.enableConfigurationSystem(locator);
+        
+        // Enable Properties service, to get service properties from a Properties object
+        PropertyFileUtilities.enablePropertyFileService(locator);
+```
+
+The [PropertyFileService][propertyfileservice] also needs the mapping from type name to Java Bean class.  In order
+to do this we must configure the [PropertyFileService][propertyfileservice] with a [PropertyFileBean][propertyfilebean].
+This is the code that maps the type named &quot;SSLCertificateBean&quot; to the SSLCertificateBean class and the
+type named &quot;WebServerBean&quot; to the WebServerBean class:
+
+```java
+        // The propertyFileBean contains the mapping from type names to Java Beans
+        PropertyFileBean propertyFileBean = new PropertyFileBean();
+        propertyFileBean.addTypeMapping("WebServerBean", WebServerBean.class);
+        propertyFileBean.addTypeMapping("SSLCertificateBean", SSLCertificateBean.class);
+        
+        // Add in the mapping from type name to bean classes
+        PropertyFileService propertyFileService = locator.getService(PropertyFileService.class);
+        propertyFileService.addPropertyFileBean(propertyFileBean);
+```
+
+The last thing to do in order to setup the environment is to tell HK2 about the backing HK2 services.  This is
+done with a simple call to addClasses:
+
+```java
+        // Add the test services themselves
+        ServiceLocatorUtilities.addClasses(locator,
+                SSLCertificateService.class,
+                WebServerImpl.class);
+```
+
+The @Before block of the test code has now setup HK2 for the test run.
+
+## Running the test
+
+This is the full test that shows that the WebServerImpl is properly running and gets the proper values from the
+properties file:
+
+```java
+    /**
+     * This test demonstrates adding and the modifying the http and
+     * ssl ports of the web server
+     */
+    @Test // @org.junit.Ignore
+    public void testDemonstrateWebServerConfiguration() throws IOException {
+        // Before we add a configuration there is no web server
+        WebServer webServer = locator.getService(WebServer.class);
+        Assert.assertNull(webServer);
+        
+        Properties configuration = new Properties();
+        
+        // Gets the URL of the configuration property file.  This
+        // file contains one web server and two SSL certificate
+        // configuration objects
+        URL configURL = getClass().getClassLoader().getResource("config.prop");
+        InputStream configStream = configURL.openConnection().getInputStream();
+        try {
+            // Read the property file
+            configuration.load(configStream);
+        }
+        finally {
+            configStream.close();
+        }
+        
+        // In order to read the Properties object into HK2 we need to get a PropertyFileHandle
+        PropertyFileService propertyFileService = locator.getService(PropertyFileService.class);
+        PropertyFileHandle propertyFileHandle = propertyFileService.createPropertyHandleOfAnyType();
+        
+        // Now read the configuration into hk2
+        propertyFileHandle.readProperties(configuration);
+        
+        // We should now have a web server!
+        webServer = locator.getService(WebServer.class);
+        Assert.assertNotNull(webServer);
+        
+        // Lets open all the ports, and check that they have the expected values
+        // In this case the ports are:
+        // adminPort = 7070
+        // sslPort = 81
+        // port = 80
+        Assert.assertEquals((int) 7070, webServer.openAdminPort());
+        Assert.assertEquals((int) 81, webServer.openSSLPort());
+        Assert.assertEquals((int) 80, webServer.openPort());
+        
+        // Now lets check that we have two SSL certificates
+        List<File> certs = webServer.getCertificates();
+        
+        // The two certificates should be Corporatex509.cert and HRx509.cert
+        Assert.assertEquals(2, certs.size());
+        
+        HashSet<String> foundCerts = new HashSet<String>();
+        for (File cert : certs) {
+            foundCerts.add(cert.getName());
+        }
+        
+        Assert.assertTrue(foundCerts.contains("Corporatex509.cert"));
+        Assert.assertTrue(foundCerts.contains("HRx509.cert"));
+        
+        // OK, we have verified that all of the parameters of the
+        // webserver are as expected.  We are now going to dynamically
+        // change all the ports.  In the webserver however only
+        // the ssl and http ports are dynamic, so after the change
+        // only the ssl and http ports should have their new values,
+        // while the admin port should remain with the old value
+        
+        // Change the ports so that they look like this in the properties file:
+        // adminPort = 8082
+        // sslPort = 8081
+        // port = 8080
+        configuration.put("WebServerBean.Acme.adminPort", "8082");
+        configuration.put("WebServerBean.Acme.sslPort", "8081");
+        configuration.put("WebServerBean.Acme.port", "8080");
+        
+        // Tell hk2 about the change
+        propertyFileHandle.readProperties(configuration);
+        
+        // Now lets check the web server, make sure the ports have been modified
+        
+        // The adminPort is NOT dynamic in the back end service, so it did not change
+        Assert.assertEquals(7070, webServer.getAdminPort());
+        
+        // But the SSL and HTTP ports have changed dynamically
+        Assert.assertEquals(8081, webServer.getSSLPort());
+        Assert.assertEquals(8080, webServer.openPort());
+    }
+```
+
+## Final thoughts
+
+This example is a simple demonstration of the HK2 configuration subsystem from an end-user perspective.  The end-users write
+HK2 services such as WebServerImpl and SSLCertificateService.  They annotate those services with [ConfiguredBy][configuredby]
+and [Configured][configured].  They can either be injected with parameters from beans or with the entire bean.
+
+The mechanism demonstrated in this example used a properties file that was read in using the [PropertyFileService][propertyfileservice].
+Any other mechanism can be used to add java beans to the [Hub][hub], making the persistence of the configuration
+data a pluggable mechanism.  Dynamic changes to fields are also supported.  More information about the HK2 configuration
+service can be found [here][configurationdoc].
+
+[webserverimpl]: https://github.com/hk2-project/hk2/blob/master/examples/configuration/webserver/src/main/java/org/glassfish/examples/configuration/webserver/internal/WebServerImpl.java
+[service]: apidocs/org/jvnet/hk2/annotations/ServiceLocator.html
+[contract]: apidocs/org/jvnet/hk2/annotations/Contract.html
+[configuredby]: apidocs/org/glassfish/hk2/configuration/api/ConfiguredBy.html
+[configured]: apidocs/org/glassfish/hk2/configuration/api/Configured.html
+[hub]: apidocs/org/glassfish/hk2/configuration/hub/api/Hub.html
+[propertyfileservice]: apidocs/org/glassfish/hk2/configuration/persistence/properties/PropertyFileService.html
+[propertyfilehandle]: apidocs/org/glassfish/hk2/configuration/persistence/properties/PropertyFileHandle.html
+[propertyfilebean]: apidocs/org/glassfish/hk2/configuration/persistence/properties/PropertyFileBean.html
+[configurationdoc]: configuration.html
diff --git a/docs/configuration-xml-example.md b/docs/configuration-xml-example.md
new file mode 100644
index 0000000..c4e439d
--- /dev/null
+++ b/docs/configuration-xml-example.md
@@ -0,0 +1,347 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+* TOC
+{:toc}
+
+# XML Configuration Example
+
+This page shows an example of how to use the HK2 XML configuration service in order to inject
+values into HK2 services from an XML file.
+
+The example itself is that of a fake application that can boot multiple web servers, 
+Each web server has three ports it can open: an admin port, a SSL port and a normal HTTP port.
+The SSL port and HTTP port can be dynamically changed while the web server is up and running, but the
+admin port cannot.  Individual web servers can be added and removed at runtime to the
+application.  Changes made dynamically at runtime can be written out to an XML file in order
+to save the current state of the application.
+
+### The XML Configuration File
+
+The application is to be configured with an XML file.  An example XML file is found in the
+src/test/resources directory of the example and is named webserverExample1.xml.
+It looks like this:
+
+```xml
+<application>
+  <web-server name="Development Server">
+    <adminPort>8001</adminPort>
+    <port>8002</port>
+    <SSLPort>8003</SSLPort>
+  </web-server>
+  
+  <web-server name="QA Server">
+    <adminPort>9001</adminPort>
+    <port>9002</port>
+    <SSLPort>9003</SSLPort>
+  </web-server>
+  
+  <web-server name="External Server">
+    <adminPort>10001</adminPort>
+  </web-server>
+</application>
+```
+
+## The Example Application
+
+This application will have three web servers started.  The properties of each of the servers is defined in the XML file.
+The HK2 XML Service uses JAXB to parse XML files.  In most JAXB applications the users must supply an
+annotated Java concrete class or use the automatically generated implementations JAXB can generate from schema.
+However the HK2 XML Service allows the user to use an interface annotated with JAXB annotations (and a few optional
+HK2 specific annotations) rather than a concrete Java class.  As an example, lets look at the WebServerBean, which
+is an interface that is annotated with JAXB annotations.  Comments have been removed for brevity.
+
+```java
+package org.glassfish.examples.configuration.xml.webserver;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.glassfish.hk2.xml.api.annotations.Hk2XmlPreGenerate;
+import org.glassfish.hk2.xml.api.annotations.XmlIdentifier;
+import org.jvnet.hk2.annotations.Contract;
+
+@Contract
+@Hk2XmlPreGenerate
+public interface WebServerBean {
+    @XmlAttribute(required=true)
+    @XmlIdentifier
+    public String getName();
+    public void setName(String name);
+    
+    @XmlElement
+    public String getAddress();
+    public void setAddress(String address);
+    
+    @XmlElement(defaultValue="1007")
+    public int getAdminPort();
+    public void setAdminPort(int adminPort);
+    
+    @XmlElement(name="SSLPort", defaultValue="81")
+    public int getSSLPort();
+    public void setSSLPort(int sslPort);
+    
+    @XmlElement(defaultValue="80")
+    public int getPort();
+    public void setPort(int port);
+}
+```
+
+XmlAttribute and XmlElement are standard JAXB annotations that would normally only go onto concrete classes.
+[XmlIdentifier][xmlidentifier] and [Hk2XmlPreGenerate][hk2xmlpregenerate] are HK2 extensions that will be 
+explained later.  The HK2 XML service will generate a proxy for this interface, copying over all annotations
+(and in some cases making slight modifications to them in order to ensure JAXB can parse the XML properly).
+[Contract][contract] is the standard HK2 annotation that denotes that this interface should be included when
+doing automatic service analysis.
+
+[XmlIdentifier][xmlidentifier] is an HK2 XML Service annotation that tells the HK2 XML Service that the attribute represented
+by the getter or setter can be used as the key for this bean when the bean is a child of another bean.
+It is very much like the JAXB annotation XmlID except that in the case of the XmlID the key must be unique
+within the scope of the entire document, whereas with XmlIdentifier the scope of uniqueness only needs
+to be within the xpath of the stanza.
+
+[Hk2XmlPreGenerate][hk2xmlpregenerate] is an HK2 XML Service annotation that tells HK2 that the proxy
+for this bean should be generated at build time and placed within the JAR being built.  This uses the
+standard JSR-269 annotation processor and so should work with most build systems including ant, maven,
+gradle and others.  The only requirement is that the HK2 XML Service jar be in the classpath of the compiler.
+Note that if the [Hk2XmlPreGenerate][hk2xmlpregenerate] annotation is NOT put on the interface class then the
+proxy will be generated dynamically at runtime, so using the [Hk2XmlPreGenerate][hk2xmlpregenerate] annotation
+is mainly a matter of runtime performance, since proxy generation can be a heavy operation.
+
+Lets take a look at the ApplicationBean, which has the WebServer bean as a child:
+
+```java
+package org.glassfish.examples.configuration.xml.webserver;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import org.jvnet.hk2.annotations.Contract;
+
+@Contract
+@XmlRootElement(name="application")
+public interface ApplicationBean {
+
+    @XmlElement(name="web-server")
+    public WebServerBean[] getWebServers();
+    public void setWebServers(WebServerBean[] webServers);
+    public void addWebServers(WebServerBean addMe);
+    public void removeWebServers(String removeMe);
+    public WebServerBean lookupWebServers(String findMe);
+
+}
+```
+
+The ApplicationBean has a standard JAXB getter and setter for the WebServerBean which is annotated with the
+JAXB standard annotation XmlElement.  Note that like all JAXB annotations the annotation can be placed
+on the setter method or the getter method.  Most JAXB annotations can also be placed on fields of concrete
+classes, but since this is an interface they are placed on either the getter or setter.  The
+methods addWebServers, removeWebServers and lookupWebServers are methods that the HK2 XML Service understands
+are part of the web-server family of methods and allows the users of the API to add, remove and
+locate WebServers.  The XmlRootElement annotation is a standard JAXB annotation that is placed on classes
+that can be at the root of the XML file.
+
+Note that in this example we chose to use an array type as the return from getWebServers and as the
+input to setWebServers but we could have also used a qualified java.util.List.
+
+NOTE:  At the current time there is no support for plurals.  This is a bug that should be fixed.
+
+## [XmlService][xmlservice]
+
+Now we need to parse our XML into these Java Beans.  To do this we use the [XmlService][xmlservice].
+You add the XmlService to any locator by using the method enableXmlService in
+[XmlServiceUtilities][xmlserviceutilities].
+
+The tests cases for this example use the [HK2Runner][hk2runner], which allows the test
+case itself (WebServerXmlTest.java) to directly inject the XmlService after the [HK2Runner][hk2runner]
+has been initialized.  The following junit @Before block initializes the [HK2Runner][hk2runner]
+and then initializes the [XmlService][xmlservice] using the [XmlServiceUtilities][xmlserviceutilities].
+
+```java
+    @Before
+    public void before() {
+        initialize();
+        
+        XmlServiceUtilities.enableXmlService(testLocator);
+    }
+```
+
+The testLocator is from the [HK2Runner][hk2runner] and is available after the initialize call,
+which is also responsible for injecting the [XmlService][xmlservice] provider so that it
+can be used by the individual tests:
+
+```java
+    @Inject
+    private Provider<XmlService> xmlServiceProvider;
+```
+
+We can now look at how to unmarshall the XML into the ApplicationBean in the first test
+in WebServerXmlTest:
+
+```java
+    @Test
+    public void testParseWebServerXmlFile() throws Exception {
+        XmlService xmlService = xmlServiceProvider.get();
+        
+        URI webserverFile = getClass().getClassLoader().getResource(EXAMPLE1_FILENAME).toURI();
+        
+        XmlRootHandle<ApplicationBean> applicationRootHandle =
+                xmlService.unmarshall(webserverFile, ApplicationBean.class);
+        
+        ApplicationBean root = applicationRootHandle.getRoot();
+        WebServerBean webservers[] = root.getWebServers();
+        
+        Assert.assertEquals(3, webservers.length);
+        
+        {
+            WebServerBean developmentServer = webservers[0];
+            Assert.assertEquals("Development Server", developmentServer.getName());
+            Assert.assertEquals(8001, developmentServer.getAdminPort());
+            Assert.assertEquals(8002, developmentServer.getPort());
+            Assert.assertEquals(8003, developmentServer.getSSLPort());
+        }
+        
+        {
+            WebServerBean qaServer = webservers[1];
+            Assert.assertEquals("QA Server", qaServer.getName());
+            Assert.assertEquals(9001, qaServer.getAdminPort());
+            Assert.assertEquals(9002, qaServer.getPort());
+            Assert.assertEquals(9003, qaServer.getSSLPort());
+        }
+        
+        {
+            WebServerBean externalServer = webservers[2];
+            Assert.assertEquals("External Server", externalServer.getName());
+            Assert.assertEquals(10001, externalServer.getAdminPort());
+            Assert.assertEquals(80, externalServer.getPort());
+            Assert.assertEquals(81, externalServer.getSSLPort());
+        }
+     }
+```
+
+The XML file has been unmarshalled into the ApplicationBean and into the three children WebServerBeans.
+Note that even the default values have been filled into the getPort and setSSLPort methods from
+the External Server WebServer, whose values were not specified directly in the XML file.
+
+The [XmlService][xmlservice] generated an [XmlRootHandle][xmlroothandle] which can be used to
+get at the root bean of the JavaBean tree.
+
+The example above illustrates one way to get the data from your XML configuration file and
+into your application, which is to directly use the root Java Bean that is produced from the
+[XmlRootHandle][xmlroothandle].  There are two other ways to get the data from your XML file
+into your application.  They are:
+
+1.  The individual Java Beans are put into the HK2 Service registry and so can be used like normal services
+2.  You can use the [ConfiguredBy][configuredby] scope to have HK2 services whose lifecycle is managed by the Java Bean tree
+
+The following two sections will explain each option.
+
+## Unmarshalled Java Beans as HK2 services
+
+When you unmarshall XML with the [XmlService][xmlservice] unmarshall method and the interfaces
+in the Java Bean tree are marked with [Contract][contract] then those beans will be
+added to the HK2 service registry.  If the Java Bean has a field marked with either
+[XmlIdentifier][xmlidentifier] or the standard JAXB XmlID annotation then the service
+will be put into the HK2 service registry with that field as its name.  So in this
+example three services would be put into the Service registry with contract
+WebServerBean, each one with a different name (&quot;Development Server&quot;,
+&quot;QA Server&quot; and &quot;External Server&quot;).
+
+The following example has a WebServerManager that injects an [IterableProvider][iterableprovider]
+of WebServerBean.  The named method of the [IterableProvider][iterableprovider] allows
+the WebServerManager to find the correct WebServerBean given the desired name.
+Here is the code for the WebServerManager:
+
+```java
+@Service
+public class WebServerManager {
+    @Inject
+    private IterableProvider<WebServerBean> allWebServers;
+    
+    /**
+     * Gets the WebServer bean with the given name, or null if
+     * none can be found with that name
+     * 
+     * @param name The non-null name of the web server to find in
+     * the HK2 service registry
+     * @return the WebServerBean HK2 service with the given name
+     */
+    public WebServerBean getWebServer(String name) {
+        return allWebServers.named(name).get();
+    }
+}
+```
+
+The test file for this use case is WebServersAsHK2ServicesTest and is mostly the
+same as the previous example.  In this case the test gets the WebServerManager
+service and uses that to query for WebServersBeans as HK2 services from
+the WebServerManager.  It then validates that the expected values for each
+WebServerBean are as expected:
+
+```java
+    @Test
+    public void testWebServerBeansAreHK2Services() throws Exception {
+        XmlService xmlService = xmlServiceProvider.get();
+        
+        URI webserverFile = getClass().getClassLoader().getResource(EXAMPLE1_FILENAME).toURI();
+        
+        XmlRootHandle<ApplicationBean> applicationRootHandle =
+                xmlService.unmarshall(webserverFile, ApplicationBean.class);
+        
+        WebServerManager manager = testLocator.getService(WebServerManager.class);
+        Assert.assertNotNull(manager);
+        
+        {
+            WebServerBean developmentServer = manager.getWebServer("Development Server");
+            Assert.assertEquals("Development Server", developmentServer.getName());
+            Assert.assertEquals(8001, developmentServer.getAdminPort());
+            Assert.assertEquals(8002, developmentServer.getPort());
+            Assert.assertEquals(8003, developmentServer.getSSLPort());
+        }
+        
+        {
+            WebServerBean qaServer = manager.getWebServer("QA Server");
+            Assert.assertEquals("QA Server", qaServer.getName());
+            Assert.assertEquals(9001, qaServer.getAdminPort());
+            Assert.assertEquals(9002, qaServer.getPort());
+            Assert.assertEquals(9003, qaServer.getSSLPort());
+        }
+        
+        {
+            WebServerBean externalServer = manager.getWebServer("External Server");
+            Assert.assertEquals("External Server", externalServer.getName());
+            Assert.assertEquals(10001, externalServer.getAdminPort());
+            Assert.assertEquals(80, externalServer.getPort());
+            Assert.assertEquals(81, externalServer.getSSLPort());
+        }
+    }
+```s
+
+Of course a service can always just use javax.inject.Named to inject a specific WebServerBean if
+wants to hard-code the name in the code.
+
+## An HK2 Service Per web-server XML stanza
+
+In the next example the system will generate a new WebServer for every web-server XML stanza
+in the file, and will inject that WebServer with the values found from that stanza.
+ 
+[xmlservice]: apidocs/org/glassfish/hk2/xml/api/XmlService.html
+[xmlserviceutilities]: apidocs/org/glassfish/hk2/xml/api/XmlServiceUtilities.html
+[hk2runner]: apidocs/org/jvnet/hk2/testing/junit/HK2Runner.html
+[xmlroothandle]: apidocs/org/glassfish/hk2/xml/api/XmlRootHandle.html
+[configuredby]:apidocs/org/glassfish/hk2/configuration/api/ConfiguredBy.html
+[contract]: apidocs/org/jvnet/hk2/annotations/Contract.html
+[xmlidentifier]: apidocs/org/glassfish/hk2/xml/api/annotations/XmlIdentifier.html
+[hk2xmlpregenerate]: apidocs/org/glassfish/hk2/xml/api/annotations/Hk2XmlPreGenerate.html
diff --git a/docs/configuration.md b/docs/configuration.md
new file mode 100644
index 0000000..d2720cf
--- /dev/null
+++ b/docs/configuration.md
@@ -0,0 +1,216 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+* TOC
+{:toc}
+
+# Configuration
+
+HK2 has an optional feature which allows configuration values specified in some format
+such as (but not limited to) XML or Properties files to be injected into HK2 services.
+
+## The parts
+
+The architecture of the HK2 configuration system consists of three parts.  These three parts are
+then combined to make the user experience simple and intuitive.  The three basic parts of the
+HK2 configuration system are:
+
+1.  Persistence (some external configuration format such as XML or properties)
+2.  Registry (a single JVM in-memory representation of Java Beans or bean-like maps)
+3.  HK2 service integration (injecting values into HK2 services)
+
+Each of these parts play a role in bringing configuration information into HK2 services.  The basic
+idea is that the persistence layer translates whatever external format the configuration has into
+JavaBeans and updates the registry.  The registry then notifies the HK2 service integration piece
+which either adds HK2 services or updates existing HK2 services with new values from the existing
+JavaBeans.
+
+Since it is the second part of the HK2 configuration system that serves as the basic abstraction
+layer it shall be described first.
+
+## The HK2 Configuration Registry
+
+The HK2 Configuration Registry is an in-memory registry of JavaBeans (or bean-like maps).  Instances
+are organized by a type, and then further by instance names.  It is usually the case that all instances
+of the same type have the same java type, and the same set of parameters.  Instance names can either
+be a field from the bean or can be calculated some other way.  The combination of type name and
+instance name will always uniquely identify a particular instance.
+
+The main API for working with the Registry is the [Hub][hub].  The [Hub][hub] is an HK2 service that
+can be added to a [ServiceLocator][servicelocator] with the enableConfigurationHub method of the
+[ManagerUtilities][managerutilities] class.
+
+The current [BeanDatabase][beandatabase] can be gotten from the [Hub][hub]. A 
+[WriteableBeanDatabase][writeablebeandatabase] which allows changes to the [BeanDatabase][beandatabase]
+is available from the [Hub][hub].  [BeanDatabaseUpdateListener][beandatabaseupdatelistener] implementations
+can be registered with the [Hub][hub] to keep track of the current state of the configuration registry.
+
+Those creating a module that is providing configuration from some backing store into the registry will
+most often be working with the [BeanDatabase][beandatabase] and [WriteableBeanDatabase][writeablebeandatabase]
+API.  The HK2 service integration part of the HK2 configuration feature sets itself up as a
+[BeanDatabaseUpdateListener][beandatabaseupdatelistener] in order to provision HK2 services with configuration
+data.  However there may be other uses for a [BeanDatabaseUpdateListener][beandatabaseupdatelistener].
+
+## HK2 Service Integration
+
+The HK2 service integration layer takes JavaBean instances from the Hub and creates an HK2 service per instance
+of the type.  It does this by setting itself up as a [BeanDatabaseUpdateListener][beandatabaseupdatelistener]
+on the [Hub][hub].  HK2 mark themselves as being configured by a specific type by putting themselves into
+the [ConfiguredBy][configuredby] scope.  This is the definition of the [ConfiguredBy][configuredby] scope
+annotation:
+
+```java
+@Scope
+@Retention(RUNTIME)
+@Target(TYPE)
+public @interface ConfiguredBy {
+    /** The type to be associated with this service */
+    public String value();
+    
+    /** * Specifies the creation policy for configured services */
+    public CreationPolicy creationPolicy() default CreationPolicy.ON_DEMAND;
+    
+    public enum CreationPolicy {
+        /**
+         * Instances of services with this policy will
+         * be created when some user code creates explicit
+         * demand for the service.  This is similar to most
+         * other hk2 services
+         */
+        ON_DEMAND,
+        
+        /**
+         * Instances of services with this policy will
+         * be created as soon as their backing instances
+         * become available
+         */
+        EAGER
+    }
+}
+```
+
+HK2 services in the [ConfiguredBy][configuredby] scope are normal HK2 services in that they can have normal
+injection points and have all the other features of an HK2 service.  They are also able to inject configuration
+data into fields, constructors or methods that are annotated with [Configured][configured].  There will be one
+instance of the HK2 service created for each instance of the type in the [BeanDatabase][beandatabase].  Each
+instance of the HK2 service will have a name equal to the name of the instance in the [BeanDatabase][beandatabase]
+upon which it is based.
+
+Any field or parameter annotated with [Configured][configured] will be injected with a value from the JavaBean instance
+in the [BeanDatabase][beandatabase] upon which this instance of the HK2 service is based.  This is the definition of
+the [Configured][configured] annotation:
+
+```java
+@Retention(RUNTIME)
+@Target( { FIELD, PARAMETER })
+@InjectionPointIndicator
+public @interface Configured {
+    public final static String BEAN_KEY = "$bean";
+    
+    /**
+     * The name of the field in the java bean or
+     * bean-like map to use for injecting into
+     * this field or parameter
+     */
+    public String value() default "";
+    
+    /**
+     * Describes how dynamic a configured field or parameter must be.
+     * All parameters of a constructor must be STATIC.
+     * All parameters of a method must have the same dynamicity value
+     * 
+     * @return The dynamicicty of this field or parameter
+     */
+    public Dynamicity dynamicity() default Dynamicity.STATIC;
+    
+    /**
+     * Describes how dynamic a configured field or parameter should be
+     */
+    public enum Dynamicity {
+        /** This value should not automatically change over the life of the service instance */
+        STATIC,
+        /** This value can change at any time during the life of the service instance */
+        FULLY_DYNAMIC
+    }
+
+}
+```
+
+When placed on a java Field the name of the parameter can come from the name of the field.  However, when placed
+on a parameter of a constructor or a method the [Configured][configured] value field must be filled in with
+the name of the parameter from the JavaBean to use.  If the parameter name is &quot;$bean&quot; then the parameter
+or field will take the whole bean as its value.
+
+Fields and methods that have parameters marked with [Configured][configured] can opt in to having those values
+changed dynamically when the corresponding parameter in the JavaBean is modified.
+
+An HK2 service can also mark methods to run before and after dynamic changes are taking place, and it can also
+implement the java.beans.PropertyChangeListener interface.  To mark a method to run prior to dynamic changes
+being made use the [PreDynamicChange][predynamicchange] annotation on a method:
+
+```java
+@Retention(RUNTIME)
+@Target(METHOD)
+public @interface PreDynamicChange {
+}
+```
+
+To mark a method to run after dynamic changes are complete use the [PostDynamicChange][postdynamicchange] annotation
+on a method:
+
+```java
+@Retention(RUNTIME)
+@Target(METHOD)
+public @interface PostDynamicChange {
+}
+```
+
+The methods marked with [PreDynamicChange][predynamicchange] or [PostDynamicChange][postdynamicchange] can take
+zero parameters or a single parameter that is a List&lt;PropertyChangeListener&gt;.  If the List version is used
+the List will contain the full set of dynamic changes that took place in a single [BeanDatabase][beandatabase]
+operation.  Furthermore, the [PreDynamicChange][predynamicchange] can optionally return a boolean value.  If
+it does return a boolean value and that boolean value is false, then any fields marked as being dynamic will NOT
+get updated.
+
+The HK2 service integration part of the HK2 configuration system can be enabled using the enableConfigurationSystem
+method of the [ConfigurationUtilities][configurationutilities] class.
+
+## Configuration Persistence
+
+The persistence layer isn't a layer so much as a set of plugins that take configuration data from some form (usually
+persistent) and tranlate it into JavaBeans or bean-like maps.  Those JavaBeans or bean-like maps are then
+placed into the [Hub][hub].  There can be multiple providers providing the input, or some providers can be used
+in some scenarios while others are used in other scenarios.  For example, a central server could read the configuration
+from an XML file while remote clients could have a network plugin that receive the configuration from the central
+server.
+
+At the time of writing HK2 provides a provider that reads property files.  There may be other providers that
+are added as well (i.e., one that reads XML data).
+
+## The HK2 Properties Configuration provider
+
+This space is under construction
+
+[hub]: apidocs/org/glassfish/hk2/configuration/hub/api/Hub.html
+[servicelocator]: apidocs/org/glassfish/hk2/api/ServiceLocator.html
+[managerutilities]: apidocs/org/glassfish/hk2/configuration/hub/api/ManagerUtilities.html
+[beandatabase]: apidocs/org/glassfish/hk2/configuration/hub/api/BeanDatabase.html
+[writeablebeandatabase]: apidocs/org/glassfish/hk2/configuration/hub/api/WriteableBeanDatabase.html
+[beandatabaseupdatelistener]: apidocs/org/glassfish/hk2/configuration/hub/api/BeanDatabaseUpdateListener.html
+[configuredby]: apidocs/org/glassfish/hk2/configuration/api/ConfiguredBy.html
+[configured]: apidocs/org/glassfish/hk2/configuration/api/Configured.html
+[predynamicchange]: apidocs/org/glassfish/hk2/configuration/api/PreDynamicChange.html
+[postdynamicchange]: apidocs/org/glassfish/hk2/configuration/api/PostDynamicChange.html
diff --git a/docs/ctm-example.md b/docs/ctm-example.md
new file mode 100644
index 0000000..32018d3
--- /dev/null
+++ b/docs/ctm-example.md
@@ -0,0 +1,322 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+# Tenant Managed Scope Example
+
+This example illustrates how a scope can be made that is tenant aware.  First, lets define a tenant.
+
+A tenant is a an entity who has certain attributes that are backed by an XML configuration file.
+The XML configuration file will contain all the information about that tenant.
+For example, this XML contains all the data about a Tenant named Alice
+ 
+```xml
+<environments>
+    <environment name="Alice" minSize="1" maxSize="2" />
+</environments>
+```
+
+ This XML contains all the data about a tenant named Bob
+ 
+```xml
+<environments>
+    <environment name="Bob" minSize="10" maxSize="20" />
+</environments>
+```
+
+ The CTM team would like to have an interface called Environment that encapsulates all the information about a tenant:
+
+```java
+public interface Environment {
+    String getName();
+    int getMinSize();
+    int getMaxSize();
+}
+```
+
+  There is code in the system that would like to inject the Environment class.  However, the code that will inject
+  this interface is in the Singleton scope, which means it never changes.  And yet, depending on the state of the system
+  the underlying tenant may change from Alice to Bob, or to any other tenant.  For example, the class could look like
+  this:
+  
+```java
+@Singleton
+public class ServiceProvisioningEngine {
+
+   @Inject
+   private Environment tenant;
+
+   private void provisionServices() {
+       //envs here could be  either env1   or  env2 depending on
+       //   whether this code is being executed on behalf of either tenant1 OR tenant2
+   }
+
+}
+```
+
+We would like to demonstrate how a custom scope, called the TenantScope, can be used to solve this problem.  Firstly, in order
+to solve the problem of the Singleton service getting injected with the Environment only at construction time, we must have HK2
+inject a proxy for the Environment service rather than the particular environment itself.  The proxy can figure out, depending
+on the state of the system, which tenant is active, and then use the proper Environment object for the real call.  In order to
+ensure that this proxy is created, the TenantScope must be Proxiable.  You mark a scope as being Proxiable by adding the @Proxiable
+annotation to the definition of the scope annotation itself, like this:
+
+```java
+@Scope
+@Proxiable
+@Retention(RUNTIME)
+@Target( { TYPE, METHOD })
+public @interface TenantScoped {
+}
+```
+ 
+This annotation is now marked as a scope indicator (via the @Scope annotation) and as proxiable (via the @Proxiable annotation).  All
+objects that are injected from this scope will be given a proxy that uses the underlying machinery to determine the state of the system
+and to use the proper backing objects for the real calls.
+
+Now, however, we need some way to tell the system what tenant is currently active.  For this example, we have created a
+class called the TenantManager.  The TenantManager is in the Singleton scope which means it will only be created once (when the first
+person demands one).  The job of the TenantManager is to be able to set the currently active tenant.  It does so with this call:
+ 
+```java
+@Service
+public class TenantManager {
+    private String currentTenant;
+    
+    public void setCurrentTenant(String currentTenant) {
+        this.currentTenant = currentTenant;
+    }
+    
+    public String getCurrentTenant() {
+        return currentTenant;
+    }
+}
+```
+
+OK, great, now we know how to change the current tenant that is running on the system.  But how do we make the system understand this?
+Well, since we decided that we were going to have a proxiable scope, we also need a corresponding implementation of the Context interface.
+You do this by implementing Context, and making sure that the parameterized type of the Context is the class of the scope annotation.
+In this case, we would implement the context for the TenantScope scope like this:
+ 
+```java
+@Singleton
+public class TenantScopedContext implements Context<TenantScoped> {
+    @Inject
+    private TenantManager manager;
+    ...
+```
+
+Note that the implementation of Context is itself a service, in the Singleton scope (there is nothing that says a Context must be
+in the Singleton scope, but most probably would be).  The only rule is that a Context implementation cannot be in the same scope as
+the scope it is backing.  Also notice that since Context is a regular service that it can be injected with other services, such
+as the TenantManager.  Luckily, that is just what we need, since the TenantManager knows what the current scope is!  First, lets
+see what the implementation of the isActive method of the TenantScopedContext would look like:
+ 
+```java
+    public boolean isActive() {
+        return manager.getCurrentTenant() != null;
+    }
+```
+
+That was pretty easy.  But now lets think about what the TenantScopeContext has to do.  It must keep the set of objects created
+per tenant.  For example, we do not want to create the Environment implementation for the Alice tenant more than once.  And
+so the TenantScopeContext keeps a mapping for each tenant.  Here is the map, and the code that gets the proper mapping based
+on the current tenant:
+ 
+```java
+    private final HashMap<String, HashMap<ActiveDescriptor<?>, Object>> contexts = new HashMap<String, HashMap<ActiveDescriptor<?>, Object>>();
+    
+    private HashMap<ActiveDescriptor<?>, Object> getCurrentContext() {
+        if (manager.getCurrentTenant() == null) throw new IllegalStateException("There is no current tenant");
+        
+        HashMap<ActiveDescriptor<?>, Object> retVal = contexts.get(manager.getCurrentTenant());
+        if (retVal == null) {
+            retVal = new HashMap<ActiveDescriptor<?>, Object>();
+            
+            contexts.put(manager.getCurrentTenant(), retVal);
+        }
+        
+        return retVal;
+    }
+```
+
+Based on this code, it is now easy to write the find method of the TenantScopedContext:
+ 
+```java
+    public <T> T find(ActiveDescriptor<T> descriptor) {
+        HashMap<ActiveDescriptor<?>, Object> mappings = getCurrentContext();
+        
+        return (T) mappings.get(descriptor);
+    }
+```
+
+The method that does findOrCreate is also fairly simple to write now.  If it cannot find the service in the mapping
+for this tenant, then it must create one using the create method of the ActiveDescriptor, passing in the root.  The
+passing in of the root allows for objects of scope PerLookup to be destroyed properly when this object gets destroyed.
+    
+```java
+    public <T> T findOrCreate(ActiveDescriptor<T> activeDescriptor,
+            ServiceHandle<?> root) {
+        HashMap<ActiveDescriptor<?>, Object> mappings = getCurrentContext();
+        
+        Object retVal = mappings.get(activeDescriptor);
+        if (retVal == null) {
+            retVal = activeDescriptor.create(root);
+            
+            mappings.put(activeDescriptor, retVal);
+        }
+        
+        return (T) retVal;
+    }
+```
+
+That is it for writing the Context implementation for the TenantScope!  At this point, objects will be created in the
+tenant scope only when no object has already been created for that tenant.  And when a tenant is switched, a new mapping
+is generated and we start the process all over again.
+
+That is all well and good, but the question of how these objects are truly created for the TenantScope is still unclear.  For example,
+we need for the Alice Environment implementation to be produced when the Alice tenant is active, and we need the Bob Environment
+to be produced when the Bob tenant is active.
+
+In order to achieve this goal, we create a factory of Environments.  A factory can be used to create objects when some criteria
+that cannot be easily expressed as an injection point needs to be taken into account.  Factories
+can produce things into any scope and with any qualifiers.  The Factory interface has a method on it called produce(), which
+can be annotated with the scope and qualifiers that are to be associated with the produced objects.
+
+We then implement an EnvironmentFactory, giving the type we are producing as the actual type in the parameterized type, like this:
+
+```java
+@Singleton
+public class EnvironmentFactory implements Factory<Environment> {
+    @Inject
+    private TenantManager manager;
+    
+    ...
+}
+```
+
+It is interesting to notice that the factory itself is a service in the Singleton scope, and hence can be injected with the
+TenantManager.  However, that does not mean that the EnvironmentFactory is producing objects into the Singleton scope, only that the
+factory itself is in the Singleton scope.  We tell the system that this factory is producing items for the TenantScope by annotating
+the produce method, like this:
+
+```java
+    @TenantScoped
+    public Environment provide() {...}
+```
+
+In this example, we are going to use other ServiceLocator registry's in order to create the specific Environment objects that we need.
+We will have a new ServiceLocator registry for each tenant, and that new ServiceLocator will be responsible for instantiating
+and providing the Environment implementations that we require.
+
+ServiceLocators will be used as delegate for Habitat to create config instance of Environments based on a
+particular backing XML file, using the configuration subsystem of hk2.
+
+Thus the job of the EnvironmentFactory is to keep a map from tenants to their backing ServiceLocator registries.  Here is
+the mapping and the code that associates a particular ServiceLocator with the current tenant:
+ 
+```java
+    private final HashMap<String, ServiceLocator> backingLocators = new HashMap<String, ServiceLocator>();
+    private final TenantLocatorGenerator generator = new TenantLocatorGenerator();
+    
+    private ServiceLocator getCurrentLocator() {
+        if (manager.getCurrentTenant() == null) throw new IllegalStateException("There is no current tenant");
+        
+        ServiceLocator locator = backingLocators.get(manager.getCurrentTenant());
+        if (locator == null) {
+            locator = createNewLocator();
+            backingLocators.put(manager.getCurrentTenant(), locator);
+        }
+        
+        return locator;
+    }
+    
+    private ServiceLocator createNewLocator() {
+        return generator.generateLocatorPerTenant(manager.getCurrentTenant());
+    }
+```
+
+The job of the TenantLocatorGenerator is to create a new ServiceLocator based on the current tenant and populate it
+with values from a backing XML file.
+ 
+```java
+        ServiceLocator serviceLocator = factory.create(tenantName, parent);
+
+        // Will add itself to serviceLocator by tenantName
+        Habitat h = new Habitat(null, tenantName);
+        
+        // Populate this serviceLocator with config data.
+        for (Populator p : serviceLocator.<Populator>getAllServices(Populator.class)) {
+            p.run(new ConfigParser(h));
+        }
+```
+
+Then it is necessary to implement Populator service, as follows below. Note, Habitat is backed by ServiceLocator for tenant.
+ 
+```java
+		@Service
+		public class EnvironmentXml implements Populator {
+		    @Inject
+		    TenantManager tenantManager;
+		
+		    @Inject
+		    protected Habitat habitat;
+		
+		    @Override
+		    public void run(ConfigParser parser) throws ConfigPopulatorException {
+		        String tenantName = tenantManager.getCurrentTenant();
+		        URL source = URL<tenantName.xml>
+		        parser.parse(source, new DomDocument(habitat));
+		    }
+		
+		}
+```
+  
+The code of the produce method in the EnvironmentFactory is now straightforward:
+
+```java
+    @TenantScoped
+    public Environment provide() {
+        ServiceLocator locator = getCurrentLocator();
+        
+        return locator.getService(Environment.class);
+    }
+```
+
+Voila!  We have a fairly simple example of how to create a TenantContext that meets the original requirements.  We have
+created a TenantScope/TenantContext pair, and made sure it only creates objects when no object already exists for a certain
+tenant.  We have also seen how to write a factory which knows how to produce Environment objects based on the currently
+active tenant. 
+ 
+Now, lets take a look at the test, and how the test validates the original requirement, which was that the
+ServiceProviderEngine should be using the proper tenant based on the current state of the system, without having
+to be re-injected.  Here is the pseudo-code for the test:
+ 
+```java
+    TenantManager tenantManager = locator.getService(TenantManager.class);
+    ServiceProviderEngine engine = locator.getService(ServiceProviderEngine.class);
+        
+    tenantManager.setCurrentTenant(TenantLocatorGenerator.ALICE);
+        
+    // Validate that the engine is using the ALICE tenant
+        
+    tenantManager.setCurrentTenant(TenantLocatorGenerator.BOB);
+        
+    // Validate that the engine is using the BOB tenant
+```
+
+The point of the test is to ensure that the Environment object passed into the ServiceProviderEngine is in fact getting switched
+when we switch the tenant from Alice to Bob.
+
diff --git a/docs/custom-resolver-example.md b/docs/custom-resolver-example.md
new file mode 100644
index 0000000..6e8515d
--- /dev/null
+++ b/docs/custom-resolver-example.md
@@ -0,0 +1,413 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+* TOC
+{:toc}
+
+# Custom Injection Resolver Example
+
+## Custom Injection Resolution
+
+This directory contains an example that illustrates how to write a custom injection resolver.
+
+A custom injector allow users to define their own injection annotation, or to customize in some way the system
+injection resolver that does the JSR-330 standard resolution.  In this example, we will define our own
+injection resolver which customizes the JSR-300 standard one, but supplies the ability to get more information
+out of annotations on the parameter of a method.
+
+In this use case, we want to have a method that can be injected, and which can annotate parameters of the method
+to determines the value that parameter should take.  The real value will end up coming from an index
+into the data of an HttpRequest.  Here is an example of a method that uses this custom injector, from the
+HttpEventReceiver class:
+
+```java
+    @AlternateInject
+    public void receiveRequest(
+            @HttpParameter int rank,
+            @HttpParameter(1) long id,
+            @HttpParameter(2) String action,
+            Logger logger) {
+       //...
+    }
+```
+
+The method receiveRequest takes the parameters rank, id, action and logger.  But the determination of what value rank, id and
+action should take will be determined by the index in the HttpParameter annotation.  Here is the definition of HttpParameter:
+
+```java
+@Retention(RUNTIME)
+@Target( { PARAMETER })
+public @interface HttpParameter {
+    /** The index  number of the parameter to retrieve */
+
+   public int value() default 0;
+}
+```
+
+The logger parameter of the receiveRequest method is just another service.  This service will come from the normal JSR-330
+resolver, but the other parameters will be determined from the HttpParameter annotation.  The determination of
+what the values should take comes from an object called the HttpRequest, which does nothing but store strings in certain indexes.
+The HttpRequest object itself is in the RequestScope context, which means its values will change depending on what request
+is currently active.  In order to do that, the RequestScope context is a Proxiable context.  We will see more about creating
+the RequestScoped context later in this document.
+
+For now, lets look at how we define the **@AlternateInject** annotation.  An injection annotation is valid on fields, methods,
+parameters of methods,
+constructors and parameters of constructors.  However, in this case the **@AlternateInject** is only supported for methods, so
+the definition of **@AlternateInject** looks like this:
+
+```java
+@Retention(RUNTIME)
+@Target( { METHOD })
+@InjectionPointIndicator
+public @interface AlternateInject {
+}
+```
+
+When providing a custom injection annotation, you must also provide an implementation of the
+[InjectionResolver][injectionresolver] interface.  It is this
+implementation that will be called whenever HK2 wants to inject into a constructor or field or method
+that is annotated with the custom injection annotation.  The actual type of the parameterized type of
+the [InjectionResolver][injectionresolver] implementation must be
+the custom injection annotation.
+
+The annotation [InjectionPointIndicator][injectionpointindicator] can
+optionally be placed on the custom annotation.  Using this annotation
+allows the automatic analysis of a class with custom injection
+annotations prior to the registration of the associated [InjectionResolver][injectionresolver].
+
+Here is how the AlternateInjectionResolver is defined:
+
+```java
+@Singleton
+public class AlternateInjectResolver implements InjectionResolver<AlternateInject> {
+    //...
+}
+```
+
+Implementations of [InjectionResolver][injectionresolver] are registered
+with HK2 like any other service, and like any other service they may be injected with other services in the system.
+The AlternateInjectResolver is in the @Singleton context, which is the usual context for implementations of
+[InjectionResolver][injectionresolver].  In general however implementations of [InjectionResolver][injectionresolver] may be in any context.
+Implementations of [InjectionResolver][injectionresolver] may not use the custom injection
+annotations that they themselves are defining to inject things into themselves.
+
+Implementations of [InjectionResolver][injectionresolver] that want
+to customize the default JSR-330 system provided injector can do so by injecting the default JSR-330 system provided
+injector.  The AlternateInjectionResolver does just that:
+
+```java
+public class AlternateInjectResolver implements InjectionResolver<AlternateInject> {
+    @Inject @Named(InjectionResolver.SYSTEM_RESOLVER_NAME)
+    private InjectionResolver<Inject> systemResolver;
+}
+```
+
+The system JSR-330 injection resolver is put into the registry with a specific name so that other injection resolvers
+can easily inject it using the @Named annotation.
+
+Now we need to write the resolve method from [InjectionResolver][injectionresolver].
+We can get the current method we are injecting into from the passed in [Injectee][injectee], and from that we can tell whether or not any particular
+parameter of the method has the @HttpParameter annotation.  But what happens when a parameter does have the
+@HttpParameter annotation?
+
+In that case, the real data should come from the underlying HttpRequest object.  The HttpRequest object is a very simple
+object that stores strings at certain indexes:
+
+```java
+@RequestScope
+public class HttpRequest {
+    public String getPathElement(int index) {...}
+
+    public void addElement(String element) {...}
+}
+```
+
+Because this is a request scoped object, the underlying values will change whenever the request has changed.  So our
+AlternateInjectResolver can inject an HttpRequest object and use it to get values whenever it detects an
+@HttpParameter annotation on a parameter of the method.  This is a code snippet from AlternateInjectResolver:
+
+```java
+public class Foo {
+    @Inject
+    private HttpRequest request;
+
+    public Object resolve(Injectee injectee, ServiceHandle<?> root) {
+        //...
+
+        Annotation annotations[] = method.getParameterAnnotations()[injectee.getPosition()];
+        HttpParameter httpParam = getHttpParameter(annotations);
+        if (httpParam == null) {
+            return systemResolver.resolve(injectee, root);
+        }
+
+        int index = httpParam.value();
+        String fromRequest = request.getPathElement(index);
+
+        //...
+    }
+}
+```
+
+In the above code snippet the resolve method looks for an HttpParameter annotation on the particular parameter being
+injected.  If it does not find such an annotation it simply lets the system injection resolver do the resolution.
+Otherwise, it gets the value from the injected HttpRequest.
+
+But that is not the end of the story.  The values that get injected into can be of type int, long or String.  The
+resolve method can determine the type that is required to be returned, and ensure that it does the correct conversion
+before returning the object.  Here is how that code works:
+
+```java
+    Class<?> injecteeType = method.getParameterTypes()[injectee.getPosition()];
+    if (int.class.equals(injecteeType)) {
+        return Integer.parseInt(fromRequest);
+    }
+    if (long.class.equals(injecteeType)) {
+        return Long.parseLong(fromRequest);
+    }
+    if (String.class.equals(injecteeType)) {
+        return fromRequest;
+    }
+```
+
+That is it for the implementation of our custom injection resolver!  Every time the HttpEventReceiver
+class is instantiated its receiveRequest method will be called with the values from the current
+HttpRequest.  The custom injection resolver was used to find the proper values in the HttpRequest and
+to convert them to the proper types.  The logger would come from the default JSR-330 resolver, since
+it is not annotated with the HttpParameter annotation.
+
+### The RequestScope Context
+
+While the above is enough to demonstrate the custom injection resolver, it is instructive to also go through
+how the RequestScope context works.
+
+The RequestScope context is a proxiable context that changes every time a new request has come in.  The HttpRequest
+in the above example is in the RequestScope, and hence its underlying values will change whenever the request
+has been deemed to change.
+
+In order to create such a scope/context, we first define the scope annotation, RequestScope:
+
+```java
+@Scope
+@Proxiable
+@Retention(RUNTIME)
+@Target( { TYPE, METHOD })
+public @interface RequestScope {
+}
+```
+
+ The context that goes along with that request scope must implement the
+ [Context][context] interface.  The actual type of the [Context][context] parameterized type must be the
+ annotation of the scope.  The [Context][context] implementation
+ for our RequestScope is called RequestContext and is defined like this:
+
+```java
+@Singleton
+public class RequestContext implements Context<RequestScope> {
+    //...
+}
+```
+
+Most implementations of [Context][context] are put into the Singleton
+scope, though this is not required.  An implementation of [Context][context]
+are just like regular HK2 services, and so can be injected with other HK2 services.
+
+The job of an implementation of [Context][context] is to keep a mapping
+of objects created for that particular context while that context is active.  The code that looks up and finds
+objects for a particular request is straight-forward:
+
+
+```java
+public class Bar {
+    private final HashMap<ActiveDescriptor<?>, Object> requestScopedEntities = new HashMap<ActiveDescriptor<?>, Object>();
+
+    public <U> U findOrCreate(ActiveDescriptor<U> activeDescriptor, ServiceHandle<?> root) {
+        U retVal = (U) requestScopedEntities.get(activeDescriptor);
+        if (retVal != null) {
+            return retVal;
+        }
+
+        retVal = activeDescriptor.create(root);
+        requestScopedEntities.put(activeDescriptor, retVal);
+
+        return retVal;
+    }
+
+    public <U> U find(ActiveDescriptor<U> descriptor) {
+        return (U) requestScopedEntities.get(descriptor);
+    }
+}
+```
+
+Since an implementation of [Context][context] is a service, it can be
+looked up by other services.  RequestContext has methods on it that allow some controller to tell it when
+a request has started, and when it ends.  When a request ends its objects are no longer needed and should
+be destroyed.  Here are the methods on RequestContext that begin and end a request:
+
+```java
+    private boolean inRequest = false;
+
+    /**
+     * Starts a request
+     */
+    public void startRequest() {
+        inRequest = true;
+    }
+
+    public void stopRequest() {
+        inRequest = false;
+
+        for (Map.Entry<ActiveDescriptor<?>, Object> entry : requestScopedEntities.entrySet()) {
+            ActiveDescriptor<Object> ad = (ActiveDescriptor<Object>) entry.getKey();
+            Object value = entry.getValue();
+
+            ad.dispose(value);
+        }
+
+        requestScopedEntities.clear();
+    }
+
+    public boolean isActive() {
+        return inRequest;
+    }
+```
+
+The startRequest method above sets the flag saying that the Request has begun.  Any new requests to
+find or create request scoped objects will be adding those objects to the requestScopedEntities map.  The
+stopRequest method above will set the flag saying that the request is over and destroy any objects that were
+created for this request.  It then also clears the requestScopedEntities map so that this RequestScoped context
+is now clean and ready for the next request to come along.
+The isActive method of [Context][context] will tell the system whether or not there is a request that is active.
+
+That is it for the implementation of our RequestScope scope/context pair.  In this example the HttpRequest object
+is in the RequestScope, but this implementation does not preclude other services from also being in this scope.
+The scope is Proxiable, so that it can be injected into other objects with a different lifecycle (like the
+AlternateInjectResolver itself).  Further, it properly disposes all request scoped objects that were created
+when the request has terminated.
+
+## Putting it all together
+
+We now have a custom injection resolver and a custom scope.  Lets look at the other classes in the example, to see
+how they tie everything together.
+
+First we have a class called the HttpServer.  The HttpServer is a mock HttpServer that takes requests from the faux
+network and does the following things:
+
++ Tells the RequestScope that a Request has begun
++ Fills in the HttpRequest with information from the wire
+
+The request processing then continues from there, until the faux network decides that the request has finished.  The
+HttpServer will then tell the RequestContext that the request has terminated.
+
+Here is the implementation of our mocked HttpServer:
+
+```java
+@Singleton
+public class HttpServer {
+    @Inject
+    private HttpRequest httpRequest;
+
+    @Inject
+    private RequestContext requestContext;
+
+    public void startRequest(String lastRank, String id, String action) {
+        requestContext.startRequest();
+
+        httpRequest.addElement(lastRank);
+        httpRequest.addElement(id);
+        httpRequest.addElement(action);
+    }
+
+    public void finishRequest() {
+        requestContext.stopRequest();
+    }
+}
+```
+
+This mock HttpServer will be used by the test code to give the server requests from the network and to then end those requests.  The
+injected HttpRequest will be created anew in the HttpServer.startRequest  method when the RequestContext.startRequest() method is called.
+
+We then have another class called RequestProcessor which is in the PerLookup scope and which is responsible for further handling the
+request.  In our example it doesn't have much to do other than injecting an instance of the HttpEventReceiver.  Since the
+HttpEventReceiver is also in the PerLookup scope, it will be created whenever the instance of RequestProcessor is created.  Here is
+the code for RequestProcessor:
+
+```java
+@PerLookup
+public class RequestProcessor {
+    @Inject
+    private HttpEventReceiver eventReciever;
+
+    public HttpEventReceiver processHttpRequest() {
+        return eventReciever;
+    }
+}
+```
+
+We can now look at how the test code work.
+The test has a helper method that does the following:
+
++ Gets the HttpServer service
++ starts a request by giving it passed in strings that came from the faux network
++ Gets a RequestProcessor service
++ Gets the HttpEventReceiver from the RequestProcessor
++ ends the request with the HttpServer
++ Checks that the values from the HttpEventReceiver were passed into it properly
+
+Here is the test utility method:
+
+```java
+    private void doRequest(int rank, long id, String event) {
+        HttpServer httpServer = locator.getService(HttpServer.class);
+
+        httpServer.startRequest("" + rank, "" + id, event);
+
+        RequestProcessor processor = locator.getService(RequestProcessor.class);
+
+        HttpEventReceiver receiver = processor.processHttpRequest();
+
+        httpServer.finishRequest();
+
+        // And now test that we got what we should have
+        Assert.assertEquals(rank, receiver.getLastRank());
+        Assert.assertEquals(id, receiver.getLastId());
+        Assert.assertEquals(event, receiver.getLastAction());
+    }
+```
+
+After having this utility method, the test itself is very simple, and just ensures that the whole thing fits together nicely:
+
+```java
+    @Test
+    public void testSomeRequests() {
+        doRequest(50, 1, "FirstRequest");
+        doRequest(100, 2, "SecondRequest");
+        doRequest(1000, 3, "ThirdRequest");
+    }
+```
+
+## Conclusion
+
+ In this example we have learned how to create and use a custom injection resolver and a request scoped context.  We have done so
+ with a fake HttpServer example, that takes requests from a fake network and passes values to services based on fields in the
+ HttpRequest.  We have seen how the custom resolver can use data from annotations to further discover the values that should be
+ given to the parameter.  We have seen how the proxiable request context is used to ensure that the underlying request can
+ change from request to request.  We have shown how a custom resolver can customize the default JSR-330 provider.
+
+[context]: apidocs/org/glassfish/hk2/api/Context.html
+[injectionresolver]: apidocs/org/glassfish/hk2/api/InjectionResolver.html
+[injectionpointindicator]: apidocs/org/glassfish/hk2/api/InjectionPointIndicator.html
+[injectee]: apidocs/org/glassfish/hk2/api/Injectee.html
diff --git a/docs/events.md b/docs/events.md
new file mode 100644
index 0000000..9092f5f
--- /dev/null
+++ b/docs/events.md
@@ -0,0 +1,157 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+* TOC
+{:toc}
+
+# Events
+
+The HK2 event service provides a pluggable mechanism that allows delivery of messages from service to
+service.  Those services sending events are called publishers and those receiving events are called
+subscribers.  A message can be any java object.
+
+## Topics
+
+A [Topic][topic] is a special HK2 service that can be injected into a service or can be looked up from
+a [ServiceLocator][servicelocator].  It normally is injected as a ParameterizedType, where the generic
+Type is the class of the event that will be published.  So if there is an event class called ImportantEvent
+that is to be distributed to subscribers, the injection point for the [Topic][topic] might look like this:
+
+```java
+    @Inject
+    Topic<ImportantEvent> importantEventTopic;
+```
+
+The publish method of [Topic][topic] will distribute the message to the set of subscribers.  In this way
+the subscribers and the publishers need not have any previous knowledge of each other.
+
+A [Topic][topic] may have qualifiers associated with it.  These qualifiers will normally be used to
+further select the set of subscribers who should receive the message.  In the following example
+only those subscribers who ask for CodeRed ImportEvent events will receive them (assuming CodeRed is
+a qualifier):
+
+```java
+    @Inject @CodeRed
+    Topic<ImportantEvent> importantEventTopic;
+```
+
+## Pluggability
+
+In order to provide maximum flexibility in terms of qualities of service between publishers and
+subscribers the HK2 event subsystem is pluggable.  This means that when a message is published
+by the publish method of the [Topic][topic] service it is not given directly to the subscribers.
+Instead there is an HK2 service called the [TopicDistributionService][topicdistributionservice]
+that is responsible for distributing messages from the producer to the subscribers.
+
+Having the [TopicDistributionService][topicdistributionservice] be responsible for the distribution
+of messages allows the designers of the system to control the quality of service between the
+producers and the subscribers.  Some of the qualities of service that can be controlled this way are
+security, threading and error handling.  It is even possible to distribute events outside of the
+JVM if that is what the [TopicDistributionService][topicdistributionservice] decides to do!
+
+The [TopicDistributionService][topicdistributionservice] has a method called distributeMessage
+which is responsible for sending events to subscribers.  It takes the [Topic][topic] that sent
+the message and the message to send.  The [Topic][topic] contains information concerning the
+Type of the [Topic][topic] and all of its associated qualifiers.
+
+HK2 provides a default implementation of [TopicDistributionService][topicdistributionservice]
+which will be described in the sections below.
+
+## The Default TopicDistributionService
+
+In order to enable the default [TopicDistributionService][topicdistributionservice] the
+[ServiceLocatorUtilities][servicelocatorutilities] method enableTopicDistribution should be called:
+
+```java
+    public void initializeEvents(ServiceLocator locator) {
+        ServiceLocatorUtilities.enableTopicDistribution(locator);
+    }
+```
+
+The default [TopicDistributionService][topicdistributionservice] is named HK2TopicDistributionService
+and has a priority of 0.  It is possible to enhance the behavior of the default
+[TopicDistributionService][topicdistributionservice] by adding an implementation of
+[TopicDistributionService][topicdistributionservice] with a higher priority and which injects
+the default [TopicDistributionService][topicdistributionservice].  Then the default implementation
+can be delegated to by the custom enhanced [TopicDistributionService][topicdistributionservice].
+An example of how to do this is given [here][threaded-events-example].
+
+## Subscribers
+
+In the HK2 default system subscribers are found by finding methods on services that have a
+single parameter annotated with [@SubscribeTo][subscribeto].  Any other parameters of the
+method are considered to be injection points that should be satisfied by normal HK2 services.
+The following methods are all subscribers to ImportantEvent:
+
+```java
+  public void importantEventSubscriber(@SubscribeTo ImportantEvent event) {
+    // Do something with this important event
+  }
+  
+  public void importantEventSubscriber(@SubscribeTo ImportantEvent event, ServiceLocator locator) {
+    // Do something with this important event and with the ServiceLocator
+  }
+  
+  public void importantEventSubscriber(ServiceLocator locator, @SubscribeTo ImportantEvent event) {
+    // Do something with this important event and with the ServiceLocator
+  }
+```
+
+All three of the above methods will be called when a [Topic][topic] publish method is called with
+an ImportantEvent.
+
+In the default implementation the subscribers will be called on the same thread as the caller of
+the [Topic][topic] publish method.  Any exceptions thrown by subscribers (or for other reasons such
+as an injection point not being available) will be given to all registered implementations of the 
+[DefaultTopicDistributionErrorService][defaulttopicdistributionerrorservice].  The default
+[TopicDistributionService][topicdistributionservice] will only distribute events
+to services whose instances were created after the [ServiceLocatorUtilities][servicelocatorutilities]
+method enableTopicDistribution has been called.  Any subscribers on a service that is disposed or
+has had its associated descriptor removed will not be invoked.
+
+Events will only be given to services that have already been created.  For example an event will
+not cause a Singleton service that has not already been instantiated to become instantiated, even if
+the Singleton service is a listener to the event.
+
+A method parameter with [@SubscribeTo][subscribeto] can also take qualifiers.  A qualifier will
+restrict the set of messages that will be given to the subscription method.  For example the
+following method will only get ImportantEvents from Topics that are also qualified with
+the CodeRed qualifier:
+
+```java
+  public void codeRedSubscriber(@SubscribeTo @CodeRed ImportantEvent redEvent) {
+    // do something with the code-red event
+  }
+```
+
+If an injection point on a subscription method has scope PerLookup then the instance of
+that service will be disposed after the subscription method has returned.
+
+## Conclusion
+
+Events can help your application have low cohesion, as subscribers and publishers need not
+have any relationship other than agreeing on an event Type.  HK2 provides a powerful mechanism
+for plugging in any messaging provider to provide desired qualities of service.  A default
+messaging provider is available which can either be replaced or enhanced if other qualities
+of service are required by the application.
+
+[topic]: apidocs/org/glassfish/hk2/api/messaging/Topic.html
+[servicelocator]: apidocs/org/glassfish/hk2/api/ServiceLocator.html
+[topicdistributionservice]: apidocs/org/glassfish/hk2/api/messaging/TopicDistributionService.html
+[servicelocatorutilities]: apidocs/org/glassfish/hk2/utilities/ServiceLocatorUtilities.html
+[subscribeto]: apidocs/org/glassfish/hk2/api/messaging/SubscribeTo.html
+[defaulttopicdistributionerrorservice]: apidocs/org/glassfish/hk2/utilities/DefaultTopicDistributionErrorService.html
+[threaded-events-example]: threaded-events-example.html
diff --git a/docs/extensibility.md b/docs/extensibility.md
new file mode 100644
index 0000000..cfb1488
--- /dev/null
+++ b/docs/extensibility.md
@@ -0,0 +1,466 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+* TOC
+{:toc}
+
+# Extensibility
+
+
+## Compatibility
+
+This page describes the features of the GlassFish HK2 2.0 API.  The Habitat API
+from version 1.x of HK2 has been replaced with a new interface called
+[ServiceLocator][servicelocator]. More information can be found [here][apioverview].
+
+## Features of GlassFish HK2
+
+GlassFish HK2 has many features for customizing the system.  This page is intended to give an
+overview of each feature.  Among the set of GlassFish HK2 features are:
+
+## Events
+
+It is possible to send messages from one service to another using the GlassFish HK2 event feature.  The event feature is allows for unrelated
+services to message each other without prior coordination (other than on the Type of event).  It is a pluggable event service,
+which allows for user defined qualities of service between the publishers and subscribers.
+
+The GlassFish HK2 event service is described fully [here][events].
+
+An example of plugging in a different event distributor can be found [here][threaded-events-example].
+
+### Adding a Scope and Context to the system
+
+In GlassFish HK2 a [Context][context] is a class that is used to control the lifecycle of service instances.  A [Scope][scope] is an annotation that is put onto another
+annotation that is used to associate any service with a particular [Context][context].  All services
+in GlassFish HK2 are associated with a single scope.
+
+There are two system provided scope/context pairs.  The default [Scope][scope] for services annotated with [@Service][service] is the
+[Singleton][singleton] scope.  Service instances in the [Singleton][singleton] scope are created once and are never destroyed.
+
+The default [Scope][scope] for services bound with the [DynamicConfiguration][dynamicconfiguration] bind call is [PerLookup][perlookup].
+Service instances in the [PerLookup][perlookup] scope are created every time that the service is injected or looked up via the API.
+These instances are destroyed when the [ServiceHandle][servicehandle] destroy method is called on any service that has injected a [PerLookup][perlookup] object.
+
+Any number of other scope/context pairs can be added to the system.  In order to do so, the user must write
+an implementation of [Context][context] where the parameterized type of the [Context][context] is the annotation annotated with [Scope][scope] that the [Context][context] is handling.
+This implementation of [Context][context] is then bound into the [ServiceLocator][servicelocator] like any other service.
+
+To make this more clear, we have two examples of user scope/context pairs:
+
+- This [example][ctm-example] adds a context that is based on the current running tenant.
+- This [example][custom-resolver-example] adds a request scoped context.
+
+## PerThread Scope
+
+There is a per-thread scope/context pair optionally supported in GlassFish HK2.
+Services marked with [PerThread][perthread] have their life cycle defined by the thread they are on.
+Two different threads injecting a service from the [PerThread][perthread] scope will get different objects.
+Two objects on the same thread injecting a [PerThread][perthread] scope service will get the same object.
+
+The [PerThread][perthread] scope can be added to any [ServiceLocator][servicelocator] by using the method [enablePerThreadScope][enableperthreadscope]
+
+## InheritableThread Scope
+
+There is a inheritable thread scope/context pair optionally supported in GlassFish HK2.
+Services marked with [InheritableThread][inheritablethread] are similar to PerThread scoped services with one caveat,
+their life cycle defined by the thread they are on and are inherited by its child threads.
+Two different threads injecting a service from the [InheritableThread][inheritablethread] scope will get different objects.
+Two objects on the same thread injecting a [InheritableThread][inheritablethread] scope service will get the same object.
+Two objects on a parent and child thread injecting a [InheritableThread][inheritablethread] scope service will get the same object.
+
+The [InheritableThread][inheritablethread] scope can be added to any [ServiceLocator][servicelocator] by using the method [enableInheritableThreadScope][enableInheritableThreadScope]
+
+## Immediate Scope
+
+There is an Immediate scope/context pair optionally supported in GlassFish HK2.
+Services marked with [Immediate][immediate] will be started as soon as their
+[ActiveDescriptors][activedescriptor] are added to the [ServiceLocator][servicelocator].  They are destroyed when
+their [ActiveDescriptors][activedescriptor] are removed from the [ServiceLocator][servicelocator].
+[Immediate][immediate] services are started and stopped on an independent thread.  Users of this
+feature can also register implementations of [ImmediateErrorHandler][immediateerrorhandler] in order
+to catch errors thrown by [Immediate][immediate] services.
+
+Care should be taken with the Injection points of an [Immediate][immediate] service, as they will implicitly
+get created immediately in order to satisfy the dependencies.  Since [Immediate][immediate] services
+are created using an independent thread there is no guarantee that [Immediate][immediate] services
+will be started before or after any other service.  The only guarantee is that [Immediate][immediate]
+services will eventually get started.  Normally they get started very quickly after being added to
+the [ServiceLocator][servicelocator].
+
+The [Immediate][immediate] scope can be added to any [ServiceLocator][servicelocator] by using
+the method [enableImmediateScope][enableimmediatescope].  It is important to notice that
+[enableImmediateScope][enableimmediatescope] must be called on all [ServiceLocators][servicelocator]
+who will have [Immediate][immediate] services bound in them.  In particular it is NOT sufficient to
+call [enableImmediateScope][enableimmediatescope] on the parent of a [ServiceLocators][servicelocator],
+since this implementation will only automatically detect [Immediate][immediate] services directly added
+to the [ServiceLocators][servicelocator] given to the [enableImmediateScope][enableimmediatescope]
+method.
+
+## Proxies
+
+Rather than injecting an instance of a service itself, GlassFish HK2 can also inject a proxy to that service.  There are a few
+reasons that you might want to use proxies.  One reason is because the lifeycle of two different scopes may be
+different.  For example, you might have something like a RequestScoped scope, and you would like to inject it
+into a Singleton scoped object.  But the Singleton scoped object is only injected once, and the RequestScoped service
+will be changing every time the Request has changed.  This can be solved by injecting a proxy into the
+Singleton scoped object.  Then every time the Singleton scoped service uses the RequestScoped service the proxy
+will make sure to use the real RequestScoped service that is appropriate for the current request.
+
+Another reason you might want to use a proxy for a service is if the service is extremely expensive to create, and
+if possible you want to delay the creation until the service is actually used by the caller.  In fact, if the caller
+never invokes on the proxy, it is possible the service will never get started!  This can be done by injecting a
+proxy into a service rather than the real service.  The proxy will not attempt to create the service until some method
+of that proxy is invoked.
+
+All proxies created by GlassFish HK2 will also implement [ProxyCtl][proxyctl].
+[ProxyCtl][proxyctl] can be used to force the creation of the underlying service without calling any of the methods of that service.
+Of course every service that is to be proxied must be proxiable, so the service to be proxied must either be an interface or a class that is not declared final,
+has no final fields or methods and has a public zero-argument constructor.  In general it is better to proxy interfaces
+rather than classes.
+
+In order to have GlassFish HK2 create a proxy for your service rather than the service itself you can create a proxiable scope.
+A proxiable scope is just like a normal scope, except that the scope annotation is also annotated with [Proxiable][proxiable].
+All services injected or looked up from this scope will be given a proxy rather than the real service.
+
+This is an example of a proxiable scope:
+
+```java
+@Scope
+@Proxiable
+@Retention(RUNTIME)
+@Target( { TYPE, METHOD })
+public @interface ProxiableSingleton {
+}
+```
+
+While normally every service in a proxiable scope is proxiable, you can override the default proxying behavior
+on a per-service basis.  This is also true for services in non-proxiable scopes.  For example you can make
+a service that is in Singleton scope (which is not proxiable) be proxied.
+You do this by setting the field [isProxiable][isproxiable].
+If that method returns null then that service will use the scopes mode when it comes to proxying.
+If that method returns non-null then the system will either proxy or not proxy based on the returned value.
+Classes that are automatically analyzed can also use the [UseProxy][useproxy] annotation to indicate explicitly
+whether or not they should be proxied.  This is a service in Singleton scope that will be proxied:
+
+```java
+@Singleton @UseProxy
+public class SingletonService {
+}
+```
+
+This is a service in the ProxiableSingleton scope that will NOT be proxied (even though ProxiableSingleton is
+a Proxiable scope):
+
+```java
+@ProxiableSingleton @UseProxy(false)
+public class AnotherService {
+}
+```
+
+### Proxying within the same scope
+
+By default if a service is proxiable then it will be proxied even when being injected into other services within the same scope.
+This allows for the lazy use case.  However, it is sometimes the case that it is counter-productive to proxy services when
+they are injected into other services of the same scope.  GlassFish HK2 supports Proxiable scopes that do NOT proxy services when they
+are being injected into the same scope.  The [Proxiable][proxiable] annotation has a field called proxyForSameScope that by default is true but which can be set to false.
+The following scope is a proxiable scope where services injected into other services in the same scope will not be proxied:
+
+```java
+@Scope
+@Proxiable(proxyForSameScope=false)
+@Retention(RUNTIME)
+@Target( { TYPE, METHOD })
+public @interface RequestScope {
+}
+```
+
+ Individual descriptors can also explicity set whether or not they should be proxied for other services in the same
+ scope by setting the [isProxyForSameScope][isproxyforsamescope] value.
+ This value can also be set when using automatic class analysis by using the [ProxyForSameScope][proxyforsamescope].  The following
+ service is in the ProxiableSingelton scope which would normally not proxy when being injected into the same scope, but
+ which in this case WILL be proxied even when injected into another service in the same scope:
+
+```java
+@RequestScope @ProxyForSameScope
+public class ExpensiveRequestService {
+}
+```
+
+### Proxies and equals()
+
+GlassFish HK2 treats the equals method of Object slightly differently from other methods.  If the incoming parameter of the equals
+method is itself a proxy, then GlassFish HK2 will unwrap that object and send in the unproxied object.  This is to ensure that
+two proxy instances that are pointing to the same underlying service will return true even if the equals method is
+not explicitly implemented.  Consider the following example:
+
+```java
+Foo foo1 = locator.getService(Foo.class);
+Foo foo2 = locator.getService(Foo.class);
+Assert.assertTrue(foo1.equals(foo2));
+```
+
+In the example above if foo1 and foo2 are proxies that point to the same underlying service then if GlassFish HK2 did NOT treat equals
+specially the assertion of truth would fail, since foo1 would have its equals method called being given the proxy of foo2, not
+the underlying object of foo2.  Instead, because equals is treated specially, the assertion will be true since foo2 will be
+unwrapped and the underlying object will get passed in.
+
+No other method is treated in this way by the proxying code of GlassFish HK2.
+
+
+## ClassLoading
+
+Classloading is an interesting challenge in any Java environment.  GlassFish HK2 defers classloading as long as possible, but at some
+point, it must get access to the true class in order to create and inject instances.  At that moment, GlassFish HK2 will attempt
+to reify the descriptor, using the [ServiceLocator][servicelocator] reify method.
+
+Every [Descriptor][descriptor] bound into the system has an associated [HK2Loader][hk2loader].
+If the getLoader method of [Descriptor][descriptor] returns null, then the system defined algorithm
+for loading classes will be used.  Otherwise, the given [HK2Loader][hk2loader] will be used to load the class described by this [Descriptor][descriptor].
+
+The system algorithm used when the getLoader method of [Descriptor][descriptor] returns null is to first consult the classloader of the class being injected into, if available.
+If not available, GlassFish HK2 will use the classloader that loaded GlassFish HK2 itself.
+Failing this, the class will fail to be loaded and an exception will be thrown.
+
+Note that since the user is providing an implementation of [HK2Loader][hk2loader]
+rather than a java.lang.ClassLoader that it is possible to delay the instantiation of the underlying ClassLoader until
+the [Descriptor][descriptor] is being reified.  It might also be possible to have the implementation of [HK2Loader][hk2loader] consult several underlying ClassLoaders,
+or construct the class dynamically using weaving or some other class building technology.
+The mind boggles at all the ways [HK2Loader][hk2loader] can be implemented.
+
+## Custom Injection Resolvers
+
+By default the system provides JSR-330 standard injection.
+That means honoring [@Inject][javaxinject] and all other parts of the JSR-330 specification.
+However, it is sometimes the case that a user would like to customize the JSR-330 resolution in some manner,
+or provide their own injection points based on a different annotation.
+
+In order to do so, the user implements [InjectionResolver][injectionresolver].
+The parameterized type of the [InjectionResolver][injectionresolver] must be the injection annotation that they will resolve.
+The user implementation of [InjectionResolver][injectionresolver] is then bound into a [ServiceLocator][servicelocator] like any other service.
+
+Annotations to be used as injection points can optionally be annotated
+with [InjectionPointIndicator][injectionpointindicator].  This annotation
+allows automatic analysis of classes using the custom [InjectionResolver][injectionresolver].
+
+This [example][custom-resolver-example] adds a custom injection resolver that customizes the default JSR-330 injection resolver.
+
+### Just in Time Injection Resolver
+
+There are times when the set of services to be injected is not completely known before the system is booted.  In
+these cases it may be useful to use a [Just In Time Injection Resolver][justintimeinjectionresolver].  The
+[Just In Time Injection Resolver][justintimeinjectionresolver] is a GlassFish HK2 service that is called whenever the
+system cannot find a suitable service for a given [Injection Point][injectee].  If the
+[Just In Time Injection Resolver][justintimeinjectionresolver] service knows how to find the service then
+it can add the service to the ServiceLocator and tell GlassFish HK2 to look again for the service.  A good example
+of using this would be when retrieving services from a remote system, or from some other service oriented
+system such as OSGi, Spring or Guice.
+
+## Security
+
+Certain operations that are performed by the users of GlassFish HK2 can be validated.  Validation can either
+allow or deny the operation in question.  The operations that can be validated are adding a
+service to the [ServiceLocator][servicelocator], removing a service from the [ServiceLocator][servicelocator],
+injecting a service into another service or looking up a service from the [ServiceLocator][servicelocator].
+This feature is most often used in secure use-cases, but has applicability for other use-cases
+as well.  To use validation the user registers an implementation of [ValidationService][validationservice]
+with the [ServiceLocator][servicelocator] whose operations are to be validated.
+
+There is an example example of how the [ValidationService][validationservice] can be used to do a complete
+security lockdown of the system.  This example runs with the J2SE security manager turned on and
+grants some privileges to some projects and other privileges to other projects to ensure that
+the [ValidationService][ValidationService] can be used to define the security of the system.
+
+The example can be seen [here][security-lockdown-example-runner].
+
+## Instance Lifecycle
+
+A user may register an implementation of [InstanceLifecycleListener][instancelifecyclelistener] to be notified whenever an instance of a service is created.
+Unlike the [ValidationService][validationservice], which deals only with the metadata of a service,
+the [InstanceLifecycleListener][instancelifecyclelistener] is notified whenever an instance
+of a service is created or destroyed.  This is a useful facility for tracing or for scenarios where a service wishes to become
+an automatic listener for anything that it is injected into.
+
+## Interception
+
+[AOP Alliance][aopalliance] method and constructor interception is supported by GlassFish HK2.  Methods and constructors that are to be
+intercepted are identified using instances of the GlassFish HK2 [InterceptionService][interceptionservice].  An example of
+how to use the [InterceptionService][interceptionservice] can be found [here][aopexample].
+
+There is an GlassFish HK2 provided default implementation of the [InterceptionService][interceptionservice] which uses
+annotations to indicate services that should be intercepted, those that should do the intercepting and to
+bind intercepted methods and constructors to their interceptors.  Information about the GlassFish HK2 provided
+default implementation of the [InterceptionService][interceptionservice] can be found [here][aopdefault].
+
+## Dynamic Configuration Listeners
+
+A user may register an implementation of [DynamicConfigurationListener][dynamicconfigurationlistener] to be notified  whenever
+the set of [ActiveDescriptors][activedescriptor] in a [ServiceLocator][servicelocator] has changed.  The
+[DynamicConfigurationListener][dynamicconfigurationlistener] must be in the [Singleton][singleton] scope.
+
+## Class Analysis
+
+GlassFish HK2 often needs to look at a java class in order to find things about that class such as its set
+of constructors, methods or fields.  The choices GlassFish HK2 makes is usually determined by specifications
+such as JSR-330 or JSR-299.  However, in some cases different specifications make different choices,
+or the user of the GlassFish HK2 system may have some other scheme it would like to use in order to
+select the parts of class which GlassFish HK2 should manipulate.  For example, the JAX-RS specification
+requires the system to choose the constructor with the largest number of parameters (by default)
+while the JSR-299 specification requires the system to choose the zero-argument constructor
+or else fail.
+
+The GlassFish HK2 system allows the user to register named implementation of the [ClassAnalyzer][classanalyzer]
+in order to modify or completely replace the constructors, fields and methods GlassFish HK2 would choose.
+Individual GlassFish HK2 [Descriptors][descriptor] can set the name of the [ClassAnalyzer][classanalyzer]
+that should be used to analyze the implementation class.
+
+GlassFish HK2 always adds an implementation of [ClassAnalyzer][classanalyzer] with the name "default" that implements
+the JSR-299 style of selection.
+
+## Run Level Services
+
+If your system has sets of services that need to come up and down in an orderly fashion consider
+using the GlassFish HK2 Run Level Services.  The Run Level Service allows one to specify levels at
+which services come up and down and will bring these services up and down when the system run level
+has changed.
+
+Learn more about Run Level Services [here][runlevelservices].
+
+## Self Descriptor Injection
+
+Any service can have its own [ActiveDescriptor][activedescriptor] injected into itself.  One use case for
+this is when you have a common set of services that all share the same super class.  The super class can
+self inject the [ActiveDescriptor][activedescriptor] and then use that to do further generic processing
+of the service.  To self inject the [ActiveDescriptor][activedescriptor] for your service use the
+[Self][self] annotation on a field or on a parameter of your constructor or initializer method.  Here is an example:
+
+```java
+public abstract class GenericService {
+  @Inject @Self
+  private ActiveDescriptor<?> myOwnDescriptor;
+}
+```
+
+## ServiceLocator to ServiceLocator Bridge
+
+It is possible to import all the [NORMAL] services from one ServiceLocator into
+another ServiceLocator as long as the locators do not have a parent/child relationship.  You do
+this be creating a ServiceLocator bridge between the two ServiceLocators.  This is done using
+the [bridgeServiceLocator][bridgeservicelocator] method in the optional hk2-extras module.
+
+Bridges are one-way and dynamic.  Suppose you have a ServiceLocator named Foo and have bridged
+its services into the Bar ServiceLocator.  If you add a service to the Foo ServiceLocator that service
+will be locatable in the Bar ServiceLocator, even if the service is added after the bridge was
+created.
+
+Cycles between ServiceLocators are supported.  It will appear that all services from all ServiceLocators
+are available in all of the ServiceLocators involved in the cycle.  For example, if Foo and Bar
+service locators have bridges going in both directions then it will appear that Foo and Bar
+have the same set of [NORMAL] services.
+
+A bridge between two service locators is torn down by using the method
+[unbridgeServiceLocator][unbridgeservicelocator] or by shutting down the ServiceLocator
+supplying the services.
+
+There are some feature interaction implications for bridged locators.  For example if you
+have a proxiable scope (such as a RequestScope) in a source locator that is bridged to destination
+locators then when the destination locator gets a reference to the service that object may be a proxy
+of a proxy.  The first proxy is the proxy created by the destination locator and the second proxy
+is the proxy created by the source locator.  Take this into account if you use the __make
+method of [ProxyCtl][proxyctl] since it may just return the underlying proxy rather than the
+end service.  Calling methods on services works but may go through layers of proxies.  This should
+be mostly invisible to your application unless you are doing complex work with the proxies.
+
+## Error Handling
+
+Errors can pop up in various phases of the GlassFish HK2 service lifecycle.  Users can register implementations of the
+[ErrorService][errorservice] in order to be notified when errors occur.  There are currently four types of
+errors that the system sends to the [ErrorService][errorservice]:
+
++ FAILURE_TO_REIFY:  When there has been a problem classloading a service
++ DYNAMIC_CONFIGURATION_FALURE: When a dynamic update to the set of services fails
++ SERVICE_CREATION_FALURE: When a service fails during creation
++ SERVICE_DESTRUCTION_FAILURE: When a service fails during destruction
+
+Using the [ErrorService][errorservice] can be a convenient place to standardize on logging of service failures.
+
+## Operations
+
+A GlassFish HK2 Operation is a scope/context pair used to implement scopes like RequestScope, ApplicationScope
+or TransactionScope.  Any service lifecycle (context) for which only one instance of that context can be
+active at a time is a candidate to be a GlassFish HK2 Operation.  RequestScope is a good example in most containers,
+as each thread is generally tied to a single request.
+
+More information about GlassFish HK2 Operations and an example can be found [here][operations].
+
+## Stub Generation
+
+GlassFish HK2 has a [Stub][stub] annotation that can be put onto abstract classes.  The hk2-metadata-generator
+will then generate a class that implements the unimplemented methods on the abstract class.  This
+is very useful when testing as simple stubs can be made of services that would normally not work properly
+in a test environment.  For more information see [hk2-metdata-generator][hk2-metadata-generator].
+
+[apioverview]: api-overview.html
+[servicelocator]: apidocs/org/glassfish/hk2/api/ServiceLocator.html
+[context]: apidocs/org/glassfish/hk2/api/Context.html
+[servicehandle]: apidocs/org/glassfish/hk2/api/ServiceHandle.html
+[perlookup]: apidocs/org/glassfish/hk2/api/PerLookup.html
+[perthread]: apidocs/org/glassfish/hk2/api/PerThread.html
+[enableperthreadscope]: apidocs/org/glassfish/hk2/utilities/ServiceLocatorUtilities.html#enablePerThreadScope(org.glassfish.hk2.api.ServiceLocator)
+[inheritablethread]: apidocs/org/glassfish/hk2/api/InheritableThread.html
+[enableinheritablethreadscope]: apidocs/org/glassfish/hk2/utilities/ServiceLocatorUtilities.html#enableInheritableThreadScope(org.glassfish.hk2.api.ServiceLocator)
+[enableimmediatescope]: apidocs/org/glassfish/hk2/utilities/ServiceLocatorUtilities.html#enableImmediateScope(org.glassfish.hk2.api.ServiceLocator)
+[immediateerrorhandler]: apidocs/org/glassfish/hk2/utilities/ImmediateErrorHandler.html
+[service]: apidocs/org/jvnet/hk2/annotations/Service.html
+[dynamicconfiguration]: apidocs/org/glassfish/hk2/api/DynamicConfiguration.html
+[scope]: https://jakarta.ee/specifications/platform/8/apidocs/javax/inject/Scope.html
+[singleton]: https://jakarta.ee/specifications/platform/8/apidocs/javax/inject/Singleton.html
+[ctm-example]: ctm-example.html
+[proxyctl]: apidocs/org/glassfish/hk2/api/ProxyCtl.html
+[proxiable]: apidocs/org/glassfish/hk2/api/Proxiable.html
+[isproxiable]: apidocs/org/glassfish/hk2/api/Descriptor.html#isProxiable()
+[useproxy]: apidocs/org/glassfish/hk2/api/UseProxy.html
+[isproxyforsamescope]: apidocs/org/glassfish/hk2/api/Descriptor.html#isProxyForSameScope()
+[proxyforsamescope]: apidocs/org/glassfish/hk2/api/ProxyForSameScope.html
+[descriptor]: apidocs/org/glassfish/hk2/api/Descriptor.html
+[hk2loader]: apidocs/org/glassfish/hk2/api/HK2Loader.html
+[javaxinject]: https://jakarta.ee/specifications/platform/8/apidocs/javax/inject/Inject.html
+[injectionresolver]: apidocs/org/glassfish/hk2/api/InjectionResolver.html
+[injectionpointindicator]: apidocs/org/glassfish/hk2/api/InjectionPointIndicator.html
+[validationservice]: apidocs/org/glassfish/hk2/api/ValidationService.html
+[security-lockdown-example-runner]: security-lockdown-example-runner.html
+[instancelifecyclelistener]: apidocs/org/glassfish/hk2/api/InstanceLifecycleListener.html
+[classanalyzer]: apidocs/org/glassfish/hk2/api/ClassAnalyzer.html
+[custom-resolver-example]: custom-resolver-example.html
+[runlevelservices]: runlevel.html
+[activedescriptor]: apidocs/org/glassfish/hk2/api/ActiveDescriptor.html
+[dynamicconfigurationlistener]: apidocs/org/glassfish/hk2/api/DynamicConfigurationListener.html
+[immediate]: apidocs/org/glassfish/hk2/api/Immediate.html
+[self]: apidocs/org/glassfish/hk2/api/Self.html
+[aopalliance]: http://aopalliance.sourceforge.net/
+[interceptionservice]: apidocs/org/glassfish/hk2/api/InterceptionService.html
+[aopexample]: aop-example.html
+[aopdefault]: aop-default.html
+[events]: events.html
+[threaded-events-example]: threaded-events-example.html
+[bridgeservicelocator]: apidocs/org/glassfish/hk2/extras/ExtrasUtilities.html#bridgeServiceLocator(org.glassfish.hk2.api.ServiceLocator,org.glassfish.hk2.api.ServiceLocator)
+[errorservice]: apidocs/org/glassfish/hk2/api/ErrorService.html
+[unbridgeservicelocator]: apidocs/org/glassfish/hk2/extras/ExtrasUtilities.html#unbridgeServiceLocator(org.glassfish.hk2.api.ServiceLocator,org.glassfish.hk2.api.ServiceLocator)
+[NORMAL]: apidocs/org/glassfish/hk2/api/DescriptorVisibility.html#NORMAL
+[justintimeinjectionresolver]: apidocs/org/glassfish/hk2/api/JustInTimeInjectionResolver.html
+[injectee]: apidocs/org/glassfish/hk2/api/Injectee.html
+[operations]: operations.html
+[hk2-metadata-generator]: inhabitant-generator.html
+[stub]: apidocs/org/glassfish/hk2/utilities/Stub.html
diff --git a/docs/getting-started.md b/docs/getting-started.md
new file mode 100644
index 0000000..6713eb0
--- /dev/null
+++ b/docs/getting-started.md
@@ -0,0 +1,100 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+* TOC
+{:toc}
+
+# Getting started
+
+## Maven Build
+
+The best way to use HK2 in your builds is to add the following dependency in your maven build:
+
+```xml
+<project>
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.acme</groupId>
+    <artifactId>myModule</artifactId>
+    <version>1.0-SNAPSHOT</version>
+
+    <dependencies>
+      <dependency>
+        <groupId>org.glassfish.hk2</groupId>
+        <artifactId>hk2</artifactId>
+        <version>2.5.0-b36</version>
+      </dependency>
+    </dependencies>
+</project>
+```
+
+The org.glassfish.hk2:hk2 dependency has a dependency on all of the HK2 jars.
+However, this may be more than you want, since it includes configuration, 
+run-level services and some osgi support that your application may not need.
+If instead you wanted the absolute minimum working profile for hk2 you would instead have your project look like this:
+
+```xml
+<project>
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.acme</groupId>
+    <artifactId>myModule</artifactId>
+    <version>1.0-SNAPSHOT</version>
+
+    <dependencies>
+      <dependency>
+        <groupId>org.glassfish.hk2</groupId>
+        <artifactId>hk2-locator</artifactId>
+        <version>2.5.0-b36</version>
+      </dependency>
+    </dependencies>
+</project>
+```
+
+The hk2-locator project contains the implementation of the hk2 API, with
+no other bells and whistles.  In particular, the ability to automatically
+detect services is not available, and so all HK2 objects must be added
+programmatically and gotten with the HK2 API.  However, the above is perfect
+for small projects that want to play with the HK2 API to see how it works.
+
+## Automatic Service Population
+
+In order for HK2 to automatically find services at runtime it can read files called inhabitant files.
+ These are usually placed in your JAR file at location META-INF/hk2-locator.
+ Normally the file is named default.
+ (You can however use a different file name or location(s) by using more specific API).
+ HK2 has a tool for automatically creating these files based on class files annotated with [@Service][service].
+ There is also a simple API for creating and populating a [ServiceLocator][servicelocator] with services found in these files.
+
+In order to have your Maven build generate the META-INF files that hk2 reads in order to populate a [ServiceLocator][servicelocator] 
+use the [hk2-inhabitant-generator][inhabitant-generator].
+This tool can be used from the command line, or it can be put into your maven or ant builds.
+
+In order to have your program automatically load the files generated with the [hk2-inhabitant-generator][inhabitant-generator] you can
+use the [createAndPopulateServiceLocator][createandpopulateservicelocator] method near the start of your main method, like this:
+  
+```java
+  public static void main(String argv[]) {
+      ServiceLocator locator = ServiceLocatorUtilities.createAndPopulateServiceLocator();
+      
+      MyService myService = locator.getService(MyService.class);
+      
+      ...
+  }
+```
+
+[servicelocator]: apidocs/org/glassfish/hk2/api/ServiceLocator.html
+[inhabitant-generator]: inhabitant-generator.html
+[createandpopulateservicelocator]: apidocs/org/glassfish/hk2/utilities/ServiceLocatorUtilities.html#createAndPopulateServiceLocator()
+[service]: apidocs/org/jvnet/hk2/annotations/Service.html
diff --git a/docs/guice-bridge.md b/docs/guice-bridge.md
new file mode 100644
index 0000000..c47fa7a
--- /dev/null
+++ b/docs/guice-bridge.md
@@ -0,0 +1,146 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+* TOC
+{:toc}
+
+# The Guice/HK2 Bridge
+
+The Guice/HK2 Bridge can be used to inject [Guice][guice] services
+into HK2 services or inject HK2 services into [Guice][guice] services.
+It can be used bi-directionally as well.
+
++ [Definitions](guice-bridge.html#Definitions)
++ [Injecting Guice services into HK2 services](guice-bridge.html#Injecting_Guice_services_into_HK2_services)
++ [Injecting HK2 services into Guice services](guice-bridge.html#Injecting_HK2_services_into_Guice_services)
++ [Bi-Directional HK2 Guice Bridge](guice-bridge.html#Bi-Directional_HK2_Guice_Bridge)
+
+## Definitions
+
++ A [Guice][guice] service is a service that is instantiated (created) by [Guice][guice]
++ An HK2 service is a service that is instantiated (created) by HK2
+
+## Injecting Guice services into HK2 services
+
+[Guice][guice] services can be injected into any injection point in HK2.
+In order to do this you must tell HK2 about the [Guice][guice] [Injector][injector] 
+which has the [Guice][guice] service definitions.
+This is accomplished in two steps.
+
+In the first step you should have the [ServiceLocator][servicelocator]
+that contains services you wish to be injected with [Guice][guice] services.
+You must initialize this [ServiceLocator][servicelocator] with some required
+Guice/HK2 bridge services.  You can do this using the utility class [GuiceBridge][guicebridge].
+This is a code snippet that initializes a [ServiceLocator][servicelocator]:
+ 
+```java
+  GuiceBridge.getGuiceBridge().initializeGuiceBridge(aServiceLocator);
+```
+
+In the second step you must tell your initialized [ServiceLocator][servicelocator] about the
+specific [Guice][guice] [Injector][injector](s) that you want it to look for services in.
+You do this with the [GuiceIntoHK2Bridge][guiceintohk2bridge] service that was added in the previous step.
+The following code snippet adds a [Guice][guice] [Injector][injector] to be searched for services when injecting into HK2 services:
+ 
+```java
+  public void tieInjectorToLocator(ServiceLocator aServiceLocator, Injector guiceInjector) {
+      GuiceIntoHK2Bridge guiceBridge = aServiceLocator.getService(GuiceIntoHK2Bridge.class);
+      guiceBridge.bridgeGuiceInjector(guiceInjector);
+  }
+```
+
+Any [Guice][guice] [Injector][injector] added with the [bridgeGuiceInjector][bridgeguiceinjector]
+method will be searched for services that HK2 cannot otherwise find.
+
+For example, if you have a service called GuiceService that is created by [Guice][guice], you can inject it into an HK2 service
+(called HK2Service) like this:
+ 
+```java
+  @Service
+  public class HK2Service {
+      @Inject
+      private GuiceService guiceService;
+  }
+```
+
+## Injecting HK2 services into Guice services
+
+HK2 services can be injected into [Guice][guice] services.
+In order to do so, you must use the [HK2Inject][hk2inject] injection annotation.
+For example, if you have an HK2 service named HK2Service that is to be injected
+into a [Guice][guice] service (called GuiceService) your code would look like this:
+
+```java
+  public class GuiceService {
+      @HK2Inject
+      private HK2Service hk2Service;
+  }
+```
+
+In order to do this we have provided an implementation of [Module][module]
+that should be given to [Guice][guice] when creating the [Guice][guice] [Injector][injector].
+This implementation of [Module][module] is [HK2IntoGuiceBridge][hk2intoguicebridge].
+The following code snippet is an example of how you would create a [Guice][guice]
+[Injector][injector] using the [HK2IntoGuiceBridge][hk2intoguicebridge] [Module][module] to
+tell the [Guice][guice] [Injector][injector] about the [ServiceLocator][servicelocator] to use for finding HK2 services:
+  
+```java
+  Injector injector = Guice.createInjector(
+                new HK2IntoGuiceBridge(serviceLocator),
+                // application modules);
+```
+
+Any [Guice][guice] service that can be created with this [Injector][injector] 
+will now search the provided [ServiceLocator][servicelocator] 
+when it encounters a service that is injected with the [HK2Inject][hk2inject] annotation.
+  
+## Bi-Directional HK2 Guice Bridge
+
+[Guice][guice] and HK2 can bridge back and forth between each other.
+The following code example shows how you could accomplish such a thing:
+
+```java
+  public Injector createBiDirectionalGuiceBridge(ServiceLocator serviceLocator,
+            Module... applicationModules) {
+        Module allModules[] = new Module[applicationModules.length + 1];
+        
+        allModules[0] = new HK2IntoGuiceBridge(serviceLocator);
+        for (int lcv = 0; lcv < applicationModules.length; lcv++) {
+            allModules[lcv + 1] = applicationModules[lcv];
+        }
+        
+        Injector injector = Guice.createInjector(allModules);
+        
+        GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
+        GuiceIntoHK2Bridge g2h = serviceLocator.getService(GuiceIntoHK2Bridge.class);
+        g2h.bridgeGuiceInjector(injector);
+        
+        return injector;
+    }
+```
+
+The above method will create a [Guice][guice] [Injector][injector] 
+where services created by Guice can be injected with HK2 services (using the [HK2Inject][hk2inject] annotation).
+Also services created by HK2 can be injected with [Guice][guice] services (using any supported HK2 injection annotation).
+
+[guice]: https://github.com/google/guice
+[injector]: https://google.github.io/guice/api-docs/latest/javadoc/com/google/inject/Injector.html
+[servicelocator]: apidocs/org/glassfish/hk2/api/ServiceLocator.html
+[guicebridge]: apidocs/org/jvnet/hk2/guice/bridge/api/GuiceBridge.html
+[guiceintohk2bridge]: apidocs/org/jvnet/hk2/guice/bridge/api/GuiceIntoHK2Bridge.html
+[bridgeguiceinjector]: apidocs/org/jvnet/hk2/guice/bridge/api/GuiceIntoHK2Bridge.html#bridgeGuiceInjector
+[hk2inject]: apidocs/org/jvnet/hk2/guice/bridge/api/HK2Inject.html
+[module]: https://google.github.io/guice/api-docs/latest/javadoc/com/google/inject/Module.html
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..9c11ee6
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,70 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+Eclipse GlassFish HK2 is an implementation of [Jakarta Dependency Injection](https://jakarta.ee/specifications/dependency-injection/). This project
+began as HK2 as an implementation of JSR-330 in a JavaSE environment.
+
+
+[JSR-330](http://jcp.org/aboutJava/communityprocess/final/jsr330/) defined services and injection points that can be dynamically discovered at runtime and which allow for Inversion of Control (IoC) and dependency injection (DI). Eclipse Dependency Injection continues to evolve Dependency Injection for Jakarta EE.
+
+
+GlassFish HK2 provides an API for control over its operation and has the ability to automatically load services into the container.
+
+
+It is the foundation for the GlassFish V3 and V4 application servers as well as other products.
+
+
+GlassFish HK2 also has powerful features that can be used to perform tasks such as looking up services or customizing you injections, as well as several extensibility features allowing the users to connect with other container technologies
+
+
+The following list gives an overview of some of the things that can be customized or extended with GlassFish HK2:
+- Custom lifecycles and scopes
+- Events
+- AOP and other proxies
+- Custom injection resolution
+- Assisted injection
+- Just In Time injection resolution
+- Custom validation and security
+- Run Level Services
+
+
+Getting started
+----------------
+
+Read the [introduction](introduction.html) and [get started](getting-started.html) with GlassFish HK2.
+
+
+API overview
+------------
+
+[Learn](api-overview.html) more about the GlassFish HK2 API, or [browse](apidocs/index.html) the javadoc.
+
+
+Features
+--------
+
+[Learn](extensibility.html) more about the features of GlassFish HK2
+
+
+Integration
+-----------
+
+GlassFish HK2 is well integrated with [Eclipse GlassFish](https://glassfish.org). Legacy HK2 is also used in many projects, [Spring](http://www.springsource.org) and others !
+
+Site Map
+--------
+
+All files in this site are listed on the [Site Map](sitemap) page.
\ No newline at end of file
diff --git a/docs/inhabitant-generator.md b/docs/inhabitant-generator.md
new file mode 100644
index 0000000..560e8d0
--- /dev/null
+++ b/docs/inhabitant-generator.md
@@ -0,0 +1,321 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+* TOC
+{:toc}
+
+# Inhabitant Generators
+
+There are two ways to generate hk2 metadata (called inhabitant files) that can be
+used by the runtime system to find hk2 services without having to classload those
+services.  The first is the <b>HK2 Metadata Generator</b>, which works with the javac build
+tool, and the second is the <b>HK2 Inhabitant Generator</b> which can be used at build time
+with any build system or even post build time with JARs or can be embedded in other
+tools.
+
+The HK2 Metadata Generator is easy to use, as all it requires is to be on the
+javac classpath.  The HK2 Inhabitant Generator is also easy to use
+but requires the user to specify lines in the build system files (besides just
+dependencies).  Users can choose whichever tool works for them in their
+build environment.
+
+## HK2 Metadata Generator
+
+The HK2 Metadata Generator will generate hk2 inhabitant files during the compilation
+of your java files.  It is a JSR-269 annotation processor that handles the [@Service][service]
+annotation.  The only requirement for using it is to put the javax.inject, hk2-utils, hk2-api and
+hk2-metadata-generator libraries in the classpath of the javac process.
+
+In this example we use the HK2 Metadata Generator in a Maven based build system:
+
+```xml
+  <dependency>
+      <groupId>org.glassfish.hk2</groupId>
+      <artifactId>hk2-metadata-generator</artifactId>
+  </dependency>
+```
+
+Since Maven uses transitive dependencies this is all you need to add as a dependency during
+build.
+
+In the following example we use the HK2 Metadata Generator in a gradle based build system:
+
+```java
+dependencies {
+  compile group: 'javax.inject', name: 'javax.inject', version: '1.1'
+  compile group: 'org.glassfish.hk2', name: 'hk2-utils', version: '2.4.0-b14'
+  compile group: 'org.glassfish.hk2', name: 'hk2-api', version: '2.4.0-b14'
+  compile group: 'org.glassfish.hk2', name: 'hk2-metadata-generator', version: '2.4.0-b14'
+  
+  testCompile group: 'javax.inject', name: 'javax.inject', version: '1.1'
+  testCompile group: 'org.glassfish.hk2', name: 'hk2-utils', version: '2.4.0-b14'
+  testCompile group: 'org.glassfish.hk2', name: 'hk2-api', version: '2.4.0-b14'
+  testCompile group: 'org.glassfish.hk2', name: 'hk2-metadata-generator', version: '2.4.0-b14'
+}
+```
+
+### HK2 Metadata Generator Options
+
+By default the HK2 Metadata Generator places the output file in META-INF/hk2-locator/default. However
+this behavior can be modified by setting the option <i>org.glassfish.hk2.metadata.location</i> to
+the desired location.  This is done with the javac compiler using the -A option.  In gradle
+this looks something like this:
+
+```java
+compileJava {
+  options.compilerArgs << '-Aorg.glassfish.hk2.metadata.location=META-INF/hk2-locator/acme'
+}
+```
+
+## HK2 Inhabitant Generator
+
+The HK2 Inhabitant Generator is a utility that will generate inhabitants file during the
+build of your JAR file.  It works by analyzing the classes that have been built by javac and
+then creating the file **META-INF/hk2-locator/default** (by default) in your JAR file that has
+information in it about all of the classes that you have marked with [@Service][service] or
+[@Contract][contract].
+
+The HK2 Inhabitatants Generator can be used as a standalone command-line tool, or it can
+be embedded in any Java program.  It can also be used in a Maven build.  An Eclipse build
+and an ant task are also planned.  Here are the ways that the HK2 Inhabitants Generator can
+be used:
+
+### Command Line Tool
+
+The HK2 Inhabitants Genertor can be run from the command line like this:
+ 
+```java
+java org.jvnet.hk2.generator.HabitatGenerator
+```
+
+By default the [HabibatGenerator][habitatgenerator] will attempt to analyze the first element of the classpath
+and replace that element (if it is a JAR) with a new JAR that has an inhabitants file in
+it describing all of the classes marked with [@Service][service].  If the first element of the classpath
+is a directory it will attempt to create a new inhabitants file in that directory describing
+all of the classes marked with [@Service][service].
+
+You can modify this behavior by using command line options.
+Here is the usage statement for [HabibatGenerator][habitatgenerator]:
+ 
+```
+java org.jvnet.hk2.generator.HabitatGenerator
+  [--file jarFileOrDirectory]
+  [--outjar jarFile]
+  [--locator locatorName]
+  [--verbose]
+```
+
+The --file option allows the user to pick a directory or JAR file to analyze for classes marked
+with @Service.
+
+The --outjar option allows the user to pick the output JAR file that the generator should create
+with the inhabitants file in it.
+
+The --locator option allows the user to name the locator that these services should go into.  This
+value is \"default\" by default.
+
+The --verbose option make the generator print extra information as it does its work.
+
+This command line utility will call **System.exit** when it is done with a 0 code if it was able
+to work properly and a non-zero value if it failed in some way.
+ 
+### Embedded Usage
+
+The class [org.jvnet.hk2.generator.HabitatGenerator][habitatgenerator] has a static method on called embeddedMain.
+The embeddedMain takes the typical argv[] array of parameters and so has the same behavior
+as the command line usage.  The biggest difference is that this method returns an
+int as the return code, either 0 for success or non-zero for failure and does not call
+System.exit().  See the [javadoc][habitatgenerator] for more information.
+ 
+Using embeddedMain is useful if you want to build your own build tools that generate inhabitants
+files for your own IDE or other build environment.
+ 
+### Using Maven
+
+The HabitatGenerator is also available as a Maven plugin.  It has a single goal, called
+generateInhabitants that is run in the process-classes phase by default.  Using this plugin
+in your build will cause inhabitants files to be generated in your output directory.
+
+The following example plugin snippet from a pom.xml will run the InhabitantsGenerator in
+both the main tree and in the test tree, in case you would like your test sources to also
+be analyzed for classes marked with [@Service][service].
+
+```xml
+    <plugin>
+      <groupId>org.glassfish.hk2</groupId>
+      <artifactId>hk2-inhabitant-generator</artifactId>
+      <version>2.5.0-b36</version>
+      <executions>
+        <execution>
+          <goals>
+            <goal>generate-inhabitants</goal>
+          </goals>
+        </execution>
+      </executions>
+    </plugin>
+```
+
+ The plugin has the following configuration options:
+ 
++ outputDirectory (the place the output file will go, defaults to $\{project.build.outputDirectory\})
++ testOutputDirectory (the place the output will go if test is true, defaults to $\{project.build.testOutputDirectory\})
++ verbose (true or false)
++ test Set to true if this execution should be for the tests rather than main
++ locator The name of the locator file (which is \"default\" by default)
++ noswap (true or false) if set to true the generator will overwrite files in place which is riskier but faster
+  
+### Ant Task
+
+The inhabitant generator can also be used as an ant task.  The ant task is org.jvnet.hk2.generator.maven.ant.HK2InhabitantGeneratorTask.
+Below find an example ant file that uses the task:
+  
+```xml
+<project name="HK2 Ant Build File" default="build" basedir=".">
+  <!-- set global properties for this build -->
+  <property name="src" location="src"/>
+  <property name="build" location="target/classes"/>
+
+  <taskdef name="hk2-inhabitant-generator"
+           classname="org.jvnet.hk2.generator.ant.HK2InhabitantGeneratorTask"/>
+
+  <target name="compile" >
+    <!-- Compile the java code from ${src} into ${build} -->
+    <javac srcdir="${src}" destdir="${build}"/>
+    <hk2-inhabitant-generator targetDirectory="${build}"/>
+  </target>
+</project>
+```
+
+The thing to note in the example above is that the hk2-inhabitant-generator must run after the classes are built, as the hk2-inhabitant-generator
+inspects the class files.
+
+The ant plugin has the following options:
+ 
++ targetDirectory (the directory to find the classes, defaults to target/classes)
++ outputDirectory (the place the output file will go, defaults to target/classes)
++ verbose (true or false)
++ locator The name of the locator file (which is \"default\" by default)
++ noswap (true or false) if set to true the generator will overwrite files in place which is riskier but faster
+
+## Stub Generation
+
+The HK2 metadata generator can also generate implementation classes based on abstract classes.  This is useful
+when testing, as it is often the case in tests that the user would like to replace some service with one
+that does nothing or does only a few special things during the test.  This is done by putting the [Stub][stub]
+annotation on an abstract class.  Any abstract methods NOT implemented by the class will have dummy implementations
+generated in a java file that also has an [Service][service] annotation.  This will then become an service in
+the Singleton scope, which should show up when using most hk2 initialization methodologies.  The benefits of
+using the [Stub][stub] annotation include:
+
++ The service need not be completely implemented.  Only those methods that need to return specific data
+needed by the test need to be implemented
++ The [Rank][rank] annotation will work when placed on the abstract class, so the stub can be given higher
+priority than the replacement class
++ Using [Stub][stub] means that this abstract class may not need to be updated if the underlying interface
+or class has an added method
++ It makes it very easy to write very simple test replacement classes
+
+In this simple example there is an interface with a large number of methods:
+
+```java
+@Contract
+public interface ManyMethodsService {
+  public void methodA();
+  public void methodB();
+  public int methodFoo();
+  public String methodBar(String input);
+  // And so on
+}
+```
+
+Somewhere in your build there is an implementation of ManyMethodsService.  It may or may not look like this:
+
+```java
+@Service
+public class ManyMethodsServiceImpl implements ManyMethodsService {
+  // Here we really implement the interface, possibly doing JDBC or other possibly heavy operations
+}
+```
+
+However, in the test environment there is only one or two methods that the test touches.  In this case
+we can very easily use the [Stub][stub] annotation to tell the hk2-metadata-generator to generate an
+implementation that fills in the missing methods.  This test version of the service might be
+implemented like this:
+
+```java
+@Stub @Rank(1)
+public abstract class TestManyMethodsService implements ManyMethodsService {
+  // Only implement the methods that the test actually touches, and return
+  // hard-coded data
+  public int methodFoo() {
+    return 13;
+  }
+  
+  public String methodBar(String input) {
+    return input;
+  }
+  
+  // Do not implement the other methods in the interface
+}
+```
+
+If the hk2-metadata-generator is in the classpath of the test build then it will see the [Stub][stub]
+annotation and will generate a java file with the unimplemented methods implemented, returning
+either null or 0 or "a" along with an added [Service][service] annotation.  Since the [Rank][rank]
+annotation is set to 1 in the abstract class (TestManyMethodsService) it will be used in favor of the true
+implementation (ManyMethodsServiceImpl).
+
+If there is a [@Named][named] qualifier on the class annotated with [Stub][stub] that qualifier will also be
+copied to the resulting implementation class.  If [@Named][named] has no value associated with it the value
+used will be the value of the class with [Stub][stub] on it.  For example this class:
+
+```java
+@Stub @Named
+public abstract class AliceService implements SomeInterface {
+}
+```
+
+will end up having the name \"AliceService\", while this class:
+
+```java
+@Stub @Named("Bob")
+public abstract class AliceService implements SomeInterface {
+}
+```
+
+will end up having the name \"Bob\".  Only the [@Named][named] qualifier is treated
+specially in this way.
+
+The [Stub][stub] annotation can also generate implementations where rather than returning null or zero values
+it throws UnsupportedOperationException (with the name of the method called in the message).  This can
+be done by setting the value field of the [Stub][stub] to EXCEPTIONS, like this:
+
+```java
+@Stub(Stub.Type.EXCEPTIONS)
+public abstract class AliceService implements SomeInterface {
+  // All generated methods will throw UnsupportedOperationException
+}
+```
+
+This can be useful when writing tests to ensure that the code does not inadvertently use one of the
+methods of the stub's implementation.
+
+[service]: apidocs/org/jvnet/hk2/annotations/Service.html
+[contract]: apidocs/org/jvnet/hk2/annotations/Contract.html
+[habitatgenerator]: apidocs/org/jvnet/hk2/generator/HabitatGenerator.html
+[stub]: apidocs/org/jvnet/hk2/utilities/Stub.html
+[rank]: apidocs/org/glassfish/hk2/api/Rank.html
+[named]: https://jakarta.ee/specifications/platform/8/apidocs/javax/inject/Named.html
diff --git a/docs/integration.md b/docs/integration.md
new file mode 100644
index 0000000..efde36a
--- /dev/null
+++ b/docs/integration.md
@@ -0,0 +1,105 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+* TOC
+{:toc}
+
+# Integration
+
+## GlassFish integration
+
+HK2 can be used in GlassFish applications.
+Every deployed GlassFish application has a unique ServiceLocator associated with it that can be looked up with JNDI name **java:app/hk2/ServiceLocator**.
+This ServiceLocator will not have a parent, and will be destroyed when the application is undeployed. 
+The following is example code that returns the application ServiceLocator:
+
+```java
+  public ServiceLocator getServiceLocator() {
+
+        try {
+          Context context = new InitialContext();
+
+          return (ServiceLocator) context.lookup("java:app/hk2/ServiceLocator");
+        }
+        catch (NamingException ne) {
+            return null;
+        }
+    }
+```
+
+There are several options for populating the per-application ServiceLocator. The first is to use the [hk2-inhabitant-generator][inhabitant-generator]. 
+For EJBs and Library JAR files the system will read files named application located in **META-INF/hk2-locator/**. For war files the system will read files named application located in WEB-INF/classes/hk2-locator.
+
+The following is an example maven stanza using the [hk2-inhabitant-generator][inhabitant-generator] to place the inhabitant file of an EJB in the proper place:
+
+```xml
+    <build>
+      <plugins>
+          <plugin>
+                <groupId>org.glassfish.hk2</groupId>
+                <artifactId>hk2-inhabitant-generator</artifactId>
+                <executions>
+                    <execution>
+                        <configuration>
+                            <locator>application</locator>
+                        </configuration>
+                        <goals>
+                            <goal>generate-inhabitants</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+```
+
+Note that the same stanza can be used for a WAR file, and if the packaging type of the pom is "war" then the [hk2-inhabitant-generator][inhabitant-generator] will automatically put the generated inhabitant file into the correct place.
+
+All inhabitant files are read when the application is deployed, and hence should be able to be looked up from the application [ServiceLocator][serviceLoc].
+One can also use the [DynamicConfigurationService][dynamicConf] in order to add services as per any normal HK2 installation. 
+
+This also works along with the [Binder][bindeer]: and [BuilderHelper][buildhelper] service builders.
+
+## CDI Integration
+
+HK2 is fully integrated with the GlassFish 4.0 CDI implementation.
+
+In other words, services created with CDI can be injected into services created with HK2, and services created with HK2 can be injected into services created with CDI. 
+It should be noted that if left alone, CDI will think that nearly every object is a CDI object, and hence it is best to let CDI create most of your objects, unless you are using specific features of HK2 that cannot be achieved with CDI.
+
+Furthermore, only HK2 services that have been loaded with **META-INF/hk2-locator/application** (for EJB and JAR) and **WEB-INF/classes/hk2-locator/application** (for WARs) can be injected into CDI services.
+
+This is because CDI does early validation of all injection points, and hence all services that are to be injected into CDI must be present prior to the CDI validation phase.
+The CDI validation phase occurs prior to any application code being run.
+Due to the dynamic nature of HK2 services, CDI services can be injected into HK2 services that were created at any time in the life of the application.
+
+## Guice
+
+HK2 services can be injected into [Guice][guice] services and [Guice][guice] services can be injected into HK2 services.
+To do so use the Guice/HK2 bridge, which is described [here](guice-bridge.html).
+  
+## Spring
+
+HK2 services can be used as [Spring][spring] beans, and [Spring][spring] beans can be injected into
+HK2 services.  To do so use the Spring/HK2 bridge, which is described [here](spring-bridge.html).
+
+[inhabitant-generator]: inhabitant-generator.html
+[serviceLoc]: apidocs/org/glassfish/hk2/api/ServiceLocator.html
+[dynamicConf]: apidocs/org/glassfish/hk2/api/DynamicConfigurationService.html
+[bindeer]: apidocs/org/glassfish/hk2/utilities/Binder.html
+[buildhelper]: apidocs/org/glassfish/hk2/utilities/BuilderHelper.html
+[guice]: http://code.google.com/p/google-guice
+[spring]: http://www.springsource.org
diff --git a/docs/introduction.md b/docs/introduction.md
new file mode 100644
index 0000000..e6d2ce2
--- /dev/null
+++ b/docs/introduction.md
@@ -0,0 +1,382 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+* TOC
+{:toc}
+
+# Introduction to GlassFish HK2
+
+This page describes the GlassFish HK2 2.0 API, which is based on JSR-330 standard annotations.
+Also, Habitat has been replaced with a new interface called [ServiceLocator][servicelocator].
+
+GlassFish HK2 is a declarative framework for services using annotations like [Contract][contract] and [Service][service].
+This page is intended to show simple usages of GlassFish HK2 mainly using the standard JSR-330 API.
+
+For information about using the GlassFish HK2 programmatic API see [this page][api-overview].
+For information about GlassFish HK2 extensibility options see [this page][extensibility]
+For information about JSR-330 see [this site][jsr330].
+
+This page assumes that you are using the GlassFish HK2 provided ability to automatically find and
+register services in an GlassFish HK2 registry.  For more information on how to control what services
+are automatically bound to what registries see TBD.
+
+## Getting Started
+
+In order to mark a concrete implementation class as one that should be available 
+as a service you annotate your class with [@Service][service].
+ 
+```java
+@Service
+public class Foo {
+}
+```
+
+By default Foo will be advertised as itself and by any interfaces that are marked with [@Contract][contract].
+Lets make Foo an interface that is a Contract and create an implementation of Foo:
+ 
+```java
+@Contract
+public interface Foo {
+}
+
+@Service
+public class FooImpl implements Foo {
+}
+```
+
+The FooImpl class will be placed into the registry advertised under both FooImpl and Foo.
+ 
+## Named Services
+ 
+In order to differentiate different implementations of the same interface you can name your services.
+Here is an example of a class that implements a contract and has two implementations, both named differently:
+ 
+```java
+@Contract
+public interface Book {
+}
+
+@Service @Named
+public class MobyDick implements Book {
+}
+
+@Service @Named
+public class ParadiseLost implements Book {
+}
+```
+
+The two classes, MobyDick and ParadiseLost, will be added to the service registry with the names
+"MobyDick" and "ParadiseLost".  If you use the [Named][named]
+qualifier without specifying a name then the name you get is the class name without the package.
+ 
+## Qualified Services
+
+Services can also be qualified with annotations called qualifiers.  Qualifiers are annotations that are themselves
+annotated with [@Qualifier][qualifier].  Here is an
+example contract with three implementations:
+ 
+```java
+@Contract
+public interface Color {
+}
+
+@Service @Blue
+public class BlueColor implements Color {
+}
+
+@Service @Red
+public class RedColor implements Color {
+}
+
+@Service @Yellow
+public class YellowColor implements Color {
+}
+```
+
+The Blue annotation is defined like this:
+
+```java
+@Qualifier
+@Retention(RUNTIME)
+@Target( { TYPE, METHOD, FIELD, PARAMETER })
+public @interface Blue {
+}
+```
+
+It is an exercise left up to the reader to implement the Red and Yellow annotations.
+ 
+## Basic Injection
+
+Lets make our example a little more interesting by injecting a book into Foo.  This is done using the
+JSR-330 standard [Inject][inject] annotation:
+ 
+```java
+@Service
+public class FooImpl implements Foo {
+  @Inject
+  private Book book;
+  
+  ...
+}
+```
+
+Upon construction the book field will be filled in by GlassFish HK2.  You can also inject into the constructor of FooImpl, or
+use an initializer method.  In both of those cases the constructor or method must be annotated with
+[@Inject][inject] in order to tell GlassFish HK2 which is the proper constructor or method to call.
+
+Here is FooImpl implemented with constructor injection:
+ 
+```java
+@Service
+public class FooImpl implements Foo {
+  private final Book book;
+  
+  @Inject
+  public FooImpl(Book book) {
+      // constructor injected!
+      this.book = book;
+  }
+}
+```
+
+Here is FooImpl implemented with initializer method injection:
+ 
+```java
+@Service
+public class FooImpl implements Foo {
+  private Book book;
+  
+  @Inject
+  public void setBook(Book book) {
+      // initializer method injected!
+      this.book = book;
+  }
+}
+```
+
+In all three of the above cases (field injected, constructor injected or initializer method injected) the injection will occur
+prior to the postConstruct method of FooImpl.  In this example we use the injected book in the postConstruct method:
+ 
+```java
+@Service
+public class FooImpl implements Foo {
+  @Inject
+  private Book book;
+  
+  @PostConstruct
+  private void postConstruct() {
+      book.doSomething();
+  }
+}
+```
+
+## Injection by name
+
+The astute observer of our example will have noticed that when injecting a Book into FooImpl that we never selected which book we wanted.
+That can be fixed by using the [Named][named] qualifier at the point of injection.  Lets fix the example by injecting both of the Books we defined earlier:
+ 
+```java
+@Service
+public class FooImpl implements Foo {
+  @Inject @Named("MobyDick")
+  private Book mobyDick;
+  
+  @Inject @Named("ParadiseLost")
+  private Book paradiseLost;
+}
+```
+
+The implementation of Book given the name "MobyDick" will be injected into the mobyDick field, and the implementation of
+Book given the name "ParadiseLost" will be injected into the paradiseLost field.
+ 
+## Injection by qualifier
+
+Injections can also be more specifically chosen by using qualifiers.  In the previous example we created three implementations
+of Color, each of which was qualified with a qualifier.  Here we create a class called ColorMixer which injects the colors
+in an initializer method, which also demonstrates that an initializer method (or constructor) can take more than one
+parameter:
+
+```java
+@Service
+public class ColorMixer {
+    private Color red;
+    private Color blue;
+    private Color yellow;
+  
+    @Inject
+    private void addPrimaries(
+            @Red Color red,
+            @Blue Color blue,
+            @Yellow Color yellow) {
+      this.red = red;
+      this.blue = blue;
+      this.yellow = yellow;
+   }
+}
+```
+
+Note that the qualifiers can go on the parameters of the initializer method addPrimaries.  In the above example the RedColor,
+BlueColor and YellowColor services will be injected into the proper fields of the initializer.
+ 
+## Provider injection
+
+There are times when your code would like finer control over when a instance of a service is created.
+Anywhere that you can inject a service, you can also inject a [Provider][atinjectprovider].
+When you inject a [Provider][atinjectprovider] for a service rather than
+the service itself the system will potentially delay the creation of the service until the 
+[get][providerget] method of the [Provider][provider] has been called.
+ 
+Lets go back to our ColorMixer example, and inject providers (into fields this time) for our primaries.
+ 
+```java
+@Service
+public class ColorMixer {
+    @Inject @Red
+    private Provider<Color> redProvider;
+    
+    @Inject @Blue
+    private Provider<Color> blueProvider;
+    
+    @Inject @Yellow
+    private Provider<Color> yellowProvider;
+}
+```
+
+This service can then get the color implementations later.  In this method of ColorMixer we create purple by getting the
+red and blue colors:
+
+```java
+@Service
+public class ColorMixer {
+    ...
+    
+    public Color makePurple() {
+      return mix(redProvider.get(), blueProvider.get());
+    }
+}
+```
+
+Note that if no-one ever makes a color that involves using yellow, that the YellowColor implementation class will never
+be created, since no-one ever called the [get][providerget] method of the yellowProvider field.
+
+The value passed into any [Provider][provider] injection point will be an
+instance of [IterableProvider][iterableprovider].
+ 
+## IterableProvider injection
+
+It is often the case that a single contract has more than one implementation.  Sometimes it is useful to get access to
+all of the implementations of the contract.
+This can be done by using an [IterableProvider][iterableprovider].
+[IterableProvider][iterableprovider] extends [Provider][provider] and also implements [Iterable][iterable].
+Anywhere a service can be injected an [IterableProvider][iterableprovider] for that service can be injected.
+
+In this example we create a Library service that wants to be able to list all of the books it carries:
+
+```java
+@Service
+public class Library {
+    @Inject
+    private IterableProvider<Book> allBooks;
+    
+    public LinkedList<Book> getAllBooks() {
+        LinkedList<Book> retVal = new LinkedList<Book>();
+        
+        for (Book book : allBooks) {
+            retVal.add(book);
+        }
+        
+        return retVal;
+    }
+}
+```
+
+Since [IterableProvider][iterableprovider] implements [Iterable][iterable] 
+it can be used in Java for/while loops, as demonstrated in the above example.
+
+Another feature of the [IterableProvider][iterableprovider] is that it can
+be used to further narrow down the selection criteria at run time.
+In our above example we can progrommatically choose the book we are interested 
+in based on a name passed into a method.  Here is how it would look:
+ 
+```java
+@Service
+public class Library {
+    @Inject
+    private IterableProvider<Book> allBooks;
+    
+    public Book findBook(String name) {
+        return allBooks.named(name).get();
+    }
+}
+```
+
+In the above example we call the [named][iterableprovidernamed] method [IterableProvider][iterableprovider]
+in order to select the book with the given name.
+The call to [get][providerget] then just returns the book with the given name.
+
+## Iterable injection
+
+[Iterable][iterable] can be used as an injection point rather than [IterableProvider][iterableprovider].  The following code will
+work as expected:
+
+```java
+@Service
+public class Library {
+    @Inject
+    private Iterable<Book> allBooks;
+    
+    public LinkedList<Book> getAllBooks() {
+        LinkedList<Book> retVal = new LinkedList<Book>();
+        
+        for (Book book : allBooks) {
+            retVal.add(book);
+        }
+        
+        return retVal;
+    }
+}
+```
+
+The value passed into any [Iterable][iterable] injection point will be an
+instance of [IterableProvider][iterableprovider].
+ 
+## Conclusion
+
+The majority of usages of GlassFish HK2 should use standard JSR-330 annotations along with
+[@Service][service] and [@Contract][contract].
+In some cases code will also use [IterableProvider][iterableprovider] as outlined above.
+In even rarer cases the code may need extremely specialized control over GlassFish HK2 by using the
+programmatic API, as described [here][api-overview].
+
+We have gone through many simple examples which have shown the basic functionality of GlassFish HK2 and JSR-330 in your
+applications.  Hopefully they have provided you with knowledge about how these annotations work and how they
+can be used in your own applications.
+
+[servicelocator]: apidocs/org/glassfish/hk2/api/ServiceLocator.html
+[contract]: apidocs/org/jvnet/hk2/annotations/Contract.html
+[service]: apidocs/org/jvnet/hk2/annotations/Service.html
+[jsr330]: http://www.jcp.org/en/jsr/detail?id=330
+[api-overview]: ./api-overview.html
+[extensibility]: ./extensibility.html
+[inject]: https://jakarta.ee/specifications/platform/8/apidocs/javax/inject/Inject.html
+[iterable]: http://docs.oracle.com/javase/6/docs/api/java/lang/Iterable.html
+[iterableprovidernamed]: apidocs/org/glassfish/hk2/api/IterableProvider.html#named%28java.lang.String%29
+[iterableprovider]: apidocs/org/glassfish/hk2/api/IterableProvider.html
+[providerget]: http://javax-inject.github.io/javax-inject/api/javax/inject/Provider.html#get%28%29
+[provider]: http://javax-inject.github.io/javax-inject/api/javax/inject/Provider.html
+[named]: http://docs.oracle.com/javaee/6/api/javax/inject/Named.html
+[qualifier]: https://jakarta.ee/specifications/platform/8/apidocs/javax/inject/Qualifier.html
+[atinjectprovider]: http://javax-inject.github.io/javax-inject/api/javax/inject/Provider.html
diff --git a/docs/operations.md b/docs/operations.md
new file mode 100644
index 0000000..f43802d
--- /dev/null
+++ b/docs/operations.md
@@ -0,0 +1,468 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+* TOC
+{:toc}
+
+# Operations
+
+Operations are building blocks for crafting scope/context pairs like RequestScoped, ApplicationScoped or
+TransactionScoped.  HK2 is designed to run in any java process, including those that do not have a container
+such as Java EE.  Even when running on a JVM with no container, many applications still have a concept of
+user requests or of different user applications running inside the same JVM.  In those cases it may be useful
+for the writers of the system to use HK2 Operations to create a class of service whose life-cycle is controlled
+by the start or stop of those user requests or controlling application or whatever other demarcation is needed
+by the process as a whole.
+
+## Operations Introduction
+
+A HK2 Operation is defined first by a scope annotation.  Any scope annotation will do, but normally these
+scopes are proxiable since they are meant to be injected into services with different lifecycles, such
+as Singleton scoped services.  Also, they are normally marked to not be proxiable for the same scope.  It is not
+a requirement that scopes used for HK2 operations are proxiable, it is just the normal case that they
+are.
+
+Once an HK2 Operation scope has been defined an implementation of [Context][context] must be added to
+the target ServiceLocator.  To create an HK2 Operation [Context][context] all that is required is to extend
+[OperationContext][operationcontext] and implement the getScope method, returning the class of the scope.
+
+The system software will use the [OperationManager][operationmanager] to create instances of the
+HK2 Operation.  A thread may only have have one instance of an HK2 Operation active at any time. 
+The following statements are also true:
+
+* Any number of HK2 Operations of different types (scopes) can be active on a single thread
+* An instance of a HK2 Operation can be active on more than one thread at a time
+
+When an instance of a HK2 Operation is created an [OperationHandle][operationhandle] is
+returned.  The [OperationHandle][operationhandle] can be used to suspend, resume or destroy
+the Operation instance.  It can be used to discover all the threads upon which an Operation
+instance is active.  The [OperationHandle][operationhandle] is itself registered in HK2 as a
+service in the Operation scope for which it was created, which is useful because arbitrary data
+can be associated with the [OperationHandle][operationhandle].
+
+The following example will illustrate basic usage of HK2 Operations.
+
+## Operations Example
+
+The example can be found under the HK2 source tree at examples/operations.  In the example
+there is an banking application that maintains a deposit ledger and withdrawal ledger indexed
+by account number.  These two ledgers keep track of the funds deposited or those available for
+withdrawal.  Both services are scoped by the bank they represent.  There is a banking service
+that can get the amounts deposited in an account at a bank or available for withdrawal from an
+account at a bank or it can transfer money from one bank account to another bank account.  It does
+this by switching the bank of the deposit account and/or the withdrawal account using HK2 Operations.
+
+#### Example Operation Scope/Context pairs
+
+There are two operation types/scopes defined in this example, a Deposit scope for the
+depositor ledgers and a Withdrawal scope for the withdrawal ledgers.  Here is the
+definition of the Deposit scope:
+
+```java
+@Scope
+@Proxiable(proxyForSameScope = false)
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface DepositScope {
+}
+```
+
+Notice that the DepositScope is proxiable, and that it will not be proxied for other services
+that are also in the DepositScope scope.  In HK2 every defined scope needs an implementation
+of [Context][context].  Since this is to be an HK2 Operation the user only need to extend
+[OperationContext][operationcontext] as below:
+
+```java
+@Singleton
+public class DepositScopeContext extends OperationContext<DepositScope> {
+
+    public Class<? extends Annotation> getScope() {
+        return DepositScope.class;
+    }
+    
+}
+```
+
+The only method that needs to be implemented is the getScope method which need only 
+return the class of the scope annotation.  The DespositScope has now been fully
+defined as an HK2 Operation.  Below find the complete definition of the
+WithdrawalScope:
+
+```java
+@Scope
+@Proxiable(proxyForSameScope = false)
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface WithdrawalScope {
+}
+```
+
+```java
+@Singleton
+public class WithdrawalScopeContext extends OperationContext<WithdrawalScope> {
+
+    public Class<? extends Annotation> getScope() {
+        return WithdrawalScope.class;
+    }
+
+}
+```
+
+### Operation Scoped Services
+
+Lets take a look at two services that are in the HK2 Operations scopes that we
+just defined.  The first one is the DepositLedger, which keeps track of how much
+has been deposited in an account by account number:
+
+```java
+@DepositScope
+public class DepositorService {
+    private Map<Long, Integer> accounts = new HashMap<Long, Integer>();
+    
+    public void depositFunds(long account, int funds) {
+        Integer balance = accounts.get(account);
+        if (balance == null) {
+            accounts.put(account, funds);
+        }
+        else {
+            int original = balance;
+            original += funds;
+            accounts.put(account, original);
+        }
+    }
+    
+    public int getBalance(long account) {
+        Integer balance = accounts.get(account);
+        if (balance == null) return 0;
+        return balance;
+        
+    }
+
+}
+```
+
+This simple service is in the DepositScope.  The important thing to notice about this
+service is that it does not keep track in any way which bank it is keeping these
+accounts for.  That is because the bank where these accounts reside will be managed
+by the system software using HK2 Operations.  That frees this service to only manage
+accounts and not the banks where the accounts reside.  The withdrawal service is very
+similar:
+
+```java
+@WithdrawalScope
+public class WithdrawalService {
+    private Map<Long, Integer> accounts = new HashMap<Long, Integer>();
+    
+    public int withdrawlFunds(long account, int funds) {
+        Integer balance = accounts.get(account);
+        if (balance == null) {
+            // How nice, 100 for me!
+            balance = new Integer(100);
+        }
+        
+        int current = balance;
+        if (funds > current) {
+            funds = current;
+        }
+        
+        current = current - funds;
+        accounts.put(account, current);
+        
+        return funds;
+    }
+    
+    public int getBalance(long account) {
+        Integer balance = accounts.get(account);
+        if (balance == null) {
+            accounts.put(account, 100);
+        }
+        
+        return accounts.get(account);
+    }
+}
+```
+
+This service, like the previous one is in a proxiable HK2 Operation
+scope.  In this case it is in the WithdrawalScope.  Like the previous
+service, this service only keeps track of accounts with a single map,
+since the WithdrawalScope will be managed per bank by the software
+setting up the environment in which these services will get called.
+
+The TransferService is in the Singleton scope, which is just a normal
+scope, not an HK2 Operations scope.  Since a Singelton service has
+a different lifecycle than the services in either DepositorScope or
+WithdrawalScope the DepositorService and WithdrawalService injected
+into it will instead inject a proxy, so that the actual service used
+will depend on the context of the call.  This is the TransferService:
+
+```java
+@Singleton
+public class TransferService {
+    @Inject
+    private DepositorService depositor;
+    
+    @Inject
+    private WithdrawalService withdrawer;
+    
+    public int doTransfer(long depositAccount, long withdrawlAccount, int funds) {
+        int recieved = withdrawer.withdrawlFunds(withdrawlAccount, funds);
+        depositor.depositFunds(depositAccount, recieved);
+        
+        return recieved;
+    }
+
+}
+```
+
+The TransferService injects the DepositorService and the WithdrawalService in order to
+transfer funds from the withdrawer to the depositor.  This service also doesn't know
+which banks are involved in the transfer, so it is also expecting the system software
+to have used the HK2 Operations system in order to properly set the context of the
+call to doTransfer.
+
+### The Banking Service
+
+The BankingService is the service whose implementation will use the HK2 Operations
+feature in order to properly setup the context in which the services in the
+DepositScope and WithdrawalScope will always be called.  The BankingService is the
+service given to end-users to use directly and so is represented by the following
+contract:
+
+```java
+@Contract
+public interface BankingService {
+    /**
+     * Transfers funds between the withdrawal account and the deposit account.  If there
+     * is not enough funds in the withdrawal account it may transfer less than the requested
+     * amount
+     * 
+     * @param withdrawlBank The bank from which the withdrawal is being made
+     * @param withdrawlAccount The account number to withdrawal funds from
+     * @param depositorBank The bank to which the deposit is being done
+     * @param depositAccount The account number to deposit funds to
+     * @param funds The number of funds to transfer
+     * @return The actual funds transferred
+     */
+    public int transferFunds(String withdrawlBank, long withdrawlAccount, String depositorBank, long depositAccount, int funds);
+    
+    /**
+     * Tells how much money has been deposited in the given account in the
+     * given bank
+     * 
+     * @param bank the name of the bank of the account to check
+     * @param account the account number to get the deposited amount from
+     * @return the amount of money deposited in this account
+     */
+    public int getDepositedBalance(String bank, long account);
+    
+    /**
+     * Tells how much money that is available for withdrawal from the
+     * given account number at the given bank.  Note that if the
+     * account number has never been seen before the amount given
+     * at the start is 100 funds
+     * 
+     * @param bank the name of the bank of the account to check
+     * @param account the account number to check
+     * @return the amount of money deposited in this account
+     */
+    public int getWithdrawlBalance(String bank, long account);
+
+}
+```
+
+It is an implementation of the BankingService that the user code will use to
+perform the balance check and transfer operations.  Lets take a look at the
+implementation of the getWithdrawalBalance in the implementation of BankingService,
+BankingServiceImpl:
+
+```java
+@Singleton
+public class BankingServiceImpl implements BankingService {
+    @Inject
+    private OperationManager manager;
+    
+    @Inject
+    private WithdrawalService withdrawerAgent;
+    
+    private final Map<String, OperationHandle<WithdrawalScope>> withdrawers = new HashMap<String, OperationHandle<WithdrawalScope>>();
+    
+    private synchronized OperationHandle<WithdrawalScope> getWithdrawerBankHandle(String bank) {
+        OperationHandle<WithdrawalScope> withdrawer = withdrawers.get(bank);
+        if (withdrawer == null) {
+            // create and start it
+            withdrawer = manager.createOperation(WithdrawalScopeImpl.INSTANCE);
+            withdrawers.put(bank, withdrawer);
+        }
+        
+        return withdrawer;
+    }
+
+    public int getWithdrawalBalance(String bank, long account) {
+        OperationHandle<WithdrawalScope> withdrawer = getWithdrawerBankHandle(bank);
+        
+        // Set the context for the withdrawal balance check
+        withdrawer.resume();
+        
+        try {
+            return withdrawerAgent.getBalance(account);
+        }
+        finally {
+            // suspend the operation
+            withdrawer.suspend();
+        }
+    }
+
+}
+```
+
+Code not involved in the implementation of getWithdrawalBalance has been removed from
+the code snippet above.
+
+The BankingServiceImpl has a Map that goes from a Bank (represented as a String) to
+an HK2 [OperationHandle][operationhandle] of type WithdrawalScope.  The method
+getWithdrawerBankHandle looks in the Map for an [OperationHandle][operationhandle].
+If it does not find one, it uses the createOperation method of
+[OperationManager][operationmanager] in order to create it.  This method does
+not start the operation, it just retrieves it from the Map or creates it.
+
+The getWithdrawalBalance method of BankingServiceImpl uses the getWithdrawerBankHandle
+to get the WithdrawalScope [OperationHandle][operationhandle] associated with the
+given bank and then associates that [OperationHandle][operationhandle] with the
+current thread by calling the resume method.  Calling the resume method
+of [OperationHandle][operationhandle] sets the calling context for the injected field
+withdrawerAgent, which will now use the WithdrawalService for that particular bank.
+Once the underlying operation has completed, the suspend method of
+[OperationHandle][operationhandle] is called to disassociate that HK2 Operation
+from the current thread.
+
+The getDepositedBalance method of BankingServiceImpl works the same way as the
+getWithdrawalBalance with the difference being that the HK2 Operation used is
+of type DepositScope as opposed to WithdrawalScope.
+
+### Transferring Funds Between Banks
+
+The implementation of the method transferFunds in BankingServiceImpl is seen below:
+
+```java
+    public synchronized int transferFunds(String withdrawlBank, long withdrawlAccount,
+            String depositorBank, long depositAccount, int funds) {
+        OperationHandle<DepositScope> depositor = getDepositBankHandle(depositorBank);
+        OperationHandle<WithdrawalScope> withdrawer = getWithdrawerBankHandle(withdrawlBank);
+        
+        // Set the context for the transfer
+        depositor.resume();
+        withdrawer.resume();
+        
+        // At this point the scopes are set properly, we can just call the service!
+        try {
+            return transferAgent.doTransfer(depositAccount, withdrawlAccount, funds);
+        }
+        finally {
+            // Turn off the two scopes
+            withdrawer.suspend();
+            depositor.suspend();
+        }
+        
+    }
+```
+
+The interesting thing about this method is that it illustrates that two HK2 Operations
+of different types (DepositScope and WithdrawalScope) can be active on a single thread
+at the same time.  This duality allows the transfer service to operate between banks simultaneously.
+
+### Seeing it Work
+
+To see the example working there is a junit test case.  The test case simply creates
+some Bank Strings (Chase, Bank of America and South Jersey Federal Credit Union) and
+then checks balances, makes transfers between banks, and checks the balances afterwards
+to make sure they are as expected.  Here it is:
+
+```java
+@Test
+    public void testTransferBetweenBanks() {
+        ServiceLocator locator = getServiceLocator();
+        
+        BankingService bankingService = locator.getService(BankingService.class);
+        
+        // First, initialize the accounts of ALICE, BOB and CAROL with 100 funds
+        int aliceBalance = bankingService.getWithdrawalBalance(CHASE_BANK, ALICE_ACCOUNT);
+        int bobBalance = bankingService.getWithdrawalBalance(BOA_BANK, BOB_ACCOUNT);
+        int carolBalance = bankingService.getWithdrawalBalance(SJFCU_BANK, CAROL_ACCOUNT);
+        
+        Assert.assertEquals(100, aliceBalance);
+        Assert.assertEquals(100, bobBalance);
+        Assert.assertEquals(100, carolBalance);
+        
+        // OK, lets transfer that 100 from alice to bob
+        int amtTransferred = bankingService.transferFunds(CHASE_BANK, ALICE_ACCOUNT, BOA_BANK, BOB_ACCOUNT, 100);
+        
+        Assert.assertEquals(100, amtTransferred);
+        
+        // And lets check the withdrawl funds again, alice should have zero, bob should have 100, carol should still have 100
+        aliceBalance = bankingService.getWithdrawalBalance(CHASE_BANK, ALICE_ACCOUNT);
+        bobBalance = bankingService.getWithdrawalBalance(BOA_BANK, BOB_ACCOUNT);
+        carolBalance = bankingService.getWithdrawalBalance(SJFCU_BANK, CAROL_ACCOUNT);
+        
+        Assert.assertEquals(0, aliceBalance);
+        Assert.assertEquals(100, bobBalance);
+        Assert.assertEquals(100, carolBalance);
+        
+        // But now bob should have 100 in his deposit account
+        int toAlice = bankingService.getDepositedBalance(CHASE_BANK, ALICE_ACCOUNT);
+        int toBob = bankingService.getDepositedBalance(BOA_BANK, BOB_ACCOUNT);
+        int toCarol = bankingService.getDepositedBalance(SJFCU_BANK, CAROL_ACCOUNT);
+        
+        Assert.assertEquals(0, toAlice);
+        Assert.assertEquals(100, toBob);
+        Assert.assertEquals(0, toCarol);
+        
+        // Now lets have Carol transfer to Alice
+        amtTransferred = bankingService.transferFunds(SJFCU_BANK, CAROL_ACCOUNT, CHASE_BANK, ALICE_ACCOUNT, 100);
+        
+        // Now Alice and Carol should have nothing left, while Bob still has his original 100
+        aliceBalance = bankingService.getWithdrawalBalance(CHASE_BANK, ALICE_ACCOUNT);
+        bobBalance = bankingService.getWithdrawalBalance(BOA_BANK, BOB_ACCOUNT);
+        carolBalance = bankingService.getWithdrawalBalance(SJFCU_BANK, CAROL_ACCOUNT);
+        
+        Assert.assertEquals(0, aliceBalance);
+        Assert.assertEquals(100, bobBalance);
+        Assert.assertEquals(0, carolBalance);
+        
+        // At this point Alice and Carol should each have 100 in there deposit account
+        toAlice = bankingService.getDepositedBalance(CHASE_BANK, ALICE_ACCOUNT);
+        toBob = bankingService.getDepositedBalance(BOA_BANK, BOB_ACCOUNT);
+        toCarol = bankingService.getDepositedBalance(SJFCU_BANK, CAROL_ACCOUNT);
+        
+        Assert.assertEquals(100, toAlice);
+        Assert.assertEquals(100, toBob);
+        Assert.assertEquals(0, toCarol);
+        
+        // Yay, the Operations worked properly!
+    }
+```
+
+## Conclusion
+
+HK2 Operations provide a convenient set of tools for building scopes/context pairs that
+follow the general rule of "one operation on a thread at a time."  There are many Operations
+that correspond to this rule, such as RequestScope, ApplicationScope and TransactionScope.  Using
+a consistent facility such as HK2 Operations can reduce the code needed by your application to
+manage those scopes.
+
+[context]: apidocs/org/glassfish/hk2/api/Context.html
+[operationcontext]: apidocs/org/glassfish/hk2/extras/operation/OperationContext.html
+[operationmanager]: apidocs/org/glassfish/hk2/extras/operation/OperationManager.html
+[operationhandle]: apidocs/org/glassfish/hk2/extras/operation/OperationHandle.html
diff --git a/docs/runlevel.md b/docs/runlevel.md
new file mode 100644
index 0000000..253b63b
--- /dev/null
+++ b/docs/runlevel.md
@@ -0,0 +1,234 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+* TOC
+{:toc}
+
+# Run Level Service
+
+The HK2 run level service allows you to automatically bring your system up and down in
+an orderly fashion.  Run level services are annotated to come up or down at specific
+levels.  The user then sets the current level of the system and the run level service
+ensures that all services at that level and below are started.
+
+## Creating a RunLevel service
+
+A RunLevel service is simply a service that is in the [RunLevel][runlevel] scope.  RunLevel services
+normally have a @PostConstruct or @PreDestroy method to be called when the service is started or
+stopped (but this is not required).Here is an example of a RunLevel service:
+ 
+```java
+  @Service @RunLevel(value=5)
+  public class LoggingRunLevelService {
+    @PostConstruct
+    private void startMe() {}
+    
+    @PreDestroy
+    private void stopMe() {}
+  }
+```
+
+The LoggingRunLevelService will get started when the run level is 5 or higher, and will be shutdown
+if the run level is dropped to 4 or lower.  
+
+The following service is started at level 10:
+
+```java
+  @Service @RunLevel(value=10)
+  public class SecurityRunLevelService {
+    @PostConstruct
+    private void startMe() {}
+    
+    @PreDestroy
+    private void stopMe() {}
+  }
+```
+
+All the services in one level are started prior to any service in another level being started.
+If the system is going down rather than up, all services in a level will be stopped before
+services in a lower level are stopped.
+
+The implementation of [Context][context] that goes along with the [RunLevel][runlevel] scope
+is provided by the RunLevel feature.
+
+## The RunLevelController
+
+The [RunLevelController][runlevelcontroller] is a service implemented by the HK2 RunLevel
+feature.  It can tell you the current run level of the system, and it can be used to
+change the current run level.  You can use the asynchronous or synchronous methods
+to change the level.  The only difference is whether or not you want to block the current
+thread waiting for the services to finish. 
+
+The synchronous API to change levels is proceedTo.  You can use it like this:
+
+```java
+  public class MyClass {
+    @Inject
+    private RunLevelController controller;
+    
+    public void changeRunLevel(int level) {
+        controller.proceedTo(level);
+    }
+  }
+```
+
+This code will either bring the system up or down to the specified level while blocking
+the thread.  If you do not want to block the thread, you can use the asynchronous version
+of the API, which returns a [RunLevelFuture][runlevelfuture] that can either be polled
+or waited on at a later time.
+
+```java
+  public class MyClass {
+    @Inject
+    private RunLevelController controller;
+    
+    public RunLevelFuture changeRunLevelAsync(int level) {
+        return controller.proceedToAsync(level);
+    }
+  }
+```
+
+There are also methods on the [RunLevelFuture][runlevelfuture] which allows the caller
+to determine what level the system is proceeding to, and whether or not the current
+job is going up in level or going down.
+
+In general if there is an existing RunLevel job in progress another one cannot be
+started and existing job cannot be changed.  A running job can be cancelled at any time.
+A [RunLevelListener][runlevellistener] can be used to change the proceedTo value of a
+RunLevel job.
+
+## The RunLevelListener
+
+The [RunLevelListener][runlevellistener] is an interface implemented by users of the RunLevel
+service if they want to perform actions in error situations or at the end of a level.  The
+implementations must be put into hk2 as services.  All implementations of
+[RunLevelListener][runlevellistener] registered with HK2 will be called.
+
+In the following example the [RunLevelListener][runlevellistener] logs all
+events that happen.
+
+```java
+  @Service
+  public class RunLevelListenerLogger implements RunLevelListener {
+  
+    public void onProgress(ChangeableRunLevelFuture currentJob,
+            int levelAchieved) {
+        Logger.log("Achieved level: " + levelAchieved);
+    }
+    
+    public void onCancelled(RunLevelFuture currentJob,
+            int levelAchieved) {
+        Logger.log("Cancelled at level: " + levelAchieved);
+
+    }
+
+    public void onError(RunLevelFuture currentJob, ErrorInformation info) {
+        Logger.log("Error while progressing to level: " + currentJob.getProposedLevel(),
+            info.getError());
+    }
+  }
+```
+
+The onProgress callback can be used to change the level the current job is proceeding to
+using the changeProposedLevel method of the passed in [ChangeableRunLevelFuture][changeablerunlevelfuture].
+
+In the onError callback the [ErrorInformation][errorinformation] parameter can be
+used to get the error that was thrown by the service.  It can also be used
+to tell the RunLevel service what to do about the error.  The choices are to
+go down to the last fully achieved level and end the job there
+(ErrorInformation.ErrorAction.GO_TO_NEXT_LOWER_LEVEL_AND_STOP), or to simply
+ignore the error (ErrorInformation.ErrorAction.IGNORE).  When
+the system is going up in level the default action is to go down to the
+last fully achieved level and stop.  When the system is going down in
+level the default action is to ignore the error.
+
+If the onCancelled callback has been called then the job has been cancelled.  A new job
+can be put into place, but the current job is considered to be complete.
+
+## Multi Threading
+
+The [RunLevelController][runlevelcontroller] will attempt to run all of the services
+in a single run-level on parallel threads.  All dependencies will be honored as
+always (if run-level service B depends on run-level service A then run-level service
+A is guaranteed to be fully up before run-level service B is started).  By default
+the [RunLevelController][runlevelcontroller] will use as many threads as there are services
+in the level.  This can be controlled with the setMaximumUseableThreads method of
+[RunLevelController][runlevelcontroller].
+
+Multi-threading can be turned off by using the setThreadingPolicy method to set
+the policy to RunLevelController.ThreadingPolicy.USE_NO_THREADS.
+If this is done then an IllegalStateException will be thrown from the proceedToAsync
+method, since in order to do asynchronous processing at least one thread must be used.  When
+the policy is USE_NO_THREADS all services will be started on the thread
+that calls the proceedTo method.  However, even in the USE_NO_THREADS mode a thread will
+be used when bringing services down in order to ensure that they can be canceled in
+the case of a hung service.
+
+In some cases it is necessary to use specialized threads on which to run the run-level
+services.  The [Executor][executor] that is used by the run level feature can be replaced
+with the setExecutor method of the [RunLevelController][runlevelcontroller].  The
+[Executor][executor] that is currently being used can be discovered with the getExecutor
+method.
+
+## Ordering
+
+In general the run level feature feeds all the services in a certain level to the
+set of threads based on the natural ordering given by hk2.  If only a single thread
+is being used then that is the order services will run.  If multiple threads are
+used then that is the order those services will be given to the threads.  Thus when
+more than one thread is used the ordering in which services are started may be
+indeterminate.
+
+A user can affect the ordering with which the services are given to the threads by
+implementing the [Sorter][sorter] service.  All implementations of [Sorter][sorter]
+will be called with the results from the previous sort method of
+[Sorter][sorter].  The final result will be the list of services given to the
+set of threads executing run-level services.
+
+## Other Goodies
+
+When you give a service a RunLevel value like 10, that normally means that the service
+should start at level 10, no sooner and no later.  In fact, by default if a service
+at level 10 is started when the system level is less than 10 an error will be raised.  But
+there are other times when what you want is for the RunLevel value to mean that the service
+should be started at that level or lower.  This is useful in cases where it may be
+necessary to start the service sooner than it would normally be started based on some
+runtime characteristic of the system.  In that case you can set the mode of
+the [RunLevel][runlevel] to RUNLEVEL_MODE_NON_VALIDATING.  Here is an example:
+
+```java
+  @RunLevel(value=10, mode=RunLevel.RUNLEVEL_MODE_NON_VALIDATING)
+  public class CanRunBeforeTenService {
+  }
+```
+
+HK2 is normally a demand driven system, meaning that services are not started until there
+is an explicit lookup for a service (either via API or via injection).  The HK2 Run Level
+Service allows [RunLevel][runlevel] services to be satisfaction driven, where the condition
+for creating is the current run level of the system.  This is useful when building
+processes that have a specific set of services that need to run on booting or shutting down.
+The obvious application is for server-style processes, but it is also useful for setting
+up things like connections or security in clients.
+
+[runlevel]: apidocs/org/glassfish/hk2/runlevel/RunLevel.html
+[runlevelcontroller]: apidocs/org/glassfish/hk2/runlevel/RunLevelController.html
+[context]: apidocs/org/glassfish/hk2/api/Context.html
+[runlevelfuture]: apidocs/org/glassfish/hk2/runlevel/RunLevelFuture.html
+[runlevellistener]: apidocs/org/glassfish/hk2/runlevel/RunLevelListener.html
+[changeablerunlevelfuture]: apidocs/org/glassfish/hk2/runlevel/ChangeableRunLevelFuture.html
+[errorinformation]: apidocs/org/glassfish/hk2/runlevel/ErrorInformation.html
+[executor]: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executor.html
+[sorter]: apidocs/org/glassfish/hk2/runlevel/Sorter.html
diff --git a/docs/security-lockdown-example-runner.md b/docs/security-lockdown-example-runner.md
new file mode 100644
index 0000000..1c1b55d
--- /dev/null
+++ b/docs/security-lockdown-example-runner.md
@@ -0,0 +1,620 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+* TOC
+{:toc}
+
+# Security Lockdown Example
+
+In this example we will show how to check every injection, lookup, bind
+and unbind operation against a set of J2SE security permissions.  In order
+to do so we have constructed four projects who have a different set of
+permissions in the system.  Lets take a brief glimpse of each project
+in the example, to get an overview of what they do and how they interact
+with the system.  
+
+The first project is the runner project, which is nothing more than a set of
+junit tests which run various scenarios, showing how security is either granted
+or denied to the other projects.
+
+The next project is the system project, which is considered to be secure and
+trusted system code.  This code will receive AllPermission and therefor is able
+to manipulate any object in the system and perform any action.  The system code
+contains things like the security validation service itself, along with other
+secure code such as security services.
+
+Another project is called "Alice."  Alice is an application provider that is
+able to access security services.  Alice will not attempt to do anything bad, but
+will remain within the confines of the permissions granted her.  However, Alice
+does not have AllPermission, and therefore could not perform some operations even
+if she tried (however, she never tries to do anything she shouldn't).
+
+Mallory is the last project.  Mallory is another application provider, who also
+has some access to system resources.  In fact, Mallory has access to the Alice application.
+Mallory usually sticks to the bounds of what he is allowed to do, but sometimes will attempt
+to perform operations that he is not allowed to perform.  We shall see that when he attempts
+to do so he is rebuffed by the security operations of the system.
+
+Lets take a look in detail at how this total security lockdown of the system occurs.
+ 
+## The System Project
+
+The system project has some resources it would like to give out to some applications,
+but not to others.  It would also like to be able to prevent applications from
+binding or unbinding services from the service registry (embodied by the [ServiceLocator][servicelocator].
+
+In order to do this, the system project must decide on a protection scheme.  Therefore the
+decision is made that only code with java.lang.AllPermission shall be able to bind or unbind
+services.  In order to protect lookup and injection services the decision is made to use
+the java.lang.RuntimePermission called "accessClassInPackage".  This permission is used to allow
+code to access classes in a particular package, and so seems appropriate for also protecting services
+that are from that particular package.
+
+It should be noted that the above decisions were made arbitrarily for this example, and real system
+code can use whatever permission scheme it desires, including creating and using its own Permission
+classes.
+
+Lets first take a look at the resource that the system project would like to protect.  You will see
+in the package "org.acme.security" that there is a service called AuditService.  AuditService is an
+extremely simple secure auditing service.  The system code would like to allow some applications access
+to this service, and other applications to NOT be allowed to directly use this service.  It should be noted
+that the code that CAN access the service may be able to use that service on behalf of the callers of that
+service.  That sort of thing will all work according to the normal J2SE security model.  Here is the AuditService,
+a service that should be protected:
+ 
+```java
+@Service @Singleton
+public class AuditService {
+    ...
+}
+```
+
+The most important thing to notice about this service is that there is nothing at all special about it.  It is
+not annotated with any sort of special annotation or indication that it is a secure or protected service.  This
+is because in some environments this service may be protected, while in other environments it may not be protected.
+It is up to the environment to decide which resources need to be protected, and which do not.  In this way the
+burden of deciding which resources are to be protected and which are not are taken away from the developers of the
+resource and put into the hands of the definition of the particular environment in which those resources run.  This
+is a good thing, as it puts the burden of deciding which resources are to be protected into the hands of those who
+can better make that decision.
+ 
+But how *does* the environment decide which resources are protected, and which are not?  In HK2 the answer is a
+system defined service called the [ValidationService][validationservice].
+The [ValidationService][validationservice] has two functions.  The first
+function is to decide which resources should be protected.  The second is to provide code that must be run in
+order to protect the resources which are protected.
+ 
+In this example, the system has decided that every resource must be protected.  Hence the name "security-lockdown"
+example.  Every injection point, lookup and bind will first run through a
+[Validator][validator] to decide whether or not that operation should be allowed
+to proceed.  But before the [Validator][validator] is run on anything first the
+[ValidationService][validationservice] must tell the system that all resources
+are to be protected.
+ 
+In order to do this the system project must implement the
+[ValidationService][validationservice].  In doing so it must implement
+the getLookupFilter API, which returns a [Filter][filter] to
+the system.  The system will use this filter to determine which resources are protected.  If the filter returns
+true about any resource, then that resource will have the [Validator][validator]
+run over it whenever it is looked up or injected.  Note that bind and unbind operations are always run through
+all registered validators, as these operations are rare and can have serious effects on the state of the system.
+
+In our example, where we want to protect every resource, we implement the getLookupFilter in this way:
+ 
+```java
+@Service @Singleton
+public class ValidationServiceImpl implements ValidationService {
+    ...
+    
+    @Override
+    public Filter getLookupFilter() {
+        return BuilderHelper.allFilter();
+    }
+    
+    ...
+}
+```
+
+The[BuilderHelper][buildhelper] allFilter method returns a [Filter][filter] that always returns true.
+In this way we have assured that every lookup and injection in the system will be run through the implementation of 
+[Validator][validator], which is also returned by out implementation of [ValidationService][validationservice]:
+ 
+```java
+@Service @Singleton
+public class ValidationServiceImpl implements ValidationService {
+    private final ValidatorImpl validator = new ValidatorImpl();
+    
+    ...
+
+    @Override
+    public Validator getValidator() {
+        return validator;
+    }
+}
+```
+
+Note that since the ValidationService is a Singleton service that the ValidatorImpl will only be created once,
+and the same one will be returned to the system every time the getValidator method is called.
+
+However, the most important thing about the system code is how it protects the resources it has been charged
+to protect.  That is the job of the ValidatorImpl.  The ValidatorImpl is responsible for determining
+how to validate the BIND, UNBIND and LOOKUP operations.
+Here is the implementation of the [Validator][validator] validate method:
+ 
+```java
+public class ValidatorImpl implements Validator {
+    ...
+    
+    @Override
+    public boolean validate(ValidationInformation info) {
+        switch(info.getOperation()) {
+        case BIND:
+        case UNBIND:
+            return validateBindAndUnbind();
+        case LOOKUP:
+            return validateLookup(info.getCandidate(), info.getInjectee());
+        default:
+            return false;
+        }
+    }
+    
+    ...
+    
+}
+```
+
+It is very important to understand the context in which these calls are made.  In that way it can be determined
+how to check the permission being granted.  In the BIND, UNBIND, and in any LOOKUP that is *not* an injection
+the call frame will be the Java protection domain to check.  In the case of the
+BIND and UNBIND operations this will include the code that called commit on the [DynamicConfiguration][dynamicconfiguration].
+In the case of the non-inject lookup, this will contain the user that is attempting to look up a service.
+
+Since the BIND and UNBIND cases are fairly strait-forward in our example, lets see how this permission
+check is performed.  First, we make a checkPermission call that returns true or false depending on whether
+or not the permission is granted or not.  Here it is:
+ 
+```java
+    private static boolean checkPerm(Permission p) {
+        try {
+            AccessController.checkPermission(p);
+            return true;
+        }
+        catch (AccessControlException ace) {
+            return false;
+        }
+    }
+```
+
+This converts any AccessControlException (an indication that the permission was NOT granted) into a simple
+false value.  Otherwise, if the checkPermission call is successful this method will return true.  It should
+be noted that using the checkPermission in this way will only work properly when the code to be checked is
+on the call stack, and that every piece of code on the call-stack must have the permission being asked for.
+For the BIND and UNBIND operations then, the check is easy, since the caller is on the stack and this method
+is easy to use:
+
+```java
+    private boolean validateBindAndUnbind() {
+        return checkPerm(new AllPermission());
+    }
+```
+
+This is very simple and ensures that anyone who tries to BIND or UNBIND service descriptions into the system
+must have AllPermission!
+
+Now lets talk about the LOOKUP case.  The LOOKUP case can be broken down into two cases, the LOOKUP via an API
+case and the injection case.  Both are doing a lookup of a service.  However in the first case (pure lookup) the
+caller is directly on the stack.  In the second case there may be no other software on the stack other than the
+system software.  Therefore in that case more information may be needed in order to perform our security check.
+That extra information comes in the form of the [Injectee][injectee].  Using the combination of the candidate
+[ActiveDescriptor][activedescriptor] and the
+place that descriptor would be injecting into (the
+[Injectee][injectee]) a security decision can be made about the
+injection point.
+ 
+Lets look at the method that handles the both LOOKUP cases:
+ 
+```java
+    private boolean validateLookup(ActiveDescriptor<?> candidate, Injectee injectee) {
+        if (injectee == null) {
+            return validateLookupAPI(candidate);
+        }
+        
+        return validateInjection(candidate, injectee);
+    }
+```
+
+As you can see from the above code, the lookup has been broken into two cases, the
+lookup with the API case, and the lookup based on the injection point case.  The
+lookup with the API case is similar to the BIND and UNBIND cases, since the permission
+check simply goes against the current call stack.
+
+Before we look at how validateLookupAPI is implemented,  lets look at how we create the
+set of permissions that are necessary for the caller to be allowed to use the lookup API.
+Firstly, we create a RuntimePermission for a particular package by calling this
+method:
+ 
+```java
+    private final static String ACCESS_IN_PACKAGE = "accessClassInPackage.";
+    
+    private static Permission getLookupPermission(String packName) {
+        RuntimePermission retVal = new RuntimePermission(ACCESS_IN_PACKAGE + packName);
+        
+        return retVal;
+    }
+```
+
+The above code will create the Permission that needs to be checked to see if the
+caller should have access to the passed in package.
+
+When dealing with an [ActiveDescriptor][activedescriptor],
+we want to be sure that the caller has the right to access all of the contracts which
+that service advertises.  Hence we create a method that returns all of the permissions
+that must be checked based on all of the contracts that the
+[ActiveDescriptor][activedescriptor] advertises.
+Here is the implementation of a method that returns a list of all permissions that
+must be allowed in order to access that [ActiveDescriptor][activedescriptor]:
+ 
+```java
+    private static List<Permission> getLookupPermissions(ActiveDescriptor<?> ad) {
+        LinkedList<Permission> retVal = new LinkedList<Permission>();
+        
+        for (String contract : ad.getAdvertisedContracts()) {
+            int index = contract.lastIndexOf('.');
+            String packName = contract.substring(0, index);
+            retVal.add(getLookupPermission(packName));
+        }
+        
+        return retVal;
+    }
+```
+
+Forearmed with the above methods, we can now look at how the method which
+checks whether or not the lookup should be authorized.  Here is the implementation
+of validateLookupAPI:
+ 
+```java
+    private boolean validateLookupAPI(ActiveDescriptor<?> candidate) {
+        List<Permission> lookupPermissions = getLookupPermissions(candidate);
+     
+        for (Permission lookupPermission : lookupPermissions) {
+            if (!checkPerm(lookupPermission)) {
+                if (VERBOSE) {
+                    System.out.println("candidate " + candidate +
+                        " LOOKUP FAILED the security check for permission " + lookupPermission);
+                }
+                return false;
+            }
+        }
+        
+        return true;
+    }
+```
+
+This is a strait-forward implementation, simply ensuring with the checkPerm call that
+the caller is allowed to access all of the contracts offered by the given candidate
+[ActiveDescriptor][activedescriptor].
+
+That leaves us with the case of the lookup being performed on behalf of an injection
+point.  This sort of lookup might be done because of some system code, or on the behalf
+of a chain of instantiations being done due to a dependency chain.  Hence, it may
+not be the case that the proper protection domain is on the calling stack.  So
+in this case we must use the protection domain of the injection point in order to
+see whether or not the code representing the injection point itself has the
+proper permissions.
+
+Here is the implementation of the validateInjection method:
+  
+```java
+    private boolean validateInjection(ActiveDescriptor<?> candidate, Injectee injectee) {
+        List<Permission> lookupPermissions = getLookupPermissions(candidate);
+        
+        // If this is an Inject, get the protection domain of the injectee
+        final Class<?> injecteeClass = injectee.getInjecteeClass();
+        
+        ProtectionDomain pd = AccessController.doPrivileged(new PrivilegedAction<ProtectionDomain>() {
+
+            @Override
+            public ProtectionDomain run() {
+                return injecteeClass.getProtectionDomain();
+            }
+            
+        });
+        
+        for (Permission lookupPermission : lookupPermissions) {
+            if (!pd.implies(lookupPermission)) {
+                if (VERBOSE) {
+                    System.out.println("candidate " + candidate + " injectee " + injectee +
+                        " LOOKUP FAILED the security check for " + lookupPermission);
+                }
+                
+                return false;
+            }
+        }
+        
+        return true;
+    }
+```
+
+This method first gets the set of permissions that the protection domain must have using
+the getLookupPermissions method.  It then gets the ProtectionDomain of the injectee
+by getting the ProtectionDomain from the Class of the injection point.  It should be noted
+that getting the ProtectionDomain from the Class is itself a priviliged operation, and hence
+must be done inside a doPrivileged block, in order to ensure that only the rights of the
+system software are checked when getting the protection domain.
+
+The code then runs through the list of permissions that the ProtectionDomain of the [Injectee][injectee] must have in order for
+the injection to use an object produced by the [ActiveDescriptor][activedescriptor].
+
+This is the entire implementation of the security-lockdown validator, which will ensure that
+only those that have the rights to specific packages will be able to inject or lookup
+services from those packages, and that only those who have AllPermission will be able
+to bind or unbind services from the system.
+
+Note that the System Project has the following grant:
+ 
+```
+grant codeBase "file:${build.dir}/../../system/target/-" {
+  permission java.security.AllPermission;
+};
+```
+ 
+Now lets take a closer look at Alice and Mallory.
+ 
+### Alice
+
+Alice is a simple application that has a limited set of privileges.  Here are the exact
+priviliges that Alice is granted:
+ 
+```
+grant codeBase "file:${build.dir}/../../alice/target/-" {
+  permission java.lang.RuntimePermission "accessClassInPackage.javax.inject";
+  permission java.lang.RuntimePermission "accessClassInPackage.com.alice.application";
+  permission java.lang.RuntimePermission "accessClassInPackage.org.jvnet.hk2.annotations";
+  permission java.lang.RuntimePermission "accessClassInPackage.org.acme.security";
+};
+```
+
+One thing that will distinguish Alice from Mallory is that Alice has access to the
+org.acme.security package, whereas Mallory does not.  The means that Alice can
+inject the org.acme.security.AuditService into its services, while Mallory cannot.
+Here is the very simple AliceApp, which injects the AuditService:
+ 
+```java
+@Service @Singleton
+public class AliceApp {
+    @Inject
+    private AuditService auditor;
+    
+    /**
+     * This service makes use of the auditor service directly, which
+     * should be allowed as Alice itself has the ability to use the
+     * audit service
+     * 
+     * @param fromMe
+     */
+    public void doAuditedService(String fromMe) {
+        auditor.auditLog("Alice performed an audit for " + fromMe);
+    }
+}
+```
+
+The injection point for the AuditService will pass the validator code because Alice
+has access to org.acme.service package.  Now lets look at Mallory.
+ 
+### Mallory
+
+Mallory is another application, but unlike Alice, Mallory will sometimes attempt to do
+things which it is not allowed to do.  Since Mallory is less trusted by the administrator,
+Mallory has different grants:
+
+```
+grant codeBase "file:${build.dir}/../../mallory/target/-" {
+  permission java.lang.RuntimePermission "accessClassInPackage.javax.inject";
+  permission java.lang.RuntimePermission "accessClassInPackage.com.mallory.application";
+  permission java.lang.RuntimePermission "accessClassInPackage.com.alice.application";
+  permission java.lang.RuntimePermission "accessClassInPackage.org.jvnet.hk2.annotations";
+  permission java.lang.RuntimePermission "accessClassInPackage.org.glassfish.hk2.api";
+};
+```
+
+Note that Mallory does NOT have access to the org.acme.security package, and hence should
+not be able to inject or lookup anything from that package.
+
+Note that sometimes Mallory acts according to the rules, and other times he acts against the
+rules.  Lets look at the times Mallory acts according to the rules:
+ 
+```java
+@Service
+public class MalloryApp {
+    @Inject
+    private AliceApp alice;
+    
+    @Inject
+    private ServiceLocator locator;
+    
+    ...
+    
+    public void doAnApprovedOperation() {
+        alice.doAuditedService("Mallory");
+    }
+    
+    ...
+}
+```
+
+Mallory injects both the ServiceLocator itself as well as the AliceApp.  Since Mallory has
+been granted those rights, these injections are Validated by the Validator and found to be
+perfectly OK.  Hence this service can properly be instantiated.
+
+Now lets see what Mallory might try to do that it shouldn't.  In this case, Mallory attempts
+to look up the AuditService, which he should not be allowed to do:
+ 
+```java
+    /**
+     * Mallory cannot however lookup the AuditService himself!
+     */
+    public void tryToGetTheAuditServiceMyself() {
+        Object auditService = locator.getBestDescriptor(BuilderHelper.createContractFilter(
+            "org.acme.security.AuditService"));
+        auditService.toString();  // This should NPE!
+    }
+```
+
+Note that in this code that tricky fellow Mallory used a pure string representation of the
+fully qualified class name of the AuditService, since the system would not have allowed him
+access to the AuditService otherwise.  The code above will NPE when the auditService.toString()
+method is called.  As far as this lookup is concerned, it acts as though there is no AuditService
+to be had, rather than throwing some other form of exception (which might tell Mallory something
+about the system).
+
+In this method, Mallory will attempt to advertise a service:
+ 
+```java
+    /**
+     * Mallory cannot advertise the EvilService
+     */
+    public void tryToAdvertiseAService() {
+        DynamicConfigurationService dcs = locator.getService(DynamicConfigurationService.class);
+        DynamicConfiguration config = dcs.createDynamicConfiguration();
+        
+        config.addActiveDescriptor(EvilService.class);
+        
+        config.commit();  // This will throw a MultiException
+    }
+```
+
+Since Mallory does not have the rights to advertise a service the commit call will throw
+an exception.
+
+In this method, Mallory will attempt to unadvertise the ServiceLocator itself!!!  That
+can't be allowed, or the very fabric of space-time could be threatened:
+ 
+```java
+    /**
+     * Mallory cannot un-advertise ServiceLocator!
+     */
+    public void tryToUnAdvertiseAService() {
+        final Descriptor locatorService = locator.getBestDescriptor(
+            BuilderHelper.createContractFilter(ServiceLocator.class.getName()));
+        
+        // This filter matches ServiceLocator itself!
+        Filter unbindFilter = new Filter() {
+
+            @Override
+            public boolean matches(Descriptor d) {
+                if (d.getServiceId().equals(locatorService.getServiceId())) {
+                    if (d.getLocatorId().equals(locator.getLocatorId())) {
+                        return true;
+                    }
+                }
+                
+                return false;
+            }
+            
+        };
+        
+        DynamicConfigurationService dcs = locator.getService(DynamicConfigurationService.class);
+        DynamicConfiguration config = dcs.createDynamicConfiguration();
+        
+        config.addUnbindFilter(unbindFilter);
+        
+        config.commit();  // This will throw a MultiException
+    }
+```
+
+Again, since Mallory does not have the right to unbind services from the registry, the
+commit method will throw an exception and the entire operation will fail.
+
+In the next act of evil that Mallory attempts to perpetrate, it will try to instantiate this
+service:
+ 
+```java
+@Service @Singleton
+public class EvilInjectedService {
+    @Inject
+    private AuditService auditor;
+    
+    public EvilInjectedService() {
+        throw new AssertionError("This should never get called since AuditService is not available");
+    }
+
+}
+```
+
+In this case Mallory is not doing a direct API lookup of the AuditService, but rather the
+EvilInjectedService is trying to simply inject the service into itself, hoping that this
+mode of access would be allowed.  Unfortunately, Mallory has no such luck in this method
+of MalloryApp:
+ 
+```java
+    /**
+     * Tries to instantiate a service with an illegal injection point
+     */
+    public void tryToInstantiateAServiceWithABadInjectionPoint() {
+        locator.getService(EvilInjectedService.class);  // Will throw MultiException
+    }
+```
+
+In this case the system will attempt to instatiate the EvilInjectedService and will fail,
+since the EvilInjectedService does not have the rights to inject the AuditService.
+
+That's it for Mallory!  Mallory was allowed to perform the operations he was allowed to
+perform, and was not allowed to perform the operations for which it does not have the
+proper set of priviliges.
+
+The last project in the example is the runner.
+ 
+## The Runner Project
+
+The Runner project runs a set of junit tests that ensures that the System project, the Alice
+project and the Mallory project runs as expected.  The test case ensures that both the
+AliceApp and MalloryApp come up, and that when Mallory tries to do things that he should not
+do that he is properly rebuffed.  The most interesting thing in the Runner project is in the
+pom.xml, which gives the information that is needed to run the security-lockdown example
+with the java security manager enabled.  This is from the pom.xml:
+ 
+```xml
+<plugin>
+  <groupId>org.apache.maven.plugins</groupId>
+  <artifactId>maven-surefire-plugin</artifactId>
+  <configuration>
+    <argLine>-Dlocal.repo=${settings.localRepository}
+             -Dbuild.dir=${project.build.directory}
+             -Djava.security.manager
+             -Djava.security.policy=${project.build.directory}/test-classes/policy.txt
+    </argLine>
+    <!-- -Djava.security.debug=access,failure,domain -->
+    </configuration>
+</plugin>
+```
+
+The other interesting file in the Runner project is the policy.txt, which gives the full
+set of grants necessary to run this test properly.
+ 
+## Conclusion
+
+This example shows how a secure system can be built in HK2 given the tools provided.  In
+a real use case other decisions can be made about how to validate the operations being
+performed.  This example is here to illustrate how those decisions can be put into effect, not
+what those decisions should be.
+
+[servicelocator]: apidocs/org/glassfish/hk2/api/ServiceLocator.html
+[validationservice]: apidocs/org/glassfish/hk2/api/ValidationService.html
+[validator]: apidocs/org/glassfish/hk2/api/Validator.html
+[filter]: apidocs/org/glassfish/hk2/api/Filter.html
+[buildhelper]: apidocs/org/glassfish/hk2/utilities/BuilderHelper.html
+[dynamicconfiguration]: apidocs/org/glassfish/hk2/api/DynamicConfiguration.html
+[activedescriptor]: apidocs/org/glassfish/hk2/api/ActiveDescriptor.html
diff --git a/docs/sitemap.md b/docs/sitemap.md
new file mode 100644
index 0000000..d33bc47
--- /dev/null
+++ b/docs/sitemap.md
@@ -0,0 +1,40 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+
+# Site Map
+
++ [aop-default](aop-default.html)
++ [aop-example](aop-example.html)
++ [api-overview](api-overview.html)
++ [configuration-example](configuration-example.html)
++ [configuration-xml-example](configuration-xml-example.html)
++ [configuration](configuration.html)
++ [ctm-example](ctm-example.html)
++ [custom-resolver-example](custom-resolver-example.html)
++ [events](events.html)
++ [extensibility](extensibility.html)
++ [getting-started](getting-started.html)
++ [guice-bridge](guice-bridge.html)
++ [index](index.html)
++ [inhabitant-generator](inhabitant-generator.html)
++ [integration](integration.html)
++ [introduction](introduction.html)
++ [operations](operations.html)
++ [runlevel](runlevel.html)
++ [security-lockdown-example-runner](security-lockdown-example-runner.html)
++ [spring-bridge](spring-bridge.html)
++ [threaded-events-example](threaded-events-example.html)
diff --git a/docs/spring-bridge.md b/docs/spring-bridge.md
new file mode 100644
index 0000000..67a1677
--- /dev/null
+++ b/docs/spring-bridge.md
@@ -0,0 +1,247 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+* TOC
+{:toc}
+
+# The Spring/HK2 Bridge
+
+The Spring/HK2 Bridge can be used to inject [Spring][spring] services
+into HK2 services or inject HK2 services into [Spring][spring] services.
+
+## Definitions
+
++ A [Spring][spring] service is a service that is instantiated (created) by [Spring][spring]
++ An HK2 service is a service that is instantiated (created) by HK2
+ 
+## Injecting Spring services into HK2 services
+
+[Spring][spring] services can be injected into any injection point in HK2.
+In order to do this you must tell HK2 about the [Spring][spring] [BeanFactory][beanfactory]
+which has the [Spring][spring] bean definitions. This is accomplished in two steps.
+ 
+In the first step you should have the [ServiceLocator][servicelocator] that contains services
+you wish to be injected with [Spring][spring] services.
+You must initialize this [ServiceLocator][servicelocator] with some required Spring/HK2 bridge services.
+You can do this using the utility class [SpringBridge][springbridge].
+This is a code snippet that initializes a [ServiceLocator][servicelocator]:
+
+```java
+  SpringBridge.getSpringBridge().initializeSpringBridge(aServiceLocator);
+```
+
+In the second step you must tell your initialized [ServiceLocator][servicelocator] about the
+specific [Spring][spring] [BeanFactory][beanfactory] that you want it to look for services in.
+You do this with the [SpringIntoHK2Bridge][springintohk2bridge] service that was added in the previous step.
+The following code snippet adds a [Spring][spring] [BeanFactory][beanfactory] to be searched for services when injecting into HK2 services:
+ 
+```java
+  public void tieBeanFactoryToLocator(ServiceLocator aServiceLocator, BeanFactory springFactory) {
+      SpringIntoHK2Bridge springBridge = aServiceLocator.getService(SpringIntoHK2Bridge.class);
+      springBridge.bridgeSpringBeanFactory(springFactory);
+  }
+```
+
+ Any [Spring][spring] [BeanFactory][beanfactory] added with the bridgeSpringBeanFactory method
+ will be searched for services that HK2 cannot otherwise find.
+ 
+ For example, if you have a service called SpringService that is created by
+ [Spring][spring], you can inject it into an HK2 service
+ (called HK2Service) like this:
+ 
+```java
+  @Service
+  public class HK2Service {
+      @Inject
+      private SpringService springService;
+  }
+```
+
+## Injecting HK2 services into Spring services
+
+  HK2 services can be injected into [Spring][spring] services.  A HK2 service
+  can be injected into any place a normal Spring Bean can be injected.  For example, if you have an HK2 service
+  named HK2Service that is to be injected
+  into a [Spring][spring] service (called SpringService) your code
+  could look like this:
+
+```java
+  public class SpringService {
+      private HK2Service hk2Service;
+      
+      public void setHK2Service(HK2Service hk2Service) {
+          this.hk2Service = hk2Service;
+      }
+  }
+```
+
+  All HK2 services are in a [Spring][spring]
+  [Scope][scope]
+  that is usually named "hk2".  In order to do this we have provided an implementation of
+  [Scope][scope]
+  called
+  SpringScopeImpl.
+  SpringScopeImpl
+  is a [Spring][spring] service
+  that either takes a [ServiceLocator][servicelocator] instance
+  or the name of a [ServiceLocator][servicelocator] as attributes.
+  
+  This implementation of
+  [Scope][scope]
+  can be given to any [Spring][spring]
+  [ConfigurableBeanFactory][configurablebeanfactory].
+  The usual way this is done is in a [Spring][spring] beans.xml.  The following
+  stanza adds a
+  SpringScopeImpl
+  for a
+  [ServiceLocator][servicelocator] named HK2ToSpringTest
+  into a [Spring][spring] beans.xml:
+  
+```xml
+  <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
+      <property name="scopes">
+          <map>
+              <entry key="hk2">
+                  <bean class="org.jvnet.hk2.spring.bridge.api.SpringScopeImpl" >
+	                  <property name="ServiceLocatorName" value="HK2ToSpringTest" />
+	              </bean>
+              </entry>
+          </map>
+      </property>
+  </bean>
+```
+
+An HK2 service is then defined by adding it to the [Spring][spring] beans.xml by setting its scope to "hk2".
+The id of the HK2 service is formatted as per the utility API BuilderHelper.createTokenizedFilter.
+In the usual case this means that the id of the bean is the [Contract][contract] to be 
+looked up (though other things can be specified such as name or qualifiers).
+The following is an example [Spring][spring] beans.xml stanza that defines an HK2 service.
+  
+```xml
+    <bean id="org.jvnet.hk2.spring.bridge.test.hk2tospring.HK2Service"
+	      class="org.jvnet.hk2.spring.bridge.test.hk2tospring.HK2Service"
+	      scope="hk2" />
+```
+
+In the stanza above the scope was set to "hk2," implying that the HK2 SpringScopeImpl 
+will be used to lookup the bean.
+This bean can then be injected into any other [Spring][spring] bean in the normal way.
+The following stanza injects HK2Service into SpringService:
+  
+```xml
+    <bean id="SpringService" class="org.jvnet.hk2.spring.bridge.test.hk2tospring.SpringService">
+	  <property name="HK2Service" ref="org.jvnet.hk2.spring.bridge.test.hk2tospring.HK2Service" />
+	</bean>
+```
+
+To make it clear, the following is the entire [Spring][spring] beans.xml which injects HK2Service into SpringService:
+  
+```xml
+  <?xml version="1.0" encoding="UTF-8"?>
+  <beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+	
+	<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
+        <property name="scopes">
+            <map>
+                <entry key="hk2">
+                    <bean class="org.jvnet.hk2.spring.bridge.api.SpringScopeImpl" >
+	                  <property name="ServiceLocatorName" value="HK2ToSpringTest" />
+	                </bean>
+                </entry>
+            </map>
+        </property>
+    </bean>
+	
+	<bean id="org.jvnet.hk2.spring.bridge.test.hk2tospring.HK2Service"
+	      class="org.jvnet.hk2.spring.bridge.test.hk2tospring.HK2Service"
+	      scope="hk2" />
+ 
+	<bean id="SpringService" class="org.jvnet.hk2.spring.bridge.test.hk2tospring.SpringService">
+	  <property name="HK2Service" ref="org.jvnet.hk2.spring.bridge.test.hk2tospring.HK2Service" />
+	</bean>
+ 
+  </beans>
+```
+
+## Bi-Directional Spring/HK2 Bridge
+
+When using Spring and HK2 bi-directionally it is important to remember that Spring instantiates beans
+as soon as they are satisfied (i.e., as soon as all references are available).  This can make bootstrapping
+difficult as Spring may try to instantiate beans before they are available in HK2.  In order to avoid this
+you can use any of the methods Spring allows for lazy initialization.  The following Spring beans.xml
+file uses the lazy-init mechanism for this, but other mechanism (such as the use of proxies) can
+also be used.
+  
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+	
+	<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
+        <property name="scopes">
+            <map>
+                <entry key="hk2">
+                    <bean class="org.jvnet.hk2.spring.bridge.api.SpringScopeImpl" >
+	                  <property name="ServiceLocatorName" value="BiDirectionalSpringBridge" />
+	                </bean>
+                </entry>
+            </map>
+        </property>
+    </bean>
+	
+	<bean id="org.jvnet.hk2.spring.bridge.test.bidirectional.HK2Service1_0"
+	      class="org.jvnet.hk2.spring.bridge.test.bidirectional.HK2Service1_0"
+	      scope="hk2" 
+	      lazy-init="true"/>
+ 
+	<bean id="SpringService1_1"
+	      class="org.jvnet.hk2.spring.bridge.test.bidirectional.SpringService1_1"
+	      lazy-init="true">
+	  <property name="HK2Service1_0" ref="org.jvnet.hk2.spring.bridge.test.bidirectional.HK2Service1_0" />
+	</bean>
+	
+	<bean id="org.jvnet.hk2.spring.bridge.test.bidirectional.HK2Service1_2"
+	      class="org.jvnet.hk2.spring.bridge.test.bidirectional.HK2Service1_2"
+	      scope="hk2" 
+	      lazy-init="true"/>
+	      
+	<bean id="SpringService1_3"
+	      class="org.jvnet.hk2.spring.bridge.test.bidirectional.SpringService1_3"
+	      lazy-init="true">
+	  <property name="HK2Service1_2" ref="org.jvnet.hk2.spring.bridge.test.bidirectional.HK2Service1_2" />
+	</bean>
+ 
+</beans>
+```
+
+In the above example SpringService1_3 has HK2Service1_2 injected into it, while HK2Service1_2 has
+SpringService1_1 injected into it (though you can't see that in the XML stanza), and SpringService1_1
+has HK2Service1_0 injected into it.  Since everything in the beans.xml is lazily initialized you
+can start the Spring BeanFactory either before or after you initialize the ServiceLocator.
+
+[spring]: http://www.springsource.com/
+[beanfactory]: http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/beans/factory/BeanFactory.html
+[servicelocator]: apidocs/org/glassfish/hk2/api/ServiceLocator.html
+[contract]: apidocs/org/jvnet/hk2/annotations/Contract.html
+[configurablebeanfactory]: http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/config/ConfigurableBeanFactory.html
+[scope]: http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/config/Scope.html
+[springintohk2bridge]: apidocs/org/jvnet/hk2/spring/bridge/api/SpringIntoHK2Bridge.html
+[springbridge]: apidocs/org/jvnet/hk2/spring/bridge/api/SpringBridge.html
diff --git a/docs/threaded-events-example.md b/docs/threaded-events-example.md
new file mode 100644
index 0000000..986ea3b
--- /dev/null
+++ b/docs/threaded-events-example.md
@@ -0,0 +1,190 @@
+[//]: # " "
+[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
+[//]: # " http://www.eclipse.org/legal/epl-2.0. "
+[//]: # " "
+[//]: # " This Source Code may also be made available under the following Secondary "
+[//]: # " Licenses when the conditions for such availability set forth in the "
+[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
+[//]: # " version 2 with the GNU Classpath Exception, which is available at "
+[//]: # " https://www.gnu.org/software/classpath/license.html. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
+[//]: # " "
+
+* TOC
+{:toc}
+
+# Threaded Events Example
+
+This example will enhance the existing default HK2 event mechanism to deliver events to subscribers on a different thread from
+the publisher.
+
+## The Strategy
+
+The strategy for modifying the default behavior of the HK2 default eventing mechanism is to write our own implementation of
+[TopicDistributionService][topicdistributionservice] that uses the HK2 default service to delegate to in a different
+thread.
+
+Here is the implementation of the service.
+
+```java
+@Service @Singleton @Named @Rank(100)
+public class ThreadedEventDistributor implements TopicDistributionService {
+    @Inject @Named(TopicDistributionService.HK2_DEFAULT_TOPIC_DISTRIBUTOR)
+    private TopicDistributionService defaultDistributor;
+
+    @Override
+    public void distributeMessage(Topic<?> topic, Object message) {
+        Thread t = new Thread(new Distributor(topic, message), "TopicDistributor");
+        t.setDaemon(true);
+        
+        t.start();
+    }
+
+    private final class Distributor implements Runnable {
+        private final Topic<?> topic;
+        private final Object message;
+        
+        private Distributor(Topic<?> topic, Object message) {
+            this.topic = topic;
+            this.message = message;
+        }
+
+        @Override
+        public void run() {
+            defaultDistributor.distributeMessage(topic, message);            
+        }
+    }
+}
+```
+
+Lets take a look at this service in detail.  It is a service so it is annotated with [@Service][service].  By default an
+service annototated with [@Service][service] is put into the Singleton scope, so the @Singleton annotation is not necessary,
+but does not hurt and leads to more understandable code.  The service is also annotated with @Named which is a nice practice
+in case other implementations want to inject this specific [TopicDistributionService][topicdistributionservice] in order to
+customize it.  Perhaps the most important annotation on this class is the [@Rank][rank] annotation, since that will cause
+this service to have a higher rank than the default implementation.  This implies that when someone invokes the publish method
+of [Topic][topic] that it will be this service that gets invoked and not the default one.
+
+Now that we've assured ourselves that this implementation will get used rather than the default one we still want to delegate
+the work of finding and distributing the message to the default implementation.  To do this we @Inject the
+[TopicDistributionService][topicdistributionservice] with the specific name given to the HK2 default implementation.
+
+Armed with the default implementation we can now look at the distributeMessage method.  All it needs to do is
+start a new thread and give it the instance of the Distributor class with the Topic and message.  The Distributor
+does nothing in its run method other than call the default HK2 implementation.  But now the default HK2 distributeMethod method
+is being called on a separate thread than the caller.
+
+This is a useful extension if it is known that the subscriber might do something that takes a long time in its method or if there
+are other reasons to use a separate thread.
+
+## Testing
+
+The test code is very simple and just verifies that the subscriber is in fact on a different thread than the caller.  It does this
+by recording the thread id in its object.  The test then verifies that the thread id of the publisher and the thread id of the
+subscriber are different.
+
+This is the subscriber:
+
+```java
+@Service @Singleton
+public class EventSubscriberService {
+    private final Object lock = new Object();
+    private Long eventThreadId = null;
+    
+    /**
+     * This is the method that should get called on a different thread
+     * from the one the publisher used
+     * 
+     * @param event The event that was raised
+     */
+    @SuppressWarnings("unused")
+    private void eventSubscriber(@SubscribeTo Event event) {
+        synchronized (lock) {
+            eventThreadId = Thread.currentThread().getId();
+            
+            lock.notifyAll();
+        }
+        
+    }
+    
+    /**
+     * Returns the thread-id upon which the event was raised
+     * 
+     * @return the thread-id of the thread on which the event was raised
+     * @throws InterruptedException If the thread gets interrupted
+     */
+    public long getEventThread() throws InterruptedException {
+        synchronized (lock) {
+            while (eventThreadId == null) {
+                lock.wait();
+            }
+            
+            return eventThreadId;
+        }
+    }
+
+}
+```
+
+The publisher is very simple, just calling the publish method of the [Topic][topic] with a new Event:
+
+```java
+public class EventPublisherService {
+    @Inject
+    private Topic<Event> eventPublisher;
+    
+    /**
+     * Publishes the event on the callers thread
+     */
+    public void publishEvent() {
+        eventPublisher.publish(new Event());
+    }
+}
+```
+
+Here we can see the test, which simply ensures that the thread id of the publisher is not the same as the thread id
+of the subscriber:
+
+```java
+    @Test
+    public void testEventDeliveredOnADifferentThread() throws InterruptedException {
+        // Adds in the default event implementation
+        ServiceLocatorUtilities.enableTopicDistribution(locator);
+        
+        ServiceLocatorUtilities.addClasses(locator,
+                EventPublisherService.class,
+                EventSubscriberService.class,
+                ThreadedEventDistributor.class);
+        
+        EventSubscriberService subscriber = locator.getService(EventSubscriberService.class);
+        EventPublisherService publisher = locator.getService(EventPublisherService.class);
+        
+        // This is my current thread, should  NOT be the same thread as the subscriber method call
+        long myThreadId = Thread.currentThread().getId();
+        
+        // Publish the event
+        publisher.publishEvent();
+        
+        long subscriberThreadId = subscriber.getEventThread();
+        
+        Assert.assertNotSame("Should have had different threadId from " + myThreadId,
+                myThreadId, subscriberThreadId);
+    }
+```
+
+## Conclusion
+
+In this example we have shown how to override and enhance the default HK2 messaging provider.  The quality of service
+has been changed from being single threaded on the thread of the publisher to having the subscribers invoked on
+a separate thread altogether.
+
+It is left as an exercise for the reader to discover other qualities of service that can be modified in this way.
+
+[topicdistributionservice]: apidocs/org/glassfish/hk2/api/messaging/TopicDistributionService.html
+[topic]: apidocs/org/glassfish/hk2/api/messaging/Topic.html
+[service]: apidocs/org/jvnet/hk2/annotations/Service.html
+[rank]: apidocs/org/glassfish/hk2/api/Rank.html