Merge remote-tracking branch 'origin/master' into TOMEE-2966
diff --git a/container/openejb-junit/src/main/java/org/apache/openejb/junit/context/OpenEjbTestContext.java b/container/openejb-junit/src/main/java/org/apache/openejb/junit/context/OpenEjbTestContext.java
index 8242d06..28b5728 100644
--- a/container/openejb-junit/src/main/java/org/apache/openejb/junit/context/OpenEjbTestContext.java
+++ b/container/openejb-junit/src/main/java/org/apache/openejb/junit/context/OpenEjbTestContext.java
@@ -136,7 +136,9 @@
     @Override
     public void close() {
         try {
-            initialContext.close();
+            if(initialContext != null) {
+                initialContext.close();
+            }
         } catch (final NamingException e) {
             // ignored
         }
diff --git a/container/openejb-junit5-backward/LICENSE b/container/openejb-junit5-backward/LICENSE
new file mode 100644
index 0000000..10d7a73
--- /dev/null
+++ b/container/openejb-junit5-backward/LICENSE
@@ -0,0 +1,417 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+=================================================================================
+JUnit
+
+Eclipse Public License - v 1.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 code and
+         documentation 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 additions to
+the Program which: (i) are separate modules of software distributed in
+conjunction with the Program under their own license agreement, and (ii) are
+not derivative works of the Program. 
+
+"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,
+including all Contributors.
+
+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, in source code and object code form.
+
+      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 and
+object code 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. 
+
+3. REQUIREMENTS
+
+A Contributor may choose to distribute the Program in object code form under
+its own license agreement, provided that:
+
+      a) it complies with the terms and conditions of this Agreement; and
+
+      b) its license agreement:
+
+      i) effectively disclaims on behalf of all 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 Contributors all liability for
+damages, including direct, indirect, special, incidental and consequential
+damages, such as lost profits; 
+
+      iii) states that any provisions which differ from this Agreement are
+offered by that Contributor alone and not by any other party; and
+
+      iv) states that source code for the Program is available from such
+Contributor, and informs licensees how to obtain it in a reasonable manner on
+or through a medium customarily used for software exchange. 
+
+When the Program is made available in source code form:
+
+      a) it must be made available under this Agreement; and 
+
+      b) a copy of this Agreement must be included with each copy of the
+Program. 
+
+Contributors may not remove or alter any copyright notices contained within the
+Program.
+
+Each Contributor must identify itself as the originator of its Contribution, if
+any, in a manner that reasonably allows subsequent Recipients to identify the
+originator of the Contribution.
+
+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, 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, 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.
+
+This Agreement is governed by the laws of the State of New York and the
+intellectual property laws of the United States of America. No party to this
+Agreement will bring a legal action under this Agreement more than one year
+after the cause of action arose. Each party waives its rights to a jury trial
+in any resulting litigation. 
+
diff --git a/container/openejb-junit5-backward/NOTICE b/container/openejb-junit5-backward/NOTICE
new file mode 100644
index 0000000..a9f2f42
--- /dev/null
+++ b/container/openejb-junit5-backward/NOTICE
@@ -0,0 +1,9 @@
+
+Apache OpenEJB
+Copyright 1999-2014 The Apache OpenEJB development community
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+==========================================================
+junit - JUnit is a simple framework to write repeatable tests (http://junit.org/)
+License: Eclipse Public License - v 1.0
diff --git a/container/openejb-junit5-backward/pom.xml b/container/openejb-junit5-backward/pom.xml
new file mode 100644
index 0000000..bdd326a
--- /dev/null
+++ b/container/openejb-junit5-backward/pom.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>container</artifactId>
+        <groupId>org.apache.tomee</groupId>
+        <version>8.0.7-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>openejb-junit5-backward</artifactId>
+    <packaging>jar</packaging>
+    <name>TomEE :: Container :: JUnit 5 :: Backward Compatibility</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-api</artifactId>
+            <version>${junit.jupiter.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <version>${junit.jupiter.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>openejb-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>openejb-junit</artifactId>
+            <version>${project.version}</version>
+            <exclusions>
+                <!--Important: We do not want to include transient JUnit4 dependency here! -->
+                <exclusion>
+                    <groupId>junit</groupId>
+                    <artifactId>junit</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+    </dependencies>
+    <properties>
+        <tomee.build.name>${project.groupId}.container.junit5</tomee.build.name>
+        <netbeans.hint.license>openejb</netbeans.hint.license>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>${surefire.junit5.version}</version>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/OpenEjbExtension.java b/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/OpenEjbExtension.java
new file mode 100644
index 0000000..0cd2efc
--- /dev/null
+++ b/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/OpenEjbExtension.java
@@ -0,0 +1,61 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.junit5;
+
+import org.apache.openejb.junit.context.OpenEjbTestContext;
+import org.junit.jupiter.api.extension.AfterEachCallback;
+import org.junit.jupiter.api.extension.BeforeEachCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
+
+public class OpenEjbExtension implements BeforeEachCallback, AfterEachCallback {
+
+    private final String role;
+    private OpenEjbTestContext classTestContext;
+
+    public OpenEjbExtension() {
+        this(null);
+    }
+
+    public OpenEjbExtension(String role) {
+        this.role = role;
+    }
+
+    @Override
+    public void beforeEach(ExtensionContext extensionContext) throws Exception {
+        classTestContext = newTestContext(extensionContext, role);
+        classTestContext.configureTest(extensionContext.getTestInstance().get());
+    }
+
+    public OpenEjbTestContext newTestContext(ExtensionContext extensionContext, final String roleName) {
+        if (!extensionContext.getTestMethod().isPresent()) {
+            if (classTestContext == null) {
+                classTestContext = new OpenEjbTestContext(extensionContext.getTestClass().get());
+            }
+            return classTestContext;
+        } else {
+            return new OpenEjbTestContext(extensionContext.getTestMethod().get(), roleName);
+        }
+    }
+
+
+    @Override
+    public void afterEach(ExtensionContext extensionContext) throws Exception {
+        if (classTestContext != null) {
+            classTestContext.close();
+        }
+    }
+}
diff --git a/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/RunWithEjbContainer.java b/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/RunWithEjbContainer.java
new file mode 100644
index 0000000..0d0c6c9
--- /dev/null
+++ b/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/RunWithEjbContainer.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.junit5;
+
+import org.apache.openejb.junit5.jee.EjbContainerExtension;
+import org.apache.openejb.junit5.jee.transaction.TransactionExtension;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@ExtendWith(EjbContainerExtension.class)
+@ExtendWith(TransactionExtension.class)
+@Target(ElementType.TYPE)
+public @interface RunWithEjbContainer  {
+}
diff --git a/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/RunWithOpenEjb.java b/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/RunWithOpenEjb.java
new file mode 100644
index 0000000..d340f62
--- /dev/null
+++ b/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/RunWithOpenEjb.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.junit5;
+
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@ExtendWith(OpenEjbExtension.class)
+@Target(ElementType.TYPE)
+public @interface RunWithOpenEjb {
+}
diff --git a/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/jee/EjbContainerExtension.java b/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/jee/EjbContainerExtension.java
new file mode 100644
index 0000000..13bd310
--- /dev/null
+++ b/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/jee/EjbContainerExtension.java
@@ -0,0 +1,170 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.junit5.jee;
+
+import org.apache.openejb.Injector;
+import org.apache.openejb.OpenEJBException;
+import org.apache.openejb.OpenEjbContainer;
+import org.apache.openejb.injection.FallbackPropertyInjector;
+import org.apache.openejb.junit.jee.config.Properties;
+import org.apache.openejb.junit.jee.config.Property;
+import org.apache.openejb.junit.jee.config.PropertyFile;
+import org.apache.openejb.junit.jee.resources.TestResource;
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.osgi.client.LocalInitialContextFactory;
+import org.apache.openejb.testing.TestInstance;
+import org.apache.openejb.util.Classes;
+import org.junit.jupiter.api.extension.*;
+
+import javax.ejb.embeddable.EJBContainer;
+import javax.naming.Context;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Hashtable;
+import java.util.Optional;
+
+public class EjbContainerExtension implements AfterAllCallback, BeforeAllCallback, BeforeEachCallback {
+
+    private java.util.Properties properties;
+    private EJBContainer container;
+
+    @Override
+    public void beforeAll(ExtensionContext extensionContext) throws Exception {
+
+        Optional<Class<?>> oClazz = extensionContext.getTestClass();
+
+        if (!oClazz.isPresent()) {
+            throw new RuntimeException("Could not get class from extension context");
+        }
+        Class<?> clazz = oClazz.get();
+
+        properties = new java.util.Properties();
+
+        { // set caller first to let it be overridable by @Property
+            final StringBuilder b = new StringBuilder();
+            for (final Class<?> c : Classes.ancestors(clazz)) {
+                if (c != Object.class) {
+                    b.append(c.getName()).append(",");
+                }
+            }
+            b.setLength(b.length() - 1);
+            properties.put(OpenEjbContainer.Provider.OPENEJB_ADDITIONNAL_CALLERS_KEY, b.toString());
+        }
+
+        // default implicit config
+        {
+            try (final InputStream is = clazz.getClassLoader().getResourceAsStream("openejb-junit.properties")) {
+                if (is != null) {
+                    properties.load(is);
+                }
+            }
+        }
+
+        final PropertyFile propertyFile = clazz.getAnnotation(PropertyFile.class);
+        if (propertyFile != null) {
+            final String path = propertyFile.value();
+            if (!path.isEmpty()) {
+                InputStream is = null;
+                try {
+                    is = clazz.getClassLoader().getResourceAsStream(path);
+                    if (is == null) {
+                        final File file = new File(path);
+                        if (file.exists()) {
+                            is = new FileInputStream(file);
+                        } else {
+                            throw new OpenEJBException("properties resource '" + path + "' not found");
+                        }
+                    }
+
+                    properties.load(is);
+                } finally {
+                    if (is != null) {
+                        is.close();
+                    }
+                }
+
+            }
+        }
+
+        final Properties annotationConfig = clazz.getAnnotation(Properties.class);
+        if (annotationConfig != null) {
+            for (final Property property : annotationConfig.value()) {
+                properties.put(property.key(), property.value());
+            }
+        }
+
+        if (!properties.containsKey(Context.INITIAL_CONTEXT_FACTORY)) {
+            properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, LocalInitialContextFactory.class.getName());
+        }
+
+        container = EJBContainer.createEJBContainer(properties);
+    }
+
+    @Override
+    public void beforeEach(ExtensionContext extensionContext) throws Exception {
+        Class<?> clazz = extensionContext.getTestClass().isPresent()  ? extensionContext.getTestClass().get() : null;
+        Object test =  extensionContext.getTestInstance().isPresent() ? extensionContext.getTestInstance().get() : null;
+
+        if (clazz != null){
+
+            while (!Object.class.equals(clazz)) {
+                for (final Field field : clazz.getDeclaredFields()) {
+                    final TestResource resource = field.getAnnotation(TestResource.class);
+                    if (resource != null) {
+                        if (Context.class.isAssignableFrom(field.getType())) {
+                            field.setAccessible(true);
+                            field.set(Modifier.isStatic(field.getModifiers()) ? null : test, getContainer().getContext());
+                        } else if (Hashtable.class.isAssignableFrom(field.getType())) {
+                            field.setAccessible(true);
+                            field.set(Modifier.isStatic(field.getModifiers()) ? null : test, getProperties());
+                        } else if (EJBContainer.class.isAssignableFrom(field.getType())) {
+                            field.setAccessible(true);
+                            field.set(Modifier.isStatic(field.getModifiers()) ? null : test, getContainer());
+                        } else {
+                            throw new OpenEJBException("can't inject field '" + field.getName() + "'");
+                        }
+                    }
+                }
+                clazz = clazz.getSuperclass();
+            }
+        }
+
+        if (test != null) {
+            SystemInstance.get().setComponent(TestInstance.class, new TestInstance(test.getClass(), test));
+            SystemInstance.get().getComponent(FallbackPropertyInjector.class); // force eager init (MockitoInjector initialize everything in its constructor)
+            Injector.inject(test);
+        }
+    }
+
+    @Override
+    public void afterAll(ExtensionContext extensionContext) throws Exception {
+        if (container != null) {
+            container.close();
+        }
+    }
+
+    public java.util.Properties getProperties() {
+        return properties;
+    }
+
+    public EJBContainer getContainer() {
+        return container;
+    }
+}
diff --git a/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/jee/transaction/TransactionExtension.java b/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/jee/transaction/TransactionExtension.java
new file mode 100644
index 0000000..369f176
--- /dev/null
+++ b/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/jee/transaction/TransactionExtension.java
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.junit5.jee.transaction;
+
+import org.apache.openejb.core.transaction.JtaTransactionPolicyFactory;
+import org.apache.openejb.core.transaction.TransactionPolicy;
+import org.apache.openejb.core.transaction.TransactionType;
+import org.apache.openejb.junit.jee.transaction.Transaction;
+import org.apache.openejb.loader.SystemInstance;
+import org.junit.jupiter.api.extension.*;
+
+import javax.transaction.TransactionManager;
+import java.lang.reflect.Method;
+
+public class TransactionExtension implements AfterTestExecutionCallback {
+
+    @Override
+    public void afterTestExecution(ExtensionContext extensionContext) throws Exception {
+        final Method mtd = extensionContext.getTestMethod().get();
+        final Transaction tx = mtd.getAnnotation(Transaction.class);
+        if (tx != null) {
+            final TransactionManager transactionManager = SystemInstance.get().getComponent(TransactionManager.class);
+            final JtaTransactionPolicyFactory factory = new JtaTransactionPolicyFactory(transactionManager);
+            final TransactionPolicy policy = factory.createTransactionPolicy(TransactionType.RequiresNew);
+            if (tx.rollback()) {
+                policy.setRollbackOnly();
+            }
+            policy.commit();
+        }
+    }
+}
diff --git a/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/security/RunWithOpenEjbTestSecurity.java b/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/security/RunWithOpenEjbTestSecurity.java
new file mode 100644
index 0000000..2d1efb4
--- /dev/null
+++ b/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/security/RunWithOpenEjbTestSecurity.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.junit5.security;
+
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@ExtendWith(TestSecurityTemplateInvocationContextProvider.class)
+@Target(ElementType.TYPE)
+public @interface RunWithOpenEjbTestSecurity {
+}
diff --git a/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/security/TestSecurityTemplateInvocationContextProvider.java b/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/security/TestSecurityTemplateInvocationContextProvider.java
new file mode 100644
index 0000000..66ba44e
--- /dev/null
+++ b/container/openejb-junit5-backward/src/main/java/org/apache/openejb/junit5/security/TestSecurityTemplateInvocationContextProvider.java
@@ -0,0 +1,127 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.junit5.security;
+
+import org.apache.openejb.junit.TestSecurity;
+import org.apache.openejb.junit5.OpenEjbExtension;
+import org.junit.jupiter.api.extension.*;
+
+import javax.ejb.EJBAccessException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Stream;
+
+public class TestSecurityTemplateInvocationContextProvider implements TestTemplateInvocationContextProvider {
+    @Override
+    public boolean supportsTestTemplate(ExtensionContext extensionContext) {
+        return true;
+    }
+
+    @Override
+    public Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContexts(ExtensionContext extensionContext) {
+
+        TestSecurity testSecurity = null;
+        if (extensionContext.getTestMethod().isPresent() && extensionContext.getTestMethod().get().isAnnotationPresent(TestSecurity.class)) {
+            testSecurity = extensionContext.getTestMethod().get().getAnnotation(TestSecurity.class);
+        } else if (extensionContext.getTestClass().isPresent() && extensionContext.getTestClass().get().isAnnotationPresent(TestSecurity.class)) {
+            testSecurity = extensionContext.getTestClass().get().getAnnotation(TestSecurity.class);
+        }
+
+        if (testSecurity != null) {
+            String[] authorized = testSecurity.authorized();
+            String[] unauthorized = testSecurity.unauthorized();
+
+            List<TestTemplateInvocationContext> contexts = new ArrayList<>();
+
+            for (String role : authorized) {
+                contexts.add(invocationContext(role, true));
+            }
+            for (String role : unauthorized) {
+                contexts.add(invocationContext(role, false));
+            }
+
+            return contexts.stream();
+        } else {
+            //no security annotations present, go with the default invocation context
+
+
+           return Stream.of(new TestTemplateInvocationContext() {
+               @Override
+               public List<Extension> getAdditionalExtensions() {
+                   return Collections.singletonList(new OpenEjbExtension());
+               }
+           });
+        }
+
+    }
+
+
+    private TestTemplateInvocationContext invocationContext(String role, boolean authorized) {
+        return new TestTemplateInvocationContext() {
+
+            private boolean ejbAccessThrown = false;
+
+            @Override
+            public String getDisplayName(int invocationIndex) {
+                if(role.equals(TestSecurity.UNAUTHENTICATED)) {
+                    return "unauthenticated";
+                }
+                return role;
+            }
+
+            @Override
+            public List<Extension> getAdditionalExtensions() {
+                List<Extension> extensions = new ArrayList<>();
+
+                extensions.add(new TestExecutionExceptionHandler() {
+                    @Override
+                    public void handleTestExecutionException(ExtensionContext extensionContext, Throwable throwable) throws Throwable {
+                        if (!authorized) {
+                            if (throwable instanceof EJBAccessException) {
+                                //ok - this would be expected here, do not fail the test!
+                                ejbAccessThrown = true;
+                                return;
+                            } else {
+                                throw throwable;
+                            }
+                        }
+                        throw throwable;
+                    }
+                });
+
+                extensions.add(new AfterEachCallback() {
+                    @Override
+                    public void afterEach(ExtensionContext extensionContext) throws Exception {
+                        if (!authorized) {
+                            if (!ejbAccessThrown) {
+                                throw new RuntimeException("Expected 'EJBAccessException' but caught none.");
+                            }
+                        }
+                    }
+                });
+
+                extensions.add(new OpenEjbExtension(role));
+
+                return extensions;
+
+
+
+            }
+        };
+    }
+}
\ No newline at end of file
diff --git a/container/openejb-junit5-backward/src/main/resources/META-INF/default-openejb-test-config.properties b/container/openejb-junit5-backward/src/main/resources/META-INF/default-openejb-test-config.properties
new file mode 100644
index 0000000..d5afb6a
--- /dev/null
+++ b/container/openejb-junit5-backward/src/main/resources/META-INF/default-openejb-test-config.properties
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+java.naming.factory.initial=org.apache.openejb.core.LocalInitialContextFactory
+org.apache.openejb.junit.default-config=true
\ No newline at end of file
diff --git a/container/openejb-junit5-backward/src/main/resources/META-INF/openejb-test-login.config b/container/openejb-junit5-backward/src/main/resources/META-INF/openejb-test-login.config
new file mode 100644
index 0000000..e8624b0
--- /dev/null
+++ b/container/openejb-junit5-backward/src/main/resources/META-INF/openejb-test-login.config
@@ -0,0 +1,3 @@
+OpenEjbJunitSecurityRealm {
+    org.apache.openejb.junit.security.TestLoginModule required;
+};
diff --git a/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestClassConfigFile.java b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestClassConfigFile.java
new file mode 100644
index 0000000..7df2c1a
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestClassConfigFile.java
@@ -0,0 +1,54 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.openejb.junit5;
+
+import org.apache.openejb.junit.ContextConfig;
+import org.apache.openejb.junit.TestResource;
+import org.apache.openejb.junit.TestResourceTypes;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.util.Hashtable;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+
+@RunWithOpenEjb
+@ContextConfig(
+    configFile = "/META-INF/test-config.properties"
+)
+public class TestClassConfigFile {
+    @TestResource(TestResourceTypes.CONTEXT_CONFIG)
+    private Hashtable<String, String> contextConfig;
+
+    public TestClassConfigFile() {
+    }
+
+    @Test
+    public void testConfig() {
+        assertNotNull(contextConfig);
+
+        checkProperty("junit.test-property", "Test String");
+    }
+
+    private void checkProperty(final String key, final String expected) {
+        final String value = contextConfig.get(key);
+        assertEquals(expected, value);
+    }
+}
diff --git a/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestClassConfigFileAndProperties.java b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestClassConfigFileAndProperties.java
new file mode 100644
index 0000000..5f168bb
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestClassConfigFileAndProperties.java
@@ -0,0 +1,62 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.openejb.junit5;
+
+import org.apache.openejb.junit.ContextConfig;
+import org.apache.openejb.junit.Property;
+import org.apache.openejb.junit.TestResource;
+import org.apache.openejb.junit.TestResourceTypes;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.util.Hashtable;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+@RunWithOpenEjb
+@ContextConfig(
+    configFile = "/META-INF/test-config.properties",
+    properties = {
+        @Property("junit.test-property-override=New Value"),
+        @Property("junit.test-property-file-untrimmed=New Trimmed Value"),
+        @Property(" junit.test-property-file-trimmed = New Untrimmed Value ")
+    }
+)
+public class TestClassConfigFileAndProperties {
+    @TestResource(TestResourceTypes.CONTEXT_CONFIG)
+    private Hashtable<String, String> contextConfig;
+
+    public TestClassConfigFileAndProperties() {
+    }
+
+    @Test
+    public void testConfig() {
+        assertNotNull(contextConfig);
+
+        checkProperty("junit.test-property", "Test String");
+        checkProperty("junit.test-property-override", "New Value");
+        checkProperty("junit.test-property-file-untrimmed", "New Trimmed Value");
+        checkProperty("junit.test-property-file-trimmed", "New Untrimmed Value");
+    }
+
+    private void checkProperty(final String key, final String expected) {
+        final String value = contextConfig.get(key);
+        assertEquals(expected, value);
+    }
+}
diff --git a/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestClassConfigProperties.java b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestClassConfigProperties.java
new file mode 100644
index 0000000..dbf469e
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestClassConfigProperties.java
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.openejb.junit5;
+
+import org.apache.openejb.junit.ContextConfig;
+import org.apache.openejb.junit.Property;
+import org.apache.openejb.junit.TestResource;
+import org.apache.openejb.junit.TestResourceTypes;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.util.Hashtable;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+@RunWithOpenEjb
+@ContextConfig(
+    properties = {
+        @Property("java.naming.factory.initial=org.apache.openejb.core.LocalInitialContextFactory"),
+        @Property("junit.test-property=Test String from Properties"),
+        @Property("junit.test-empty-property="),
+        @Property("junit.test-null-property"),
+        @Property(" junit.test-trim-empty-property-key = "),
+        @Property(" junit.test-trim-null-property-key "),
+        @Property(" junit.test-trim-property-key-and-value = trimmed value ")
+    }
+)
+public class TestClassConfigProperties {
+    @TestResource(TestResourceTypes.CONTEXT_CONFIG)
+    private Hashtable<String, String> contextConfig;
+
+    public TestClassConfigProperties() {
+    }
+
+    @Test
+    public void testConfig() {
+        assertNotNull(contextConfig);
+
+        checkProperty("junit.test-property", "Test String from Properties");
+        checkProperty("junit.test-empty-property", "");
+        checkProperty("junit.test-null-property", "");
+        checkProperty("junit.test-trim-empty-property-key", "");
+        checkProperty("junit.test-trim-null-property-key", "");
+        checkProperty("junit.test-trim-property-key-and-value", "trimmed value");
+    }
+
+    private void checkProperty(final String key, final String expected) {
+        final String value = contextConfig.get(key);
+        assertEquals(expected, value);
+    }
+}
diff --git a/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestDualConfigOverride.java b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestDualConfigOverride.java
new file mode 100644
index 0000000..fe3de35
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestDualConfigOverride.java
@@ -0,0 +1,119 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.openejb.junit5;
+
+import org.apache.openejb.junit.ContextConfig;
+import org.apache.openejb.junit.Property;
+import org.apache.openejb.junit.TestResource;
+import org.apache.openejb.junit.TestResourceTypes;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.util.Hashtable;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+
+/**
+ * Here we test class level dual config, with method level overrides. We check some
+ * properties in all tests (even when not in it's config), to ensure overrides work
+ * properly, and also that context sharing doesn't happen.
+ */
+@RunWithOpenEjb
+@ContextConfig(
+    configFile = "/META-INF/test-config.properties",
+    properties = {
+        @Property("junit.test-property-override=New Class Property Value")
+    }
+)
+public class TestDualConfigOverride {
+    @TestResource(TestResourceTypes.CONTEXT_CONFIG)
+    private Hashtable<String, String> contextConfig;
+
+    public TestDualConfigOverride() {
+    }
+
+    @Test
+    public void testClassConfig() {
+        assertNotNull(contextConfig);
+
+        checkProperty("junit.test-property", "Test String");
+        checkProperty("junit.test-property-override", "New Class Property Value");
+        checkProperty("junit.test-property-override2", "Original Value 2");
+        checkProperty("junit.test-property-override3", "Original Value 3");
+        assertNull(contextConfig.get("junit.test-new-method-file-property"));
+        assertNull(contextConfig.get("junit.test-new-method-property"));
+    }
+
+    @Test
+    @ContextConfig(
+        configFile = "/META-INF/test-config-method.properties"
+    )
+    public void testMethodFileOverride() {
+        assertNotNull(contextConfig);
+
+        checkProperty("junit.test-property", "Test String");
+        checkProperty("junit.test-property-override", "New Class Property Value");
+        checkProperty("junit.test-property-override2", "New Method File Value 2");
+        checkProperty("junit.test-property-override3", "Original Value 3");
+        checkProperty("junit.test-new-method-file-property", "New Method Value");
+        assertNull(contextConfig.get("junit.test-new-method-property"));
+    }
+
+    @Test
+    @ContextConfig(
+        properties = {
+            @Property("junit.test-property-override3=New Method Property Value 3"),
+            @Property("junit.test-new-method-property=New Method Property Value")
+        }
+    )
+    public void testMethodPropertiesOverride() {
+        assertNotNull(contextConfig);
+
+        checkProperty("junit.test-property", "Test String");
+        checkProperty("junit.test-property-override", "New Class Property Value");
+        checkProperty("junit.test-property-override2", "Original Value 2");
+        checkProperty("junit.test-property-override3", "New Method Property Value 3");
+        checkProperty("junit.test-new-method-property", "New Method Property Value");
+        assertNull(contextConfig.get("junit.test-new-method-file-property"));
+    }
+
+    @Test
+    @ContextConfig(
+        configFile = "/META-INF/test-config-method.properties",
+        properties = {
+            @Property("junit.test-property-override2=New Method Property Value 2"),
+            @Property("junit.test-new-method-property=New Method Property Value")
+        }
+    )
+    public void testMethodDualOverride() {
+        assertNotNull(contextConfig);
+
+        checkProperty("junit.test-property", "Test String");
+        checkProperty("junit.test-property-override", "New Class Property Value");
+        checkProperty("junit.test-property-override2", "New Method Property Value 2");
+        checkProperty("junit.test-property-override3", "Original Value 3");
+        checkProperty("junit.test-new-method-file-property", "New Method Value");
+        checkProperty("junit.test-new-method-property", "New Method Property Value");
+    }
+
+    private void checkProperty(final String key, final String expected) {
+        final String value = contextConfig.get(key);
+        assertEquals(expected, value);
+    }
+}
diff --git a/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestEJBContainerExtensionDefaultConfig.java b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestEJBContainerExtensionDefaultConfig.java
new file mode 100644
index 0000000..fb2b31b
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestEJBContainerExtensionDefaultConfig.java
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.junit5;
+
+import org.apache.openejb.config.DeploymentFilterable;
+import org.apache.openejb.junit.jee.config.Properties;
+import org.apache.openejb.junit.jee.config.Property;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@Properties({
+    @Property(key = DeploymentFilterable.CLASSPATH_EXCLUDE, value = "jar:.*"),
+    @Property(key = DeploymentFilterable.CLASSPATH_INCLUDE, value = ".*openejb-junit5-backward.*")
+})
+@RunWithEjbContainer
+public class TestEJBContainerExtensionDefaultConfig {
+
+    @org.apache.openejb.junit.jee.resources.TestResource
+    private java.util.Properties props;
+
+    @Test
+    public void configIsHere() {
+        assertEquals("true", props.getProperty("implicit-config"));
+    }
+}
diff --git a/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestEJBContainerExtensionResources.java b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestEJBContainerExtensionResources.java
new file mode 100644
index 0000000..d5f6ea1
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestEJBContainerExtensionResources.java
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.junit5;
+
+import org.apache.openejb.config.DeploymentFilterable;
+import org.apache.openejb.junit.jee.config.Properties;
+import org.apache.openejb.junit.jee.config.Property;
+import org.junit.jupiter.api.Test;
+
+import javax.ejb.embeddable.EJBContainer;
+import javax.naming.Context;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+@Properties({ // just a small conf to go faster
+    @Property(key = DeploymentFilterable.CLASSPATH_EXCLUDE, value = "jar:.*"),
+    @Property(key = DeploymentFilterable.CLASSPATH_INCLUDE, value = ".*openejb-junit5-backward.*")
+})
+@RunWithEjbContainer
+public class TestEJBContainerExtensionResources {
+    @org.apache.openejb.junit.jee.resources.TestResource
+    private Context ctx;
+
+    @org.apache.openejb.junit.jee.resources.TestResource
+    private java.util.Properties props;
+
+    @org.apache.openejb.junit.jee.resources.TestResource
+    private EJBContainer container;
+
+    @Test
+    public void checkCtx() {
+        assertNotNull(ctx);
+    }
+
+    @Test
+    public void checkProps() {
+        assertNotNull(props);
+    }
+
+    @Test
+    public void checkContainer() {
+        assertNotNull(container);
+    }
+}
diff --git a/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestEJBContainerExtensionWithLocalEJB.java b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestEJBContainerExtensionWithLocalEJB.java
new file mode 100644
index 0000000..1662976
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestEJBContainerExtensionWithLocalEJB.java
@@ -0,0 +1,69 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.junit5;
+
+import org.apache.openejb.config.DeploymentFilterable;
+import org.apache.openejb.junit.jee.config.Properties;
+import org.apache.openejb.junit.jee.config.Property;
+import org.apache.openejb.junit5.ejbs.BasicEjbLocal;
+import org.junit.jupiter.api.Test;
+
+import javax.ejb.embeddable.EJBContainer;
+import javax.inject.Inject;
+import javax.naming.Context;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+
+@Properties({
+    @Property(key = DeploymentFilterable.CLASSPATH_EXCLUDE, value = "jar:.*"),
+    @Property(key = DeploymentFilterable.CLASSPATH_INCLUDE, value = ".*openejb-junit5-backward.*")
+})
+@RunWithEjbContainer
+public class TestEJBContainerExtensionWithLocalEJB {
+
+    @org.apache.openejb.junit.jee.resources.TestResource
+    private Context ctx;
+
+    @org.apache.openejb.junit.jee.resources.TestResource
+    private java.util.Properties props;
+
+    @org.apache.openejb.junit.jee.resources.TestResource
+    private EJBContainer container;
+
+    @Inject
+    private BasicEjbLocal ejb;
+
+    private void doChecks() {
+        assertNotNull(ctx);
+        assertNotNull(props);
+        assertNotNull(container);
+        assertNotNull(ejb);
+        assertEquals("a b", ejb.concat("a", "b"));
+    }
+
+    @Test
+    public void checkAllIsFine() {
+        doChecks();
+    }
+
+    @Test
+    public void checkAllIsStillFine() {
+        doChecks();
+    }
+}
diff --git a/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestEjbBasic.java b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestEjbBasic.java
new file mode 100644
index 0000000..6e934fe
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestEjbBasic.java
@@ -0,0 +1,73 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.openejb.junit5;
+
+import org.apache.openejb.api.LocalClient;
+import org.apache.openejb.junit.ContextConfig;
+import org.apache.openejb.junit.Property;
+import org.apache.openejb.junit5.ejbs.BasicEjbLocal;
+import org.apache.openejb.junit5.jee.EjbContainerExtension;
+import org.apache.openejb.junit5.jee.transaction.TransactionExtension;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import javax.ejb.EJB;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+
+@ContextConfig(properties = {
+    @Property("openejb.deployments.classpath.include=.*openejb-junit5-backward.*"),
+    @Property("java.naming.factory.initial=org.apache.openejb.core.LocalInitialContextFactory")
+})
+@RunWithOpenEjb
+@LocalClient
+public class TestEjbBasic {
+    @EJB
+    private BasicEjbLocal sampleEjb;
+
+    public TestEjbBasic() {
+    }
+
+    @Test
+    public void testEjbInjection() {
+        assertNotNull(sampleEjb);
+    }
+
+    @Test
+    public void testEjbInvocation() {
+        assertNotNull(sampleEjb);
+
+        final String object = sampleEjb.concat("Hello", "World");
+        assertEquals("Hello World", object);
+
+        final double root = sampleEjb.squareroot(81);
+        assertEquals(9, root, 0.0);
+    }
+
+    @Test
+    public void testEjbException() {
+        assertNotNull(sampleEjb);
+
+        try {
+            sampleEjb.squareroot(-1);
+            fail("Call must fail with exception.");
+        } catch (final Exception e) {
+        }
+    }
+}
diff --git a/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestEjbSecurity.java b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestEjbSecurity.java
new file mode 100644
index 0000000..76fd7f6
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestEjbSecurity.java
@@ -0,0 +1,198 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.openejb.junit5;
+
+import org.apache.openejb.api.LocalClient;
+import org.apache.openejb.junit.ContextConfig;
+import org.apache.openejb.junit.Property;
+import org.apache.openejb.junit.TestSecurity;
+import org.apache.openejb.junit5.ejbs.BasicEjbLocal;
+import org.apache.openejb.junit5.ejbs.SecuredEjbLocal;
+import org.apache.openejb.junit5.security.RunWithOpenEjbTestSecurity;
+import org.apache.openejb.junit5.security.TestSecurityTemplateInvocationContextProvider;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.TestTemplate;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import javax.ejb.EJB;
+import javax.ejb.EJBAccessException;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@ContextConfig(properties = {
+        @Property("openejb.deployments.classpath.include=.*openejb-junit5-backward.*"),
+        @Property("java.naming.factory.initial=org.apache.openejb.core.LocalInitialContextFactory")
+})
+@RunWithOpenEjbTestSecurity
+@TestSecurity(
+        authorized = {"RoleA"}
+)
+@LocalClient
+public class TestEjbSecurity {
+    @EJB
+    private BasicEjbLocal basicEjb;
+
+    @EJB
+    private SecuredEjbLocal securedEjb;
+
+    public TestEjbSecurity() {
+    }
+
+    @TestTemplate
+    public void testEjbInjection() {
+        assertNotNull(basicEjb);
+        assertNotNull(securedEjb);
+    }
+
+    @TestTemplate
+    public void testClassLevelSecurity() {
+        assertNotNull(securedEjb);
+
+        assertEquals("Unsecured Works", basicEjb.concat("Unsecured", "Works"));
+        assertEquals("Dual Role Works", securedEjb.dualRole());
+        assertEquals("RoleA Works", securedEjb.roleA());
+    }
+
+    @TestTemplate
+    public void testClassLevelSecurityUnauthorized() {
+        assertThrows(EJBAccessException.class, () -> {
+            assertNotNull(securedEjb);
+            securedEjb.roleB();
+        });
+    }
+
+    @TestTemplate
+    @TestSecurity(
+            authorized = {"RoleB"}
+    )
+    public void testMethodLevelSecurity() {
+        assertNotNull(securedEjb);
+
+        assertEquals("Unsecured Works", basicEjb.concat("Unsecured", "Works"));
+        assertEquals("Dual Role Works", securedEjb.dualRole());
+        assertEquals("RoleB Works", securedEjb.roleB());
+    }
+
+    @TestTemplate
+    @TestSecurity(
+            authorized = {"RoleB"}
+    )
+    public void testMethodLevelSecurityUnauthorized() {
+        assertThrows(EJBAccessException.class, () -> {
+            assertNotNull(securedEjb);
+            securedEjb.roleA();
+        });
+    }
+
+    @TestTemplate
+    @TestSecurity(
+            authorized = {"RoleA"},
+            unauthorized = {"RoleB"}
+    )
+    public void testMultipleSecurityRoles_RoleA() {
+        assertNotNull(securedEjb);
+        securedEjb.roleA();
+    }
+
+    @TestTemplate
+    @TestSecurity(
+            authorized = {"RoleB"},
+            unauthorized = {"RoleA"}
+    )
+    public void testMultipleSecurityRoles_RoleB() {
+        assertNotNull(securedEjb);
+        securedEjb.roleB();
+    }
+
+    /**
+     * This test was created to ensure that the statements are created correctly.
+     * They are constructed in such a way as to "incorrectly" specify the annotation
+     * options, and should fail with an access exception
+     */
+    @TestTemplate
+    @TestSecurity(
+            authorized = {"RoleB"}
+    )
+    public void testRoleAFailAuthorized() {
+        assertThrows(EJBAccessException.class, () -> {
+            assertNotNull(securedEjb);
+            securedEjb.roleA();
+        });
+    }
+
+    /**
+     * This test was created to ensure that the statements are created correctly.
+     * They are constructed in such a way as to "incorrectly" specify the annotation
+     * options, and should fail with an access exception
+     */
+    @TestTemplate
+    @TestSecurity(
+            authorized = {"RoleA"}
+    )
+    public void testRoleBFailAuthorized() {
+        assertThrows(EJBAccessException.class, () -> {
+            assertNotNull(securedEjb);
+            securedEjb.roleB();
+        });
+    }
+
+    /**
+     * This test was created to ensure that the statements are created correctly.
+     * They are constructed in such a way as to "incorrectly" specify the annotation
+     * options, and should fail with an access exception
+     */
+    @Disabled(value = "TODO: How to fix this in JUnit5?")
+    @TestTemplate
+    @TestSecurity(
+            unauthorized = {"RoleA"}
+    )
+    public void testRoleAFailUnauthorized() {
+        assertThrows(AssertionError.class, () -> {
+            securedEjb.roleA();
+        });
+    }
+
+    /**
+     * This test was created to ensure that the statements are created correctly.
+     * They are constructed in such a way as to "incorrectly" specify the annotation
+     * options, and should fail with an access exception
+     */
+    @Disabled(value = "TODO: How to fix this in JUnit5?")
+    @TestTemplate
+    @TestSecurity(
+            unauthorized = {"RoleB"}
+    )
+    public void testRoleBFailUnauthorized() {
+        assertThrows(AssertionError.class, () -> {
+            securedEjb.roleB();
+        });
+    }
+
+    /**
+     * This test was created to ensure that the statements are created correctly.
+     * They are constructed in such a way as to "incorrectly" specify the annotation
+     * options, and should fail with an access exception
+     */
+    @TestTemplate
+    @TestSecurity(
+            unauthorized = {TestSecurity.UNAUTHENTICATED}
+    )
+    public void testUnauthenticated() {
+        securedEjb.roleA();
+    }
+}
diff --git a/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestEjbSecurityRunTestAs.java b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestEjbSecurityRunTestAs.java
new file mode 100644
index 0000000..cf5b417
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestEjbSecurityRunTestAs.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+    * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.junit5;
+
+import org.apache.openejb.api.LocalClient;
+import org.apache.openejb.junit.ContextConfig;
+import org.apache.openejb.junit.Property;
+import org.apache.openejb.junit.RunTestAs;
+import org.apache.openejb.junit5.ejbs.BasicEjbLocal;
+import org.apache.openejb.junit5.ejbs.SecuredEjbLocal;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import javax.ejb.EJB;
+import javax.ejb.EJBAccessException;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+
+@ContextConfig(properties = {
+    @Property("openejb.deployments.classpath.include=.*openejb-junit5-backward.*"),
+    @Property("java.naming.factory.initial=org.apache.openejb.core.LocalInitialContextFactory")
+})
+@RunWithOpenEjb
+@RunTestAs("RoleA")
+@LocalClient
+public class TestEjbSecurityRunTestAs {
+    @EJB
+    private BasicEjbLocal basicEjb;
+
+    @EJB
+    private SecuredEjbLocal securedEjb;
+
+    public TestEjbSecurityRunTestAs() {
+    }
+
+    @Test
+    public void testEjbInjection() {
+        assertNotNull(basicEjb);
+        assertNotNull(securedEjb);
+    }
+
+    @Test
+    public void testClassLevelSecurity() {
+        assertNotNull(securedEjb);
+
+        assertEquals("Unsecured Works", basicEjb.concat("Unsecured", "Works"));
+        assertEquals("Dual Role Works", securedEjb.dualRole());
+        assertEquals("RoleA Works", securedEjb.roleA());
+
+        try {
+            securedEjb.roleB();
+            fail("Able to execute a method for which we shouldn't have access.");
+        } catch (final EJBAccessException e) {
+        }
+    }
+
+    @Test
+    @RunTestAs("RoleB")
+    public void testMethodLevelSecurity() {
+        assertNotNull(securedEjb);
+
+        assertEquals("Unsecured Works", basicEjb.concat("Unsecured", "Works"));
+        assertEquals("Dual Role Works", securedEjb.dualRole());
+        assertEquals("RoleB Works", securedEjb.roleB());
+
+        try {
+            securedEjb.roleA();
+            fail("Able to execute a method for which we shouldn't have access.");
+        } catch (final EJBAccessException e) {
+        }
+    }
+}
diff --git a/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestMethodConfigFile.java b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestMethodConfigFile.java
new file mode 100644
index 0000000..ea573c3
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestMethodConfigFile.java
@@ -0,0 +1,65 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.openejb.junit5;
+
+import org.apache.openejb.junit.ContextConfig;
+import org.apache.openejb.junit.TestResource;
+import org.apache.openejb.junit.TestResourceTypes;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.util.Hashtable;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@RunWithOpenEjb
+public class TestMethodConfigFile {
+    @TestResource(TestResourceTypes.CONTEXT_CONFIG)
+    private Hashtable<String, String> contextConfig;
+
+    /**
+     * We store it in a field to be sure that we check the same key in the 2 separate
+     * tests.
+     */
+    private static final String CHECK_PROPERTY = "junit.test-property";
+
+    public TestMethodConfigFile() {
+    }
+
+    @Test
+    @ContextConfig(
+        configFile = "/META-INF/test-config.properties"
+    )
+    public void testConfig() {
+        assertNotNull(contextConfig);
+
+        checkProperty(CHECK_PROPERTY, "Test String");
+    }
+
+    @Test
+    public void testConfigNotPresent() {
+        assertNotNull(contextConfig);
+
+        assertNull(contextConfig.get(CHECK_PROPERTY));
+    }
+
+    private void checkProperty(final String key, final String expected) {
+        final String value = contextConfig.get(key);
+        assertEquals(expected, value);
+    }
+}
diff --git a/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestMethodConfigProperties.java b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestMethodConfigProperties.java
new file mode 100644
index 0000000..0010d1f
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestMethodConfigProperties.java
@@ -0,0 +1,69 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.openejb.junit5;
+
+import org.apache.openejb.junit.ContextConfig;
+import org.apache.openejb.junit.Property;
+import org.apache.openejb.junit.TestResource;
+import org.apache.openejb.junit.TestResourceTypes;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.util.Hashtable;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@RunWithOpenEjb
+public class TestMethodConfigProperties {
+    @TestResource(TestResourceTypes.CONTEXT_CONFIG)
+    private Hashtable<String, String> contextConfig;
+
+    /**
+     * We store it in a field to be sure that we check the same key in the 2 separate
+     * tests.
+     */
+    private static final String CHECK_PROPERTY = "junit.test-property";
+
+    public TestMethodConfigProperties() {
+    }
+
+    @Test
+    @ContextConfig(
+        properties = {
+            @Property("java.naming.factory.initial=org.apache.openejb.core.LocalInitialContextFactory"),
+            @Property(CHECK_PROPERTY + "=Test String from Properties")
+        }
+    )
+    public void testConfig() {
+        assertNotNull(contextConfig);
+
+        checkProperty(CHECK_PROPERTY, "Test String from Properties");
+    }
+
+    @Test
+    public void testConfigNotPresent() {
+        assertNotNull(contextConfig);
+
+        assertNull(contextConfig.get(CHECK_PROPERTY));
+    }
+
+    private void checkProperty(final String key, final String expected) {
+        final String value = contextConfig.get(key);
+        assertEquals(expected, value);
+    }
+}
diff --git a/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestResourceEJBContainerExtension.java b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestResourceEJBContainerExtension.java
new file mode 100644
index 0000000..8585d88
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestResourceEJBContainerExtension.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.junit5;
+
+import org.apache.openejb.assembler.classic.Assembler;
+import org.apache.openejb.config.DeploymentFilterable;
+import org.apache.openejb.junit.jee.config.Properties;
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.spi.ContainerSystem;
+import org.junit.jupiter.api.Test;
+
+import javax.annotation.Resource;
+import javax.naming.NamingException;
+import javax.sql.DataSource;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+
+@Properties({
+    @org.apache.openejb.junit.jee.config.Property(key = DeploymentFilterable.CLASSPATH_EXCLUDE, value = "jar:.*"),
+    @org.apache.openejb.junit.jee.config.Property(key = DeploymentFilterable.CLASSPATH_INCLUDE, value = ".*openejb-junit5-backward.*"),
+    @org.apache.openejb.junit.jee.config.Property(key = "r", value = "new://Resource?type=DataSource")
+})
+@RunWithEjbContainer
+public class TestResourceEJBContainerExtension {
+
+    @Resource(name = "r")
+    private DataSource ds;
+
+    @Test
+    public void checkResource() throws NamingException {
+        assertEquals(ds,   SystemInstance.get().getComponent(ContainerSystem.class)
+                .getJNDIContext().lookup("java:" + Assembler.OPENEJB_RESOURCE_JNDI_PREFIX + "r"));
+    }
+}
diff --git a/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestWithCdiBean.java b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestWithCdiBean.java
new file mode 100644
index 0000000..aa43a24
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/TestWithCdiBean.java
@@ -0,0 +1,63 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.junit5;
+
+import org.apache.openejb.config.DeploymentFilterable;
+import org.apache.openejb.junit.jee.config.Properties;
+import org.apache.openejb.junit.jee.config.Property;
+import org.junit.jupiter.api.Test;
+
+import javax.ejb.EJB;
+import javax.ejb.Stateless;
+import javax.inject.Inject;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+
+@Properties({ // just a small conf to go faster
+    @Property(key = DeploymentFilterable.CLASSPATH_EXCLUDE, value = "jar:.*"),
+    @Property(key = DeploymentFilterable.CLASSPATH_INCLUDE, value = ".*openejb-junit5-backward.*")
+})
+@RunWithEjbContainer
+public class TestWithCdiBean {
+    @Inject
+    private CdiBean cdi;
+
+    @Inject
+    private EjbBean ejb;
+
+    @EJB
+    private EjbBean ejb2;
+
+    @Test
+    public void checkCDIInjections() {
+        assertNotNull(cdi);
+        assertNotNull(ejb);
+    }
+
+    @Test
+    public void checkEJBInjection() {
+        assertNotNull(ejb2);
+    }
+
+    public static class CdiBean {
+    }
+
+    @Stateless
+    public static class EjbBean {
+    }
+}
diff --git a/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/ejbs/BasicEjb.java b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/ejbs/BasicEjb.java
new file mode 100644
index 0000000..067b7f8
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/ejbs/BasicEjb.java
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.openejb.junit5.ejbs;
+
+import javax.ejb.Stateless;
+
+@Stateless
+public class BasicEjb implements BasicEjbLocal {
+    public String concat(final String s1, final String s2) {
+        return s1 + " " + s2;
+    }
+
+    public double squareroot(final double n) {
+        if (n < 0) {
+            throw new IllegalArgumentException("Number cannot be negative");
+        }
+
+        return Math.sqrt(n);
+    }
+}
diff --git a/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/ejbs/BasicEjbLocal.java b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/ejbs/BasicEjbLocal.java
new file mode 100644
index 0000000..d752f27
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/ejbs/BasicEjbLocal.java
@@ -0,0 +1,27 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.openejb.junit5.ejbs;
+
+import javax.ejb.Local;
+
+@Local
+public interface BasicEjbLocal {
+    String concat(String s1, String s2);
+
+    double squareroot(double n);
+}
diff --git a/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/ejbs/SecuredEjb.java b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/ejbs/SecuredEjb.java
new file mode 100644
index 0000000..b3c92bc
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/ejbs/SecuredEjb.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.openejb.junit5.ejbs;
+
+import javax.annotation.security.RolesAllowed;
+import javax.ejb.Stateless;
+
+@Stateless
+@RolesAllowed({"RoleA", "RoleB"})
+public class SecuredEjb implements SecuredEjbLocal {
+    public String dualRole() {
+        return "Dual Role Works";
+    }
+
+    @RolesAllowed({"RoleA"})
+    public String roleA() {
+        return "RoleA Works";
+    }
+
+    @RolesAllowed({"RoleB"})
+    public String roleB() {
+        return "RoleB Works";
+    }
+}
diff --git a/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/ejbs/SecuredEjbLocal.java b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/ejbs/SecuredEjbLocal.java
new file mode 100644
index 0000000..bc3fbb6
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/java/org/apache/openejb/junit5/ejbs/SecuredEjbLocal.java
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.openejb.junit5.ejbs;
+
+import javax.ejb.Local;
+
+@Local
+public interface SecuredEjbLocal {
+    String dualRole();
+
+    String roleA();
+
+    String roleB();
+}
diff --git a/container/openejb-junit5-backward/src/test/resources/META-INF/beans.xml b/container/openejb-junit5-backward/src/test/resources/META-INF/beans.xml
new file mode 100644
index 0000000..5ce485a
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/resources/META-INF/beans.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<beans xmlns="http://java.sun.com/xml/ns/javaee"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd" />
diff --git a/container/openejb-junit5-backward/src/test/resources/META-INF/ejb-jar.xml b/container/openejb-junit5-backward/src/test/resources/META-INF/ejb-jar.xml
new file mode 100644
index 0000000..3c3de1c
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/resources/META-INF/ejb-jar.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<ejb-jar/>
\ No newline at end of file
diff --git a/container/openejb-junit5-backward/src/test/resources/META-INF/test-config-method.properties b/container/openejb-junit5-backward/src/test/resources/META-INF/test-config-method.properties
new file mode 100644
index 0000000..a7c32b9
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/resources/META-INF/test-config-method.properties
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+junit.test-new-method-file-property=New Method Value
+junit.test-property-override2=New Method File Value 2
diff --git a/container/openejb-junit5-backward/src/test/resources/META-INF/test-config.properties b/container/openejb-junit5-backward/src/test/resources/META-INF/test-config.properties
new file mode 100644
index 0000000..fd0a9f7
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/resources/META-INF/test-config.properties
@@ -0,0 +1,23 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+java.naming.factory.initial=org.apache.openejb.core.LocalInitialContextFactory
+junit.test-property=Test String
+junit.test-property-override=Original Value
+junit.test-property-override2=Original Value 2
+junit.test-property-override3=Original Value 3
+junit.test-property-file-untrimmed = Original Untrimmed Value
+junit.test-property-file-trimmed=Original Trimmed Value
diff --git a/container/openejb-junit5-backward/src/test/resources/openejb-junit.properties b/container/openejb-junit5-backward/src/test/resources/openejb-junit.properties
new file mode 100644
index 0000000..9eab334
--- /dev/null
+++ b/container/openejb-junit5-backward/src/test/resources/openejb-junit.properties
@@ -0,0 +1,17 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+implicit-config = true
diff --git a/container/pom.xml b/container/pom.xml
index f9f52ad..9508572 100644
--- a/container/pom.xml
+++ b/container/pom.xml
@@ -36,7 +36,8 @@
     <module>openejb-javaagent</module>
     <module>openejb-jee</module>
     <module>openejb-jee-accessors</module>
-    <module>openejb-junit</module>
     <module>openejb-jpa-integration</module>
+    <module>openejb-junit</module>
+    <module>openejb-junit5-backward</module>
   </modules>
 </project>
diff --git a/pom.xml b/pom.xml
index 396e509..7a211bd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -98,6 +98,7 @@
     <maven.compiler.source>1.8</maven.compiler.source>
     <maven.compiler.target>1.8</maven.compiler.target>
     <surefire.version>2.21.0</surefire.version>
+    <surefire.junit5.version>3.0.0-M5</surefire.junit5.version>
 
     <!-- for the default name of the module. Needs to be overridden -->
     <tomee.build.name>${project.groupId}.${project.artifactId}</tomee.build.name>
@@ -190,6 +191,7 @@
     <org.apache.activemq.version>5.16.1</org.apache.activemq.version>
     <org.springframework.version>3.1.4.RELEASE</org.springframework.version>
     <junit.version>4.13.1</junit.version>
+    <junit.jupiter.version>5.7.0</junit.jupiter.version>
     <org.apache.axis2.version>1.4.1</org.apache.axis2.version>
     <scannotation.version>1.0.2</scannotation.version>
     <geronimo.connector.version>3.1.4</geronimo.connector.version>