Functional bi-directional links from javadocs to examples
diff --git a/src/main/java/org/apache/tomee/website/ApisUsed.java b/src/main/java/org/apache/tomee/website/ApisUsed.java
new file mode 100644
index 0000000..08d24a9
--- /dev/null
+++ b/src/main/java/org/apache/tomee/website/ApisUsed.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.tomee.website;
+
+import org.tomitribe.util.PrintString;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class ApisUsed {
+
+ private static final Pattern HEADER = Pattern.compile("\n=+ *apis +used *\n", Pattern.CASE_INSENSITIVE);
+
+ public static String insertHref(String source, final String link, final String linkText) {
+ source = normalize(source);
+
+ if (source.contains("\n= APIs Used\n")) {
+ return updateApiList(source, link, linkText);
+ } else {
+ return addApiList(source, link, linkText);
+ }
+ }
+
+ private static String addApiList(final String source, final String link, final String linkText) {
+ final PrintString out = new PrintString();
+ out.println("");
+ out.println("= APIs Used");
+ out.println("");
+ out.printf("- link:%s[%s]%n", link, linkText);
+
+ return source + out.toString();
+ }
+
+ private static String updateApiList(final String source, final String link, final String linkText) {
+ final int start = source.indexOf("\n= APIs Used\n");
+ final int end = ExampleLinks.min(source.indexOf("\n=", start + 1), source.length());
+ final String content = source.substring(start, end);
+
+ /*
+ * Do not add this link if there already one with the same title
+ */
+ if (content.contains(String.format("[%s]", linkText))) return source;
+
+ final String updated = content + String.format("- link:%s[%s]%n", link, linkText);
+
+ return source.replace(content, updated);
+ }
+
+ protected static String normalize(final String source) {
+ final Matcher matcher = HEADER.matcher(source);
+ if (!matcher.find()) return source;
+
+ return matcher.replaceAll("\n= APIs Used\n");
+ }
+}
diff --git a/src/main/java/org/apache/tomee/website/Configuration.java b/src/main/java/org/apache/tomee/website/Configuration.java
index 1b90fac..a182043 100644
--- a/src/main/java/org/apache/tomee/website/Configuration.java
+++ b/src/main/java/org/apache/tomee/website/Configuration.java
@@ -92,12 +92,12 @@
return new Source[]{
// new Source("https://github.com/apache/tomee.git", "master", "tomee-8.0"),
new Source("https://github.com/apache/tomee.git", "master", "tomee-9.0").label("milestone").related(microProfile2).related(jakartaEE9).javadoc("^org.apache.(openejb|tomee).*"),
- new Source("https://github.com/apache/tomee.git", "master", "tomee-8.0", true).related(microProfile2).related(jakartaEE8).javadoc("^org.apache.(openejb|tomee).*"),
- new Source("https://github.com/apache/tomee.git", "tomee-7.1.0", "tomee-7.1").javadoc("^org.apache.(openejb|tomee).*"),
- new Source("https://github.com/apache/tomee.git", "tomee-7.0.5", "tomee-7.0").javadoc("^org.apache.(openejb|tomee).*"),
- new Source("https://github.com/apache/tomee.git", "master", "master").javadoc("^org.apache.(openejb|tomee).*"),
- new Source("https://github.com/eclipse/microprofile-bom.git", "master", "microprofile-2.0").related(microProfile2).javadoc("^org.eclipse.microprofile.*"),
- new Source("https://github.com/eclipse-ee4j/jakartaee-platform.git", "v8", "jakartaee-8.0").related(jakartaEE8).javadoc("^javax.*"),
+// new Source("https://github.com/apache/tomee.git", "master", "tomee-8.0", true).related(microProfile2).related(jakartaEE8).javadoc("^org.apache.(openejb|tomee).*"),
+// new Source("https://github.com/apache/tomee.git", "tomee-7.1.0", "tomee-7.1").javadoc("^org.apache.(openejb|tomee).*"),
+// new Source("https://github.com/apache/tomee.git", "tomee-7.0.5", "tomee-7.0").javadoc("^org.apache.(openejb|tomee).*"),
+// new Source("https://github.com/apache/tomee.git", "master", "master").javadoc("^org.apache.(openejb|tomee).*"),
+// new Source("https://github.com/eclipse/microprofile-bom.git", "master", "microprofile-2.0").related(microProfile2).javadoc("^org.eclipse.microprofile.*"),
+// new Source("https://github.com/eclipse-ee4j/jakartaee-platform.git", "v8", "jakartaee-8.0").related(jakartaEE8).javadoc("^javax.*"),
new Source("https://github.com/eclipse-ee4j/jakartaee-platform.git", "master", "jakartaee-9.0").related(jakartaEE9).javadoc("^jakarta.*")
};
}
diff --git a/src/main/java/org/apache/tomee/website/SeeLinks.java b/src/main/java/org/apache/tomee/website/ExampleLinks.java
similarity index 64%
rename from src/main/java/org/apache/tomee/website/SeeLinks.java
rename to src/main/java/org/apache/tomee/website/ExampleLinks.java
index 9979361..0044a7a 100644
--- a/src/main/java/org/apache/tomee/website/SeeLinks.java
+++ b/src/main/java/org/apache/tomee/website/ExampleLinks.java
@@ -16,18 +16,26 @@
*/
package org.apache.tomee.website;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import org.tomitribe.swizzle.stream.StreamLexer;
+import org.tomitribe.util.IO;
+import org.tomitribe.util.Join;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
/**
- * Utility class to insert additional @see links into java source code.
+ * Utility class to insert additional @example links into java source code.
* If no Javadoc exists at the class level, some will be added.
+ *
+ * The @example tag is a custom javadoc tag that creates various "Examples" sections
+ * in the generated javadoc.
*/
-public class SeeLinks {
+public class ExampleLinks {
public static String insertHref(final String source, final String link, final String linkText) {
final int start = Math.max(source.lastIndexOf("\nimport "), source.indexOf("\npackage "));
- final int end = min(source.indexOf("\npublic "), source.indexOf("\n@"));
+ final int end = min(min(source.indexOf("\npublic "), source.indexOf("\n@")), source.indexOf("\nfinal"));
final String header = source.substring(start, end);
@@ -38,7 +46,10 @@
}
}
- private static int min(final int a, final int b) {
+ /**
+ * Returns the lowest viable index
+ */
+ public static int min(final int a, final int b) {
if (a == -1) return b;
if (b == -1) return a;
return Math.min(a, b);
@@ -46,7 +57,7 @@
private static String addComment(final String source, final String link, final String linkText, final String header) {
final String href = href(link, linkText);
- final String comment = header + "\n/**" + href + "\n */";
+ final String comment = header + "\n/**\n" + href + "\n */";
return source.replace(header, comment);
}
@@ -56,22 +67,27 @@
*/
if (header.contains(String.format(">%s</a>", linkText))) return source;
- final Pattern commentPattern = Pattern.compile("/\\*\\*(.*\n*)*?\n *\\*/");
- final Matcher matcher = commentPattern.matcher(header);
- if (!matcher.find()) return source;
-
- final String comment = matcher.group(0);
+ final StreamLexer lexer = new StreamLexer(IO.read(header));
+ final String comment;
+ try {
+ comment = lexer.readToken("/**", "*/");
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
final String href = href(link, linkText);
- final String updatedComment = comment.replaceFirst("(\n *\\*/)", href + "$1");
+ final List<String> lines = new ArrayList<>(Arrays.asList(comment.split("\n")));
+ lines.add(lines.size() - 1, href);
+
+ final String updatedComment = Join.join("\n", lines);
// TODO
return source.replace(comment, updatedComment);
}
private static String href(final String link, final String linkText) {
- final String href = String.format("\n * @see <a href=\"%s\">%s</a>", link, linkText);
+ final String href = String.format(" * @example <a href=\"%s\">%s</a>", link, linkText);
return href;
}
}
diff --git a/src/main/java/org/apache/tomee/website/Javadocs.java b/src/main/java/org/apache/tomee/website/Javadocs.java
index 5198e63..ae187d9 100644
--- a/src/main/java/org/apache/tomee/website/Javadocs.java
+++ b/src/main/java/org/apache/tomee/website/Javadocs.java
@@ -92,6 +92,8 @@
final File javadocOutput = sources.getGeneratedDestFor(source, "javadoc");
final ProcessBuilder cmd = new ProcessBuilder(
getJavadocCommand().getAbsolutePath(),
+ "-tag",
+ "example:a:Examples:",
"-sourcepath",
javaSources.getAbsolutePath(),
"-d",
diff --git a/src/main/java/org/apache/tomee/website/LearningLinks.java b/src/main/java/org/apache/tomee/website/LearningLinks.java
index 1f2614c..9f170f4 100644
--- a/src/main/java/org/apache/tomee/website/LearningLinks.java
+++ b/src/main/java/org/apache/tomee/website/LearningLinks.java
@@ -21,11 +21,14 @@
import org.tomitribe.tio.Match;
import org.tomitribe.tio.lang.JvmLang;
+import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -99,7 +102,60 @@
}
private void addApisUsed(final Example example, final List<String> apisUsed, final Map<String, JavadocSource> sources, final Source source) {
- // TODO
+ Collections.sort(apisUsed);
+
+ String content = null;
+ try {
+ content = IO.slurp(example.getDestReadme());
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+
+ final String basePath = pathToContentRoot(example.getDestReadme());
+
+ final List<JavadocSource> list = apisUsed.stream()
+ .map(sources::get)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+
+ for (JavadocSource javadocSource : list) {
+ final String link = String.format("%s%s/javadoc/%s.html",
+ basePath,
+ source.getName(),
+ javadocSource.getClassName().replace(".", "/"));
+
+ content = ApisUsed.insertHref(content, link, javadocSource.getClassName());
+ }
+
+ try {
+ IO.copy(IO.read(content), example.getDestReadme());
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ static String pathToContentRoot(final File file) {
+ final StringBuilder sb = new StringBuilder();
+
+ File parent = file;
+ while ((parent = parent.getParentFile()) != null && !parent.getName().equals("content")) {
+ sb.append("../");
+ }
+
+ return sb.toString();
+ }
+
+ static String pathFromContentRoot(final File file) {
+ final String absolutePath = file.getAbsolutePath();
+
+ final String content = "/content/";
+ final int indexOfContent = absolutePath.indexOf(content);
+
+ if (indexOfContent == -1) {
+ throw new IllegalStateException("Expected '/content/' section of path not found: " + absolutePath);
+ }
+
+ return absolutePath.substring(indexOfContent + content.length());
}
@@ -107,18 +163,23 @@
try {
final String content = IO.slurp(javadocSource.getSourceFile());
- // TODO this link won't resolve as-is, it needs to be relative
- final String link = example.getHref();
+ final String toContentRoot = pathToContentRoot(javadocSource.getSourceFile());
+ final String fromContentRoot = pathFromContentRoot(example.getDestReadme())
+ .replace(".adoc", ".html")
+ .replace(".md", ".html");
+
+ final String link = toContentRoot + fromContentRoot;
final String name = example.getName();
+
// Update the source contents to include an href link
- final String modified = SeeLinks.insertHref(content, link, name);
+ final String modified = ExampleLinks.insertHref(content, link, name);
// Overwrite the source with the newly linked version
IO.copy(IO.read(modified), javadocSource.getSourceFile());
- } catch (IOException e) {
- throw new UncheckedIOException("Unable to add link to example: " + example.getName(), e);
+ } catch (Exception e) {
+ throw new IllegalStateException("Unable to add link to java source: " + javadocSource.getSourceFile().getAbsolutePath(), e);
}
}
@@ -162,4 +223,5 @@
}
+
}
diff --git a/src/main/java/org/apache/tomee/website/Sources.java b/src/main/java/org/apache/tomee/website/Sources.java
index 579790d..b0bd03a 100644
--- a/src/main/java/org/apache/tomee/website/Sources.java
+++ b/src/main/java/org/apache/tomee/website/Sources.java
@@ -157,6 +157,7 @@
.flatMap(Source::stream)
.map(Source::getPerform)
.flatMap(Collection::stream)
+ .peek(runnable -> System.out.println("Running Hook " + runnable))
.forEach(Runnable::run);
VersionsIndex.prepare(this);
diff --git a/src/test/java/org/apache/tomee/website/ApisUsedTest.java b/src/test/java/org/apache/tomee/website/ApisUsedTest.java
new file mode 100644
index 0000000..6807e5b
--- /dev/null
+++ b/src/test/java/org/apache/tomee/website/ApisUsedTest.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.tomee.website;
+
+import org.junit.Test;
+
+import static org.apache.tomee.website.Scenario.scenario;
+import static org.junit.Assert.assertEquals;
+
+public class ApisUsedTest {
+
+
+ /**
+ * If an "APIs Used" section exists, but uses slightly different
+ * formatting, we should normalize it so it is consistent with
+ * all the other "APIs Used" sections
+ */
+ @Test
+ public void abnormalHeading() throws Exception {
+ final Scenario scenario = scenario(ApisUsedTest.class, "abnormalHeading");
+
+ final String input = scenario.get("before.adoc");
+
+ final String actual = ApisUsed.insertHref(input, "../../../jakartaee-9.0/javadoc/jakarta/persistence/EntityManager.html", "jakarta.persistence.EntityManager");
+
+ assertEquals(scenario.get("after.adoc"), actual);
+ }
+
+ /**
+ * If an "APIs Used" section exists in the middle of a document
+ * and therefore has sections after it, we should update the
+ * section where it lives and not move it or mistakenly append
+ * another "APIs Used" section.
+ */
+ @Test
+ public void hasOtherSections() throws Exception {
+ final Scenario scenario = scenario(ApisUsedTest.class, "hasOtherSections");
+
+ final String input = scenario.get("before.adoc");
+
+ final String actual = ApisUsed.insertHref(input, "../../../jakartaee-9.0/javadoc/jakarta/persistence/EntityManager.html", "jakarta.persistence.EntityManager");
+
+ assertEquals(scenario.get("after.adoc"), actual);
+ }
+
+ /**
+ * Very basic happy-path test to add an "APIs Used" section
+ * to a document that doesn't yet have one.
+ */
+ @Test
+ public void insertHref() throws Exception {
+ final Scenario scenario = scenario(ApisUsedTest.class, "insertHref");
+
+ final String input = scenario.get("before.adoc");
+
+ final String actual = ApisUsed.insertHref(input, "../../../jakartaee-9.0/javadoc/jakarta/persistence/Entity.html", "jakarta.persistence.Entity");
+
+ assertEquals(scenario.get("after.adoc"), actual);
+ }
+
+ /**
+ * We should be able to insert links into the "APIs Used"
+ * section in several different calls. The first call
+ * will add the section and the subsequent calls will
+ * update the now-existing section.
+ */
+ @Test
+ public void multipleInserts() throws Exception {
+ final Scenario scenario = scenario(ApisUsedTest.class, "multipleInserts");
+
+ final String input = scenario.get("before.adoc");
+
+ final String after1 = ApisUsed.insertHref(input,
+ "../../../jakartaee-9.0/javadoc/jakarta/persistence/Entity.html",
+ "jakarta.persistence.Entity");
+ assertEquals(scenario.get("after1.adoc"), after1);
+
+ final String after2 = ApisUsed.insertHref(after1,
+ "../../../jakartaee-9.0/javadoc/jakarta/persistence/EntityManager.html",
+ "jakarta.persistence.EntityManager");
+ assertEquals(scenario.get("after2.adoc"), after2);
+
+ final String after3 = ApisUsed.insertHref(after2,
+ "../../../jakartaee-9.0/javadoc/jakarta/persistence/Id.html",
+ "jakarta.persistence.Id");
+ assertEquals(scenario.get("after3.adoc"), after3);
+ }
+
+ /**
+ * If an API is already listed in the "APIs Used" section we should
+ * not add it again.
+ */
+ @Test
+ public void noDuplicates() throws Exception {
+ final Scenario scenario = scenario(ApisUsedTest.class, "noDuplicates");
+
+ final String input = scenario.get("before.adoc");
+
+ final String after1 = ApisUsed.insertHref(input, "../../../jakartaee-9.0/javadoc/jakarta/persistence/Entity.html", "jakarta.persistence.Entity");
+
+ assertEquals(scenario.get("after.adoc"), after1);
+
+ final String after2 = ApisUsed.insertHref(after1, "../../../jakartaee-8.0/javadoc/jakarta/persistence/Entity.html", "jakarta.persistence.Entity");
+
+ assertEquals(scenario.get("after.adoc"), after2);
+ }
+
+ @Test
+ public void normalize() throws Exception {
+ assertEquals("\n= APIs Used\n- link", ApisUsed.normalize("\n==== ApIs usEd\n- link"));
+ }
+
+}
diff --git a/src/test/java/org/apache/tomee/website/SeeLinksTest.java b/src/test/java/org/apache/tomee/website/ExampleLinksTest.java
similarity index 66%
rename from src/test/java/org/apache/tomee/website/SeeLinksTest.java
rename to src/test/java/org/apache/tomee/website/ExampleLinksTest.java
index e740239..3b15094 100644
--- a/src/test/java/org/apache/tomee/website/SeeLinksTest.java
+++ b/src/test/java/org/apache/tomee/website/ExampleLinksTest.java
@@ -25,18 +25,18 @@
import static org.junit.Assert.assertEquals;
@Ignore
-public class SeeLinksTest {
+public class ExampleLinksTest {
/**
* Test we can insert an @see link into some code that already has some javadoc
*/
@Test
public void insertHref() throws IOException {
- final Scenario scenario = scenario(SeeLinksTest.class, "insertHref");
+ final Scenario scenario = scenario(ExampleLinksTest.class, "insertHref");
final String input = scenario.get("before.java");
- final String actual = SeeLinks.insertHref(input, "http://example.org/orange.html", "Orange Example");
+ final String actual = ExampleLinks.insertHref(input, "http://example.org/orange.html", "Orange Example");
assertEquals(scenario.get("after.java"), actual);
}
@@ -46,11 +46,11 @@
*/
@Test
public void noJavadoc() throws IOException {
- final Scenario scenario = scenario(SeeLinksTest.class, "noJavadoc");
+ final Scenario scenario = scenario(ExampleLinksTest.class, "noJavadoc");
final String input = scenario.get("before.java");
- final String actual = SeeLinks.insertHref(input, "http://example.org/orange.html", "Orange Example");
+ final String actual = ExampleLinks.insertHref(input, "http://example.org/orange.html", "Orange Example");
assertEquals(scenario.get("after.java"), actual);
}
@@ -60,17 +60,17 @@
*/
@Test
public void multipleInserts() throws IOException {
- final Scenario scenario = scenario(SeeLinksTest.class, "multipleInserts");
+ final Scenario scenario = scenario(ExampleLinksTest.class, "multipleInserts");
final String input = scenario.get("before.java");
- final String after1 = SeeLinks.insertHref(input, "http://example.org/orange.html", "Orange Example");
+ final String after1 = ExampleLinks.insertHref(input, "http://example.org/orange.html", "Orange Example");
assertEquals(scenario.get("after1.java"), after1);
- final String after2 = SeeLinks.insertHref(after1, "http://example.org/red.html", "Red Sample");
+ final String after2 = ExampleLinks.insertHref(after1, "http://example.org/red.html", "Red Sample");
assertEquals(scenario.get("after2.java"), after2);
- final String after3 = SeeLinks.insertHref(after2, "http://example.org/yellow.html", "yellow");
+ final String after3 = ExampleLinks.insertHref(after2, "http://example.org/yellow.html", "yellow");
assertEquals(scenario.get("after3.java"), after3);
}
@@ -79,15 +79,15 @@
*/
@Test
public void noDuplicates() throws IOException {
- final Scenario scenario = scenario(SeeLinksTest.class, "noDuplicates");
+ final Scenario scenario = scenario(ExampleLinksTest.class, "noDuplicates");
final String input = scenario.get("before.java");
- final String after1 = SeeLinks.insertHref(input, "http://example.org/orange.html", "Orange Example");
+ final String after1 = ExampleLinks.insertHref(input, "http://example.org/orange.html", "Orange Example");
assertEquals(scenario.get("after.java"), after1);
// The second insert should be ignored as it has the same title "Orange Example"
- final String after2 = SeeLinks.insertHref(after1, "http://example.org/foo.html", "Orange Example");
+ final String after2 = ExampleLinks.insertHref(after1, "http://example.org/foo.html", "Orange Example");
assertEquals(scenario.get("after.java"), after2);
}
@@ -96,11 +96,11 @@
*/
@Test
public void hasAnnotations() throws IOException {
- final Scenario scenario = scenario(SeeLinksTest.class, "hasAnnotations");
+ final Scenario scenario = scenario(ExampleLinksTest.class, "hasAnnotations");
final String input = scenario.get("before.java");
- final String actual = SeeLinks.insertHref(input, "http://example.org/orange.html", "Orange Example");
+ final String actual = ExampleLinks.insertHref(input, "http://example.org/orange.html", "Orange Example");
assertEquals(scenario.get("after.java"), actual);
}
diff --git a/src/test/java/org/apache/tomee/website/LearningLinksTest.java b/src/test/java/org/apache/tomee/website/LearningLinksTest.java
new file mode 100644
index 0000000..09e8b37
--- /dev/null
+++ b/src/test/java/org/apache/tomee/website/LearningLinksTest.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.tomee.website;
+
+import org.junit.Test;
+
+import java.io.File;
+
+import static org.junit.Assert.assertEquals;
+
+public class LearningLinksTest {
+
+ @Test
+ public void pathToContentRoot() {
+ final File file = new File("tomee-site-generator/target/jbake/content/tomee-9.0/pt/examples/injection-of-entitymanager.adoc");
+ final String basePath = LearningLinks.pathToContentRoot(file);
+ assertEquals("../../../", basePath);
+ }
+
+ @Test
+ public void pathFromContentRoot() {
+ final File file = new File("tomee-site-generator/target/jbake/content/tomee-9.0/pt/examples/injection-of-entitymanager.adoc");
+ final String basePath = LearningLinks.pathFromContentRoot(file);
+ assertEquals("tomee-9.0/pt/examples/injection-of-entitymanager.adoc", basePath);
+ }
+}
diff --git a/src/test/resources/ApisUsedTest/abnormalHeading/after.adoc b/src/test/resources/ApisUsedTest/abnormalHeading/after.adoc
new file mode 100644
index 0000000..9a6d5db
--- /dev/null
+++ b/src/test/resources/ApisUsedTest/abnormalHeading/after.adoc
@@ -0,0 +1,230 @@
+= Injeção de Entitymanager
+:index-group: JPA
+:jbake-type: page
+:jbake-status: published
+
+Este exemplo mostra o uso de `@PersistenceContext` para ter um `EntityManager` com um contexto de persistência `EXTENDED` injetado em um `@Stateful bean`. Um bean JPA `@ Entity` é usado com o `EntityManager` para criar, persistir e mesclar dados em um banco de dados.
+
+== Criando a entidade JPA
+
+A própria entidade é simplesmente um pote anotado com `@Entity`. Criamos um chamado `Movie`, que podemos usar para armazenar registros de filmes.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.persistence.Entity;
+
+@Entity
+public class Movie {
+
+ @Id @GeneratedValue
+ private long id;
+
+ private String director;
+ private String title;
+ private int year;
+
+ public Movie() {
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Movie(String director, String title, int year) {
+ this.director = director;
+ this.title = title;
+ this.year = year;
+ }
+
+ public String getDirector() {
+ return director;
+ }
+
+ public void setDirector(String director) {
+ this.director = director;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ public void setYear(int year) {
+ this.year = year;
+ }
+}
+----
+
+== Configure o EntityManager por meio de um arquivo persistence.xml
+
+A entidade `Movie` acima pode ser criada, removida, atualizada ou excluída através de um objeto` EntityManager`.
+O próprio `EntityManager` é configurado através de um arquivo `META-INF/persistence.xml` que é colocado no mesmo jar que a entidade `Movie`.
+
+[source,xml,numbered]
+----
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
+
+ <persistence-unit name="movie-unit">
+ <jta-data-source>movieDatabase</jta-data-source>
+ <non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
+ <class>org.superbiz.injection.jpa.Movie</class>
+
+ <properties>
+ <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+ </properties>
+ </persistence-unit>
+</persistence>
+----
+
+Observe que a entidade `Movie` é listada através de um elemento `<class>`. Isso não é necessário, mas pode ajudar no teste ou quando a classe `Movie` estiver localizada em um jar diferente do jar que contém o arquivo `persistence.xml`.
+
+==Injeção via @PersistenceContext
+
+O próprio `EntityManager` é criado pelo contêiner usando as informações no `persistence.xml`, portanto, para usá-lo em tempo de execução, basta solicitar que ele seja injetado em um de nossos componentes. Fazemos isso via `@PersistenceContext`
+
+A anotação `@PersistenceContext` pode ser usada em qualquer bean CDI, EJB, Servlet, Servlet Listener, Servlet Filter ou JSF ManagedBean. Se você não usar um EJB, precisará usar um `UserTransaction` para iniciar e confirmar transações manualmente. É necessária uma transação para que qualquer um dos métodos de criação, atualização ou exclusão do EntityManager funcione.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.ejb.Stateful;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.PersistenceContextType;
+import jakarta.persistence.Query;
+import java.util.List;
+
+@Stateful
+public class Movies {
+
+ @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED)
+ private EntityManager entityManager;
+
+ public void addMovie(Movie movie) throws Exception {
+ entityManager.persist(movie);
+ }
+
+ public void deleteMovie(Movie movie) throws Exception {
+ entityManager.remove(movie);
+ }
+
+ public List<Movie> getMovies() throws Exception {
+ Query query = entityManager.createQuery("SELECT m from Movie as m");
+ return query.getResultList();
+ }
+}
+----
+
+Este `EntityManager` específico é injetado como um contexto de persistência `EXTENDED`, o que significa simplesmente que o `EntityManager` é criado quando o bean `@Stateful` é criado e destruído quando o bean `@Stateful` é destruído. Simplificando, os dados no `EntityManager` são armazenados em cache durante o tempo de vida do bean `@ Stateful`.
+
+O uso de contextos de persistência `EXTENDED` está *apenas* disponível para beans `@Stateful`. Consulte o link: ../../jpa-concepts.html [Conceitos da JPA] para obter uma explicação de alto nível sobre o que realmente é um "contexto de persistência" e como é significativo para a JPA.
+
+== MoviesTest
+
+Testar o JPA é bastante fácil, podemos simplesmente usar a API `EJBContainer` para criar um contêiner em nosso caso de teste.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import junit.framework.TestCase;
+
+import jakarta.ejb.embeddable.EJBContainer;
+import javax.naming.Context;
+import java.util.List;
+import java.util.Properties;
+
+public class MoviesTest extends TestCase {
+
+ public void test() throws Exception {
+
+ final Properties p = new Properties();
+ p.put("movieDatabase", "new://Resource?type=DataSource");
+ p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
+ p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb");
+
+ final Context context = EJBContainer.createEJBContainer(p).getContext();
+
+ Movies movies = (Movies) context.lookup("java:global/injection-of-entitymanager/Movies");
+
+ movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992));
+ movies.addMovie(new Movie("Joel Coen", "Fargo", 1996));
+ movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998));
+
+ List<Movie> list = movies.getMovies();
+ assertEquals("List.size()", 3, list.size());
+
+ for (Movie movie : list) {
+ movies.deleteMovie(movie);
+ }
+
+ assertEquals("Movies.getMovies()", 0, movies.getMovies().size());
+ }
+}
+----
+
+= Executando
+
+Quando executamos nosso caso de teste, devemos ver uma saída semelhante à seguinte.
+
+[source,console]
+----
+-------------------------------------------------------
+ T E S T S
+-------------------------------------------------------
+Running org.superbiz.injection.jpa.MoviesTest
+Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06
+http://tomee.apache.org/
+INFO - openejb.home = /Users/dblevins/examples/injection-of-entitymanager
+INFO - openejb.base = /Users/dblevins/examples/injection-of-entitymanager
+INFO - Using 'jakarta.ejb.embeddable.EJBContainer=true'
+INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
+INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
+INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database)
+INFO - Found EjbModule in classpath: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Beginning load: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Configuring enterprise application: /Users/dblevins/examples/injection-of-entitymanager
+INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container)
+INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container)
+INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
+INFO - Auto-creating a container for bean org.superbiz.injection.jpa.MoviesTest: Container(type=MANAGED, id=Default Managed Container)
+INFO - Configuring PersistenceUnit(name=movie-unit)
+INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'.
+INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase)
+INFO - Adjusting PersistenceUnit movie-unit <non-jta-data-source> to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged'
+INFO - Enterprise application "/Users/dblevins/examples/injection-of-entitymanager" loaded.
+INFO - Assembling app: /Users/dblevins/examples/injection-of-entitymanager
+INFO - PersistenceUnit(name=movie-unit, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 462ms
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies!org.superbiz.injection.jpa.Movies")
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest!org.superbiz.injection.jpa.MoviesTest")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest")
+INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Created Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Started Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Deployed Application(path=/Users/dblevins/examples/injection-of-entitymanager)
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.301 sec
+
+Results :
+
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
+----
+
+= APIs Used
+- link:../../../jakartaee-9.0/javadoc/jakarta/persistence/Entity.html[jakarta.persistence.Entity]
+- link:../../../jakartaee-9.0/javadoc/jakarta/persistence/EntityManager.html[jakarta.persistence.EntityManager]
diff --git a/src/test/resources/ApisUsedTest/abnormalHeading/before.adoc b/src/test/resources/ApisUsedTest/abnormalHeading/before.adoc
new file mode 100644
index 0000000..7c72a68
--- /dev/null
+++ b/src/test/resources/ApisUsedTest/abnormalHeading/before.adoc
@@ -0,0 +1,229 @@
+= Injeção de Entitymanager
+:index-group: JPA
+:jbake-type: page
+:jbake-status: published
+
+Este exemplo mostra o uso de `@PersistenceContext` para ter um `EntityManager` com um contexto de persistência `EXTENDED` injetado em um `@Stateful bean`. Um bean JPA `@ Entity` é usado com o `EntityManager` para criar, persistir e mesclar dados em um banco de dados.
+
+== Criando a entidade JPA
+
+A própria entidade é simplesmente um pote anotado com `@Entity`. Criamos um chamado `Movie`, que podemos usar para armazenar registros de filmes.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.persistence.Entity;
+
+@Entity
+public class Movie {
+
+ @Id @GeneratedValue
+ private long id;
+
+ private String director;
+ private String title;
+ private int year;
+
+ public Movie() {
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Movie(String director, String title, int year) {
+ this.director = director;
+ this.title = title;
+ this.year = year;
+ }
+
+ public String getDirector() {
+ return director;
+ }
+
+ public void setDirector(String director) {
+ this.director = director;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ public void setYear(int year) {
+ this.year = year;
+ }
+}
+----
+
+== Configure o EntityManager por meio de um arquivo persistence.xml
+
+A entidade `Movie` acima pode ser criada, removida, atualizada ou excluída através de um objeto` EntityManager`.
+O próprio `EntityManager` é configurado através de um arquivo `META-INF/persistence.xml` que é colocado no mesmo jar que a entidade `Movie`.
+
+[source,xml,numbered]
+----
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
+
+ <persistence-unit name="movie-unit">
+ <jta-data-source>movieDatabase</jta-data-source>
+ <non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
+ <class>org.superbiz.injection.jpa.Movie</class>
+
+ <properties>
+ <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+ </properties>
+ </persistence-unit>
+</persistence>
+----
+
+Observe que a entidade `Movie` é listada através de um elemento `<class>`. Isso não é necessário, mas pode ajudar no teste ou quando a classe `Movie` estiver localizada em um jar diferente do jar que contém o arquivo `persistence.xml`.
+
+==Injeção via @PersistenceContext
+
+O próprio `EntityManager` é criado pelo contêiner usando as informações no `persistence.xml`, portanto, para usá-lo em tempo de execução, basta solicitar que ele seja injetado em um de nossos componentes. Fazemos isso via `@PersistenceContext`
+
+A anotação `@PersistenceContext` pode ser usada em qualquer bean CDI, EJB, Servlet, Servlet Listener, Servlet Filter ou JSF ManagedBean. Se você não usar um EJB, precisará usar um `UserTransaction` para iniciar e confirmar transações manualmente. É necessária uma transação para que qualquer um dos métodos de criação, atualização ou exclusão do EntityManager funcione.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.ejb.Stateful;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.PersistenceContextType;
+import jakarta.persistence.Query;
+import java.util.List;
+
+@Stateful
+public class Movies {
+
+ @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED)
+ private EntityManager entityManager;
+
+ public void addMovie(Movie movie) throws Exception {
+ entityManager.persist(movie);
+ }
+
+ public void deleteMovie(Movie movie) throws Exception {
+ entityManager.remove(movie);
+ }
+
+ public List<Movie> getMovies() throws Exception {
+ Query query = entityManager.createQuery("SELECT m from Movie as m");
+ return query.getResultList();
+ }
+}
+----
+
+Este `EntityManager` específico é injetado como um contexto de persistência `EXTENDED`, o que significa simplesmente que o `EntityManager` é criado quando o bean `@Stateful` é criado e destruído quando o bean `@Stateful` é destruído. Simplificando, os dados no `EntityManager` são armazenados em cache durante o tempo de vida do bean `@ Stateful`.
+
+O uso de contextos de persistência `EXTENDED` está *apenas* disponível para beans `@Stateful`. Consulte o link: ../../jpa-concepts.html [Conceitos da JPA] para obter uma explicação de alto nível sobre o que realmente é um "contexto de persistência" e como é significativo para a JPA.
+
+== MoviesTest
+
+Testar o JPA é bastante fácil, podemos simplesmente usar a API `EJBContainer` para criar um contêiner em nosso caso de teste.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import junit.framework.TestCase;
+
+import jakarta.ejb.embeddable.EJBContainer;
+import javax.naming.Context;
+import java.util.List;
+import java.util.Properties;
+
+public class MoviesTest extends TestCase {
+
+ public void test() throws Exception {
+
+ final Properties p = new Properties();
+ p.put("movieDatabase", "new://Resource?type=DataSource");
+ p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
+ p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb");
+
+ final Context context = EJBContainer.createEJBContainer(p).getContext();
+
+ Movies movies = (Movies) context.lookup("java:global/injection-of-entitymanager/Movies");
+
+ movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992));
+ movies.addMovie(new Movie("Joel Coen", "Fargo", 1996));
+ movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998));
+
+ List<Movie> list = movies.getMovies();
+ assertEquals("List.size()", 3, list.size());
+
+ for (Movie movie : list) {
+ movies.deleteMovie(movie);
+ }
+
+ assertEquals("Movies.getMovies()", 0, movies.getMovies().size());
+ }
+}
+----
+
+= Executando
+
+Quando executamos nosso caso de teste, devemos ver uma saída semelhante à seguinte.
+
+[source,console]
+----
+-------------------------------------------------------
+ T E S T S
+-------------------------------------------------------
+Running org.superbiz.injection.jpa.MoviesTest
+Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06
+http://tomee.apache.org/
+INFO - openejb.home = /Users/dblevins/examples/injection-of-entitymanager
+INFO - openejb.base = /Users/dblevins/examples/injection-of-entitymanager
+INFO - Using 'jakarta.ejb.embeddable.EJBContainer=true'
+INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
+INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
+INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database)
+INFO - Found EjbModule in classpath: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Beginning load: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Configuring enterprise application: /Users/dblevins/examples/injection-of-entitymanager
+INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container)
+INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container)
+INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
+INFO - Auto-creating a container for bean org.superbiz.injection.jpa.MoviesTest: Container(type=MANAGED, id=Default Managed Container)
+INFO - Configuring PersistenceUnit(name=movie-unit)
+INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'.
+INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase)
+INFO - Adjusting PersistenceUnit movie-unit <non-jta-data-source> to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged'
+INFO - Enterprise application "/Users/dblevins/examples/injection-of-entitymanager" loaded.
+INFO - Assembling app: /Users/dblevins/examples/injection-of-entitymanager
+INFO - PersistenceUnit(name=movie-unit, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 462ms
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies!org.superbiz.injection.jpa.Movies")
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest!org.superbiz.injection.jpa.MoviesTest")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest")
+INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Created Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Started Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Deployed Application(path=/Users/dblevins/examples/injection-of-entitymanager)
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.301 sec
+
+Results :
+
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
+----
+
+==== ApIs usEd
+- link:../../../jakartaee-9.0/javadoc/jakarta/persistence/Entity.html[jakarta.persistence.Entity]
diff --git a/src/test/resources/ApisUsedTest/hasOtherSections/after.adoc b/src/test/resources/ApisUsedTest/hasOtherSections/after.adoc
new file mode 100644
index 0000000..f6e1e43
--- /dev/null
+++ b/src/test/resources/ApisUsedTest/hasOtherSections/after.adoc
@@ -0,0 +1,235 @@
+= Injeção de Entitymanager
+:index-group: JPA
+:jbake-type: page
+:jbake-status: published
+
+Este exemplo mostra o uso de `@PersistenceContext` para ter um `EntityManager` com um contexto de persistência `EXTENDED` injetado em um `@Stateful bean`. Um bean JPA `@ Entity` é usado com o `EntityManager` para criar, persistir e mesclar dados em um banco de dados.
+
+== Criando a entidade JPA
+
+A própria entidade é simplesmente um pote anotado com `@Entity`. Criamos um chamado `Movie`, que podemos usar para armazenar registros de filmes.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.persistence.Entity;
+
+@Entity
+public class Movie {
+
+ @Id @GeneratedValue
+ private long id;
+
+ private String director;
+ private String title;
+ private int year;
+
+ public Movie() {
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Movie(String director, String title, int year) {
+ this.director = director;
+ this.title = title;
+ this.year = year;
+ }
+
+ public String getDirector() {
+ return director;
+ }
+
+ public void setDirector(String director) {
+ this.director = director;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ public void setYear(int year) {
+ this.year = year;
+ }
+}
+----
+
+== Configure o EntityManager por meio de um arquivo persistence.xml
+
+A entidade `Movie` acima pode ser criada, removida, atualizada ou excluída através de um objeto` EntityManager`.
+O próprio `EntityManager` é configurado através de um arquivo `META-INF/persistence.xml` que é colocado no mesmo jar que a entidade `Movie`.
+
+[source,xml,numbered]
+----
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
+
+ <persistence-unit name="movie-unit">
+ <jta-data-source>movieDatabase</jta-data-source>
+ <non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
+ <class>org.superbiz.injection.jpa.Movie</class>
+
+ <properties>
+ <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+ </properties>
+ </persistence-unit>
+</persistence>
+----
+
+Observe que a entidade `Movie` é listada através de um elemento `<class>`. Isso não é necessário, mas pode ajudar no teste ou quando a classe `Movie` estiver localizada em um jar diferente do jar que contém o arquivo `persistence.xml`.
+
+==Injeção via @PersistenceContext
+
+O próprio `EntityManager` é criado pelo contêiner usando as informações no `persistence.xml`, portanto, para usá-lo em tempo de execução, basta solicitar que ele seja injetado em um de nossos componentes. Fazemos isso via `@PersistenceContext`
+
+A anotação `@PersistenceContext` pode ser usada em qualquer bean CDI, EJB, Servlet, Servlet Listener, Servlet Filter ou JSF ManagedBean. Se você não usar um EJB, precisará usar um `UserTransaction` para iniciar e confirmar transações manualmente. É necessária uma transação para que qualquer um dos métodos de criação, atualização ou exclusão do EntityManager funcione.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.ejb.Stateful;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.PersistenceContextType;
+import jakarta.persistence.Query;
+import java.util.List;
+
+@Stateful
+public class Movies {
+
+ @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED)
+ private EntityManager entityManager;
+
+ public void addMovie(Movie movie) throws Exception {
+ entityManager.persist(movie);
+ }
+
+ public void deleteMovie(Movie movie) throws Exception {
+ entityManager.remove(movie);
+ }
+
+ public List<Movie> getMovies() throws Exception {
+ Query query = entityManager.createQuery("SELECT m from Movie as m");
+ return query.getResultList();
+ }
+}
+----
+
+Este `EntityManager` específico é injetado como um contexto de persistência `EXTENDED`, o que significa simplesmente que o `EntityManager` é criado quando o bean `@Stateful` é criado e destruído quando o bean `@Stateful` é destruído. Simplificando, os dados no `EntityManager` são armazenados em cache durante o tempo de vida do bean `@ Stateful`.
+
+O uso de contextos de persistência `EXTENDED` está *apenas* disponível para beans `@Stateful`. Consulte o link: ../../jpa-concepts.html [Conceitos da JPA] para obter uma explicação de alto nível sobre o que realmente é um "contexto de persistência" e como é significativo para a JPA.
+
+== MoviesTest
+
+Testar o JPA é bastante fácil, podemos simplesmente usar a API `EJBContainer` para criar um contêiner em nosso caso de teste.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import junit.framework.TestCase;
+
+import jakarta.ejb.embeddable.EJBContainer;
+import javax.naming.Context;
+import java.util.List;
+import java.util.Properties;
+
+public class MoviesTest extends TestCase {
+
+ public void test() throws Exception {
+
+ final Properties p = new Properties();
+ p.put("movieDatabase", "new://Resource?type=DataSource");
+ p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
+ p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb");
+
+ final Context context = EJBContainer.createEJBContainer(p).getContext();
+
+ Movies movies = (Movies) context.lookup("java:global/injection-of-entitymanager/Movies");
+
+ movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992));
+ movies.addMovie(new Movie("Joel Coen", "Fargo", 1996));
+ movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998));
+
+ List<Movie> list = movies.getMovies();
+ assertEquals("List.size()", 3, list.size());
+
+ for (Movie movie : list) {
+ movies.deleteMovie(movie);
+ }
+
+ assertEquals("Movies.getMovies()", 0, movies.getMovies().size());
+ }
+}
+----
+
+= Executando
+
+Quando executamos nosso caso de teste, devemos ver uma saída semelhante à seguinte.
+
+[source,console]
+----
+-------------------------------------------------------
+ T E S T S
+-------------------------------------------------------
+Running org.superbiz.injection.jpa.MoviesTest
+Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06
+http://tomee.apache.org/
+INFO - openejb.home = /Users/dblevins/examples/injection-of-entitymanager
+INFO - openejb.base = /Users/dblevins/examples/injection-of-entitymanager
+INFO - Using 'jakarta.ejb.embeddable.EJBContainer=true'
+INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
+INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
+INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database)
+INFO - Found EjbModule in classpath: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Beginning load: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Configuring enterprise application: /Users/dblevins/examples/injection-of-entitymanager
+INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container)
+INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container)
+INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
+INFO - Auto-creating a container for bean org.superbiz.injection.jpa.MoviesTest: Container(type=MANAGED, id=Default Managed Container)
+INFO - Configuring PersistenceUnit(name=movie-unit)
+INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'.
+INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase)
+INFO - Adjusting PersistenceUnit movie-unit <non-jta-data-source> to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged'
+INFO - Enterprise application "/Users/dblevins/examples/injection-of-entitymanager" loaded.
+INFO - Assembling app: /Users/dblevins/examples/injection-of-entitymanager
+INFO - PersistenceUnit(name=movie-unit, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 462ms
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies!org.superbiz.injection.jpa.Movies")
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest!org.superbiz.injection.jpa.MoviesTest")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest")
+INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Created Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Started Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Deployed Application(path=/Users/dblevins/examples/injection-of-entitymanager)
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.301 sec
+
+Results :
+
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
+----
+
+= APIs Used
+
+- link:../../../jakartaee-9.0/javadoc/jakarta/persistence/Entity.html[jakarta.persistence.Entity]
+- link:../../../jakartaee-9.0/javadoc/jakarta/persistence/EntityManager.html[jakarta.persistence.EntityManager]
+
+= Related Examples
+
+- link:foo.html
\ No newline at end of file
diff --git a/src/test/resources/ApisUsedTest/hasOtherSections/before.adoc b/src/test/resources/ApisUsedTest/hasOtherSections/before.adoc
new file mode 100644
index 0000000..7966535
--- /dev/null
+++ b/src/test/resources/ApisUsedTest/hasOtherSections/before.adoc
@@ -0,0 +1,234 @@
+= Injeção de Entitymanager
+:index-group: JPA
+:jbake-type: page
+:jbake-status: published
+
+Este exemplo mostra o uso de `@PersistenceContext` para ter um `EntityManager` com um contexto de persistência `EXTENDED` injetado em um `@Stateful bean`. Um bean JPA `@ Entity` é usado com o `EntityManager` para criar, persistir e mesclar dados em um banco de dados.
+
+== Criando a entidade JPA
+
+A própria entidade é simplesmente um pote anotado com `@Entity`. Criamos um chamado `Movie`, que podemos usar para armazenar registros de filmes.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.persistence.Entity;
+
+@Entity
+public class Movie {
+
+ @Id @GeneratedValue
+ private long id;
+
+ private String director;
+ private String title;
+ private int year;
+
+ public Movie() {
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Movie(String director, String title, int year) {
+ this.director = director;
+ this.title = title;
+ this.year = year;
+ }
+
+ public String getDirector() {
+ return director;
+ }
+
+ public void setDirector(String director) {
+ this.director = director;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ public void setYear(int year) {
+ this.year = year;
+ }
+}
+----
+
+== Configure o EntityManager por meio de um arquivo persistence.xml
+
+A entidade `Movie` acima pode ser criada, removida, atualizada ou excluída através de um objeto` EntityManager`.
+O próprio `EntityManager` é configurado através de um arquivo `META-INF/persistence.xml` que é colocado no mesmo jar que a entidade `Movie`.
+
+[source,xml,numbered]
+----
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
+
+ <persistence-unit name="movie-unit">
+ <jta-data-source>movieDatabase</jta-data-source>
+ <non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
+ <class>org.superbiz.injection.jpa.Movie</class>
+
+ <properties>
+ <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+ </properties>
+ </persistence-unit>
+</persistence>
+----
+
+Observe que a entidade `Movie` é listada através de um elemento `<class>`. Isso não é necessário, mas pode ajudar no teste ou quando a classe `Movie` estiver localizada em um jar diferente do jar que contém o arquivo `persistence.xml`.
+
+==Injeção via @PersistenceContext
+
+O próprio `EntityManager` é criado pelo contêiner usando as informações no `persistence.xml`, portanto, para usá-lo em tempo de execução, basta solicitar que ele seja injetado em um de nossos componentes. Fazemos isso via `@PersistenceContext`
+
+A anotação `@PersistenceContext` pode ser usada em qualquer bean CDI, EJB, Servlet, Servlet Listener, Servlet Filter ou JSF ManagedBean. Se você não usar um EJB, precisará usar um `UserTransaction` para iniciar e confirmar transações manualmente. É necessária uma transação para que qualquer um dos métodos de criação, atualização ou exclusão do EntityManager funcione.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.ejb.Stateful;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.PersistenceContextType;
+import jakarta.persistence.Query;
+import java.util.List;
+
+@Stateful
+public class Movies {
+
+ @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED)
+ private EntityManager entityManager;
+
+ public void addMovie(Movie movie) throws Exception {
+ entityManager.persist(movie);
+ }
+
+ public void deleteMovie(Movie movie) throws Exception {
+ entityManager.remove(movie);
+ }
+
+ public List<Movie> getMovies() throws Exception {
+ Query query = entityManager.createQuery("SELECT m from Movie as m");
+ return query.getResultList();
+ }
+}
+----
+
+Este `EntityManager` específico é injetado como um contexto de persistência `EXTENDED`, o que significa simplesmente que o `EntityManager` é criado quando o bean `@Stateful` é criado e destruído quando o bean `@Stateful` é destruído. Simplificando, os dados no `EntityManager` são armazenados em cache durante o tempo de vida do bean `@ Stateful`.
+
+O uso de contextos de persistência `EXTENDED` está *apenas* disponível para beans `@Stateful`. Consulte o link: ../../jpa-concepts.html [Conceitos da JPA] para obter uma explicação de alto nível sobre o que realmente é um "contexto de persistência" e como é significativo para a JPA.
+
+== MoviesTest
+
+Testar o JPA é bastante fácil, podemos simplesmente usar a API `EJBContainer` para criar um contêiner em nosso caso de teste.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import junit.framework.TestCase;
+
+import jakarta.ejb.embeddable.EJBContainer;
+import javax.naming.Context;
+import java.util.List;
+import java.util.Properties;
+
+public class MoviesTest extends TestCase {
+
+ public void test() throws Exception {
+
+ final Properties p = new Properties();
+ p.put("movieDatabase", "new://Resource?type=DataSource");
+ p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
+ p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb");
+
+ final Context context = EJBContainer.createEJBContainer(p).getContext();
+
+ Movies movies = (Movies) context.lookup("java:global/injection-of-entitymanager/Movies");
+
+ movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992));
+ movies.addMovie(new Movie("Joel Coen", "Fargo", 1996));
+ movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998));
+
+ List<Movie> list = movies.getMovies();
+ assertEquals("List.size()", 3, list.size());
+
+ for (Movie movie : list) {
+ movies.deleteMovie(movie);
+ }
+
+ assertEquals("Movies.getMovies()", 0, movies.getMovies().size());
+ }
+}
+----
+
+= Executando
+
+Quando executamos nosso caso de teste, devemos ver uma saída semelhante à seguinte.
+
+[source,console]
+----
+-------------------------------------------------------
+ T E S T S
+-------------------------------------------------------
+Running org.superbiz.injection.jpa.MoviesTest
+Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06
+http://tomee.apache.org/
+INFO - openejb.home = /Users/dblevins/examples/injection-of-entitymanager
+INFO - openejb.base = /Users/dblevins/examples/injection-of-entitymanager
+INFO - Using 'jakarta.ejb.embeddable.EJBContainer=true'
+INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
+INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
+INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database)
+INFO - Found EjbModule in classpath: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Beginning load: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Configuring enterprise application: /Users/dblevins/examples/injection-of-entitymanager
+INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container)
+INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container)
+INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
+INFO - Auto-creating a container for bean org.superbiz.injection.jpa.MoviesTest: Container(type=MANAGED, id=Default Managed Container)
+INFO - Configuring PersistenceUnit(name=movie-unit)
+INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'.
+INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase)
+INFO - Adjusting PersistenceUnit movie-unit <non-jta-data-source> to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged'
+INFO - Enterprise application "/Users/dblevins/examples/injection-of-entitymanager" loaded.
+INFO - Assembling app: /Users/dblevins/examples/injection-of-entitymanager
+INFO - PersistenceUnit(name=movie-unit, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 462ms
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies!org.superbiz.injection.jpa.Movies")
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest!org.superbiz.injection.jpa.MoviesTest")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest")
+INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Created Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Started Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Deployed Application(path=/Users/dblevins/examples/injection-of-entitymanager)
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.301 sec
+
+Results :
+
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
+----
+
+= APIs Used
+
+- link:../../../jakartaee-9.0/javadoc/jakarta/persistence/Entity.html[jakarta.persistence.Entity]
+
+= Related Examples
+
+- link:foo.html
\ No newline at end of file
diff --git a/src/test/resources/ApisUsedTest/insertHref/after.adoc b/src/test/resources/ApisUsedTest/insertHref/after.adoc
new file mode 100644
index 0000000..f83a09d
--- /dev/null
+++ b/src/test/resources/ApisUsedTest/insertHref/after.adoc
@@ -0,0 +1,230 @@
+= Injeção de Entitymanager
+:index-group: JPA
+:jbake-type: page
+:jbake-status: published
+
+Este exemplo mostra o uso de `@PersistenceContext` para ter um `EntityManager` com um contexto de persistência `EXTENDED` injetado em um `@Stateful bean`. Um bean JPA `@ Entity` é usado com o `EntityManager` para criar, persistir e mesclar dados em um banco de dados.
+
+== Criando a entidade JPA
+
+A própria entidade é simplesmente um pote anotado com `@Entity`. Criamos um chamado `Movie`, que podemos usar para armazenar registros de filmes.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.persistence.Entity;
+
+@Entity
+public class Movie {
+
+ @Id @GeneratedValue
+ private long id;
+
+ private String director;
+ private String title;
+ private int year;
+
+ public Movie() {
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Movie(String director, String title, int year) {
+ this.director = director;
+ this.title = title;
+ this.year = year;
+ }
+
+ public String getDirector() {
+ return director;
+ }
+
+ public void setDirector(String director) {
+ this.director = director;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ public void setYear(int year) {
+ this.year = year;
+ }
+}
+----
+
+== Configure o EntityManager por meio de um arquivo persistence.xml
+
+A entidade `Movie` acima pode ser criada, removida, atualizada ou excluída através de um objeto` EntityManager`.
+O próprio `EntityManager` é configurado através de um arquivo `META-INF/persistence.xml` que é colocado no mesmo jar que a entidade `Movie`.
+
+[source,xml,numbered]
+----
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
+
+ <persistence-unit name="movie-unit">
+ <jta-data-source>movieDatabase</jta-data-source>
+ <non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
+ <class>org.superbiz.injection.jpa.Movie</class>
+
+ <properties>
+ <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+ </properties>
+ </persistence-unit>
+</persistence>
+----
+
+Observe que a entidade `Movie` é listada através de um elemento `<class>`. Isso não é necessário, mas pode ajudar no teste ou quando a classe `Movie` estiver localizada em um jar diferente do jar que contém o arquivo `persistence.xml`.
+
+==Injeção via @PersistenceContext
+
+O próprio `EntityManager` é criado pelo contêiner usando as informações no `persistence.xml`, portanto, para usá-lo em tempo de execução, basta solicitar que ele seja injetado em um de nossos componentes. Fazemos isso via `@PersistenceContext`
+
+A anotação `@PersistenceContext` pode ser usada em qualquer bean CDI, EJB, Servlet, Servlet Listener, Servlet Filter ou JSF ManagedBean. Se você não usar um EJB, precisará usar um `UserTransaction` para iniciar e confirmar transações manualmente. É necessária uma transação para que qualquer um dos métodos de criação, atualização ou exclusão do EntityManager funcione.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.ejb.Stateful;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.PersistenceContextType;
+import jakarta.persistence.Query;
+import java.util.List;
+
+@Stateful
+public class Movies {
+
+ @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED)
+ private EntityManager entityManager;
+
+ public void addMovie(Movie movie) throws Exception {
+ entityManager.persist(movie);
+ }
+
+ public void deleteMovie(Movie movie) throws Exception {
+ entityManager.remove(movie);
+ }
+
+ public List<Movie> getMovies() throws Exception {
+ Query query = entityManager.createQuery("SELECT m from Movie as m");
+ return query.getResultList();
+ }
+}
+----
+
+Este `EntityManager` específico é injetado como um contexto de persistência `EXTENDED`, o que significa simplesmente que o `EntityManager` é criado quando o bean `@Stateful` é criado e destruído quando o bean `@Stateful` é destruído. Simplificando, os dados no `EntityManager` são armazenados em cache durante o tempo de vida do bean `@ Stateful`.
+
+O uso de contextos de persistência `EXTENDED` está *apenas* disponível para beans `@Stateful`. Consulte o link: ../../jpa-concepts.html [Conceitos da JPA] para obter uma explicação de alto nível sobre o que realmente é um "contexto de persistência" e como é significativo para a JPA.
+
+== MoviesTest
+
+Testar o JPA é bastante fácil, podemos simplesmente usar a API `EJBContainer` para criar um contêiner em nosso caso de teste.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import junit.framework.TestCase;
+
+import jakarta.ejb.embeddable.EJBContainer;
+import javax.naming.Context;
+import java.util.List;
+import java.util.Properties;
+
+public class MoviesTest extends TestCase {
+
+ public void test() throws Exception {
+
+ final Properties p = new Properties();
+ p.put("movieDatabase", "new://Resource?type=DataSource");
+ p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
+ p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb");
+
+ final Context context = EJBContainer.createEJBContainer(p).getContext();
+
+ Movies movies = (Movies) context.lookup("java:global/injection-of-entitymanager/Movies");
+
+ movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992));
+ movies.addMovie(new Movie("Joel Coen", "Fargo", 1996));
+ movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998));
+
+ List<Movie> list = movies.getMovies();
+ assertEquals("List.size()", 3, list.size());
+
+ for (Movie movie : list) {
+ movies.deleteMovie(movie);
+ }
+
+ assertEquals("Movies.getMovies()", 0, movies.getMovies().size());
+ }
+}
+----
+
+= Executando
+
+Quando executamos nosso caso de teste, devemos ver uma saída semelhante à seguinte.
+
+[source,console]
+----
+-------------------------------------------------------
+ T E S T S
+-------------------------------------------------------
+Running org.superbiz.injection.jpa.MoviesTest
+Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06
+http://tomee.apache.org/
+INFO - openejb.home = /Users/dblevins/examples/injection-of-entitymanager
+INFO - openejb.base = /Users/dblevins/examples/injection-of-entitymanager
+INFO - Using 'jakarta.ejb.embeddable.EJBContainer=true'
+INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
+INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
+INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database)
+INFO - Found EjbModule in classpath: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Beginning load: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Configuring enterprise application: /Users/dblevins/examples/injection-of-entitymanager
+INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container)
+INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container)
+INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
+INFO - Auto-creating a container for bean org.superbiz.injection.jpa.MoviesTest: Container(type=MANAGED, id=Default Managed Container)
+INFO - Configuring PersistenceUnit(name=movie-unit)
+INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'.
+INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase)
+INFO - Adjusting PersistenceUnit movie-unit <non-jta-data-source> to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged'
+INFO - Enterprise application "/Users/dblevins/examples/injection-of-entitymanager" loaded.
+INFO - Assembling app: /Users/dblevins/examples/injection-of-entitymanager
+INFO - PersistenceUnit(name=movie-unit, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 462ms
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies!org.superbiz.injection.jpa.Movies")
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest!org.superbiz.injection.jpa.MoviesTest")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest")
+INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Created Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Started Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Deployed Application(path=/Users/dblevins/examples/injection-of-entitymanager)
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.301 sec
+
+Results :
+
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
+----
+
+= APIs Used
+
+- link:../../../jakartaee-9.0/javadoc/jakarta/persistence/Entity.html[jakarta.persistence.Entity]
diff --git a/src/test/resources/ApisUsedTest/insertHref/before.adoc b/src/test/resources/ApisUsedTest/insertHref/before.adoc
new file mode 100644
index 0000000..5a86e09
--- /dev/null
+++ b/src/test/resources/ApisUsedTest/insertHref/before.adoc
@@ -0,0 +1,226 @@
+= Injeção de Entitymanager
+:index-group: JPA
+:jbake-type: page
+:jbake-status: published
+
+Este exemplo mostra o uso de `@PersistenceContext` para ter um `EntityManager` com um contexto de persistência `EXTENDED` injetado em um `@Stateful bean`. Um bean JPA `@ Entity` é usado com o `EntityManager` para criar, persistir e mesclar dados em um banco de dados.
+
+== Criando a entidade JPA
+
+A própria entidade é simplesmente um pote anotado com `@Entity`. Criamos um chamado `Movie`, que podemos usar para armazenar registros de filmes.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.persistence.Entity;
+
+@Entity
+public class Movie {
+
+ @Id @GeneratedValue
+ private long id;
+
+ private String director;
+ private String title;
+ private int year;
+
+ public Movie() {
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Movie(String director, String title, int year) {
+ this.director = director;
+ this.title = title;
+ this.year = year;
+ }
+
+ public String getDirector() {
+ return director;
+ }
+
+ public void setDirector(String director) {
+ this.director = director;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ public void setYear(int year) {
+ this.year = year;
+ }
+}
+----
+
+== Configure o EntityManager por meio de um arquivo persistence.xml
+
+A entidade `Movie` acima pode ser criada, removida, atualizada ou excluída através de um objeto` EntityManager`.
+O próprio `EntityManager` é configurado através de um arquivo `META-INF/persistence.xml` que é colocado no mesmo jar que a entidade `Movie`.
+
+[source,xml,numbered]
+----
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
+
+ <persistence-unit name="movie-unit">
+ <jta-data-source>movieDatabase</jta-data-source>
+ <non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
+ <class>org.superbiz.injection.jpa.Movie</class>
+
+ <properties>
+ <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+ </properties>
+ </persistence-unit>
+</persistence>
+----
+
+Observe que a entidade `Movie` é listada através de um elemento `<class>`. Isso não é necessário, mas pode ajudar no teste ou quando a classe `Movie` estiver localizada em um jar diferente do jar que contém o arquivo `persistence.xml`.
+
+==Injeção via @PersistenceContext
+
+O próprio `EntityManager` é criado pelo contêiner usando as informações no `persistence.xml`, portanto, para usá-lo em tempo de execução, basta solicitar que ele seja injetado em um de nossos componentes. Fazemos isso via `@PersistenceContext`
+
+A anotação `@PersistenceContext` pode ser usada em qualquer bean CDI, EJB, Servlet, Servlet Listener, Servlet Filter ou JSF ManagedBean. Se você não usar um EJB, precisará usar um `UserTransaction` para iniciar e confirmar transações manualmente. É necessária uma transação para que qualquer um dos métodos de criação, atualização ou exclusão do EntityManager funcione.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.ejb.Stateful;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.PersistenceContextType;
+import jakarta.persistence.Query;
+import java.util.List;
+
+@Stateful
+public class Movies {
+
+ @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED)
+ private EntityManager entityManager;
+
+ public void addMovie(Movie movie) throws Exception {
+ entityManager.persist(movie);
+ }
+
+ public void deleteMovie(Movie movie) throws Exception {
+ entityManager.remove(movie);
+ }
+
+ public List<Movie> getMovies() throws Exception {
+ Query query = entityManager.createQuery("SELECT m from Movie as m");
+ return query.getResultList();
+ }
+}
+----
+
+Este `EntityManager` específico é injetado como um contexto de persistência `EXTENDED`, o que significa simplesmente que o `EntityManager` é criado quando o bean `@Stateful` é criado e destruído quando o bean `@Stateful` é destruído. Simplificando, os dados no `EntityManager` são armazenados em cache durante o tempo de vida do bean `@ Stateful`.
+
+O uso de contextos de persistência `EXTENDED` está *apenas* disponível para beans `@Stateful`. Consulte o link: ../../jpa-concepts.html [Conceitos da JPA] para obter uma explicação de alto nível sobre o que realmente é um "contexto de persistência" e como é significativo para a JPA.
+
+== MoviesTest
+
+Testar o JPA é bastante fácil, podemos simplesmente usar a API `EJBContainer` para criar um contêiner em nosso caso de teste.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import junit.framework.TestCase;
+
+import jakarta.ejb.embeddable.EJBContainer;
+import javax.naming.Context;
+import java.util.List;
+import java.util.Properties;
+
+public class MoviesTest extends TestCase {
+
+ public void test() throws Exception {
+
+ final Properties p = new Properties();
+ p.put("movieDatabase", "new://Resource?type=DataSource");
+ p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
+ p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb");
+
+ final Context context = EJBContainer.createEJBContainer(p).getContext();
+
+ Movies movies = (Movies) context.lookup("java:global/injection-of-entitymanager/Movies");
+
+ movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992));
+ movies.addMovie(new Movie("Joel Coen", "Fargo", 1996));
+ movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998));
+
+ List<Movie> list = movies.getMovies();
+ assertEquals("List.size()", 3, list.size());
+
+ for (Movie movie : list) {
+ movies.deleteMovie(movie);
+ }
+
+ assertEquals("Movies.getMovies()", 0, movies.getMovies().size());
+ }
+}
+----
+
+= Executando
+
+Quando executamos nosso caso de teste, devemos ver uma saída semelhante à seguinte.
+
+[source,console]
+----
+-------------------------------------------------------
+ T E S T S
+-------------------------------------------------------
+Running org.superbiz.injection.jpa.MoviesTest
+Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06
+http://tomee.apache.org/
+INFO - openejb.home = /Users/dblevins/examples/injection-of-entitymanager
+INFO - openejb.base = /Users/dblevins/examples/injection-of-entitymanager
+INFO - Using 'jakarta.ejb.embeddable.EJBContainer=true'
+INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
+INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
+INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database)
+INFO - Found EjbModule in classpath: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Beginning load: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Configuring enterprise application: /Users/dblevins/examples/injection-of-entitymanager
+INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container)
+INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container)
+INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
+INFO - Auto-creating a container for bean org.superbiz.injection.jpa.MoviesTest: Container(type=MANAGED, id=Default Managed Container)
+INFO - Configuring PersistenceUnit(name=movie-unit)
+INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'.
+INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase)
+INFO - Adjusting PersistenceUnit movie-unit <non-jta-data-source> to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged'
+INFO - Enterprise application "/Users/dblevins/examples/injection-of-entitymanager" loaded.
+INFO - Assembling app: /Users/dblevins/examples/injection-of-entitymanager
+INFO - PersistenceUnit(name=movie-unit, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 462ms
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies!org.superbiz.injection.jpa.Movies")
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest!org.superbiz.injection.jpa.MoviesTest")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest")
+INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Created Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Started Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Deployed Application(path=/Users/dblevins/examples/injection-of-entitymanager)
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.301 sec
+
+Results :
+
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
+----
diff --git a/src/test/resources/ApisUsedTest/multipleInserts/after1.adoc b/src/test/resources/ApisUsedTest/multipleInserts/after1.adoc
new file mode 100644
index 0000000..f83a09d
--- /dev/null
+++ b/src/test/resources/ApisUsedTest/multipleInserts/after1.adoc
@@ -0,0 +1,230 @@
+= Injeção de Entitymanager
+:index-group: JPA
+:jbake-type: page
+:jbake-status: published
+
+Este exemplo mostra o uso de `@PersistenceContext` para ter um `EntityManager` com um contexto de persistência `EXTENDED` injetado em um `@Stateful bean`. Um bean JPA `@ Entity` é usado com o `EntityManager` para criar, persistir e mesclar dados em um banco de dados.
+
+== Criando a entidade JPA
+
+A própria entidade é simplesmente um pote anotado com `@Entity`. Criamos um chamado `Movie`, que podemos usar para armazenar registros de filmes.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.persistence.Entity;
+
+@Entity
+public class Movie {
+
+ @Id @GeneratedValue
+ private long id;
+
+ private String director;
+ private String title;
+ private int year;
+
+ public Movie() {
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Movie(String director, String title, int year) {
+ this.director = director;
+ this.title = title;
+ this.year = year;
+ }
+
+ public String getDirector() {
+ return director;
+ }
+
+ public void setDirector(String director) {
+ this.director = director;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ public void setYear(int year) {
+ this.year = year;
+ }
+}
+----
+
+== Configure o EntityManager por meio de um arquivo persistence.xml
+
+A entidade `Movie` acima pode ser criada, removida, atualizada ou excluída através de um objeto` EntityManager`.
+O próprio `EntityManager` é configurado através de um arquivo `META-INF/persistence.xml` que é colocado no mesmo jar que a entidade `Movie`.
+
+[source,xml,numbered]
+----
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
+
+ <persistence-unit name="movie-unit">
+ <jta-data-source>movieDatabase</jta-data-source>
+ <non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
+ <class>org.superbiz.injection.jpa.Movie</class>
+
+ <properties>
+ <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+ </properties>
+ </persistence-unit>
+</persistence>
+----
+
+Observe que a entidade `Movie` é listada através de um elemento `<class>`. Isso não é necessário, mas pode ajudar no teste ou quando a classe `Movie` estiver localizada em um jar diferente do jar que contém o arquivo `persistence.xml`.
+
+==Injeção via @PersistenceContext
+
+O próprio `EntityManager` é criado pelo contêiner usando as informações no `persistence.xml`, portanto, para usá-lo em tempo de execução, basta solicitar que ele seja injetado em um de nossos componentes. Fazemos isso via `@PersistenceContext`
+
+A anotação `@PersistenceContext` pode ser usada em qualquer bean CDI, EJB, Servlet, Servlet Listener, Servlet Filter ou JSF ManagedBean. Se você não usar um EJB, precisará usar um `UserTransaction` para iniciar e confirmar transações manualmente. É necessária uma transação para que qualquer um dos métodos de criação, atualização ou exclusão do EntityManager funcione.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.ejb.Stateful;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.PersistenceContextType;
+import jakarta.persistence.Query;
+import java.util.List;
+
+@Stateful
+public class Movies {
+
+ @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED)
+ private EntityManager entityManager;
+
+ public void addMovie(Movie movie) throws Exception {
+ entityManager.persist(movie);
+ }
+
+ public void deleteMovie(Movie movie) throws Exception {
+ entityManager.remove(movie);
+ }
+
+ public List<Movie> getMovies() throws Exception {
+ Query query = entityManager.createQuery("SELECT m from Movie as m");
+ return query.getResultList();
+ }
+}
+----
+
+Este `EntityManager` específico é injetado como um contexto de persistência `EXTENDED`, o que significa simplesmente que o `EntityManager` é criado quando o bean `@Stateful` é criado e destruído quando o bean `@Stateful` é destruído. Simplificando, os dados no `EntityManager` são armazenados em cache durante o tempo de vida do bean `@ Stateful`.
+
+O uso de contextos de persistência `EXTENDED` está *apenas* disponível para beans `@Stateful`. Consulte o link: ../../jpa-concepts.html [Conceitos da JPA] para obter uma explicação de alto nível sobre o que realmente é um "contexto de persistência" e como é significativo para a JPA.
+
+== MoviesTest
+
+Testar o JPA é bastante fácil, podemos simplesmente usar a API `EJBContainer` para criar um contêiner em nosso caso de teste.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import junit.framework.TestCase;
+
+import jakarta.ejb.embeddable.EJBContainer;
+import javax.naming.Context;
+import java.util.List;
+import java.util.Properties;
+
+public class MoviesTest extends TestCase {
+
+ public void test() throws Exception {
+
+ final Properties p = new Properties();
+ p.put("movieDatabase", "new://Resource?type=DataSource");
+ p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
+ p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb");
+
+ final Context context = EJBContainer.createEJBContainer(p).getContext();
+
+ Movies movies = (Movies) context.lookup("java:global/injection-of-entitymanager/Movies");
+
+ movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992));
+ movies.addMovie(new Movie("Joel Coen", "Fargo", 1996));
+ movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998));
+
+ List<Movie> list = movies.getMovies();
+ assertEquals("List.size()", 3, list.size());
+
+ for (Movie movie : list) {
+ movies.deleteMovie(movie);
+ }
+
+ assertEquals("Movies.getMovies()", 0, movies.getMovies().size());
+ }
+}
+----
+
+= Executando
+
+Quando executamos nosso caso de teste, devemos ver uma saída semelhante à seguinte.
+
+[source,console]
+----
+-------------------------------------------------------
+ T E S T S
+-------------------------------------------------------
+Running org.superbiz.injection.jpa.MoviesTest
+Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06
+http://tomee.apache.org/
+INFO - openejb.home = /Users/dblevins/examples/injection-of-entitymanager
+INFO - openejb.base = /Users/dblevins/examples/injection-of-entitymanager
+INFO - Using 'jakarta.ejb.embeddable.EJBContainer=true'
+INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
+INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
+INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database)
+INFO - Found EjbModule in classpath: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Beginning load: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Configuring enterprise application: /Users/dblevins/examples/injection-of-entitymanager
+INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container)
+INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container)
+INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
+INFO - Auto-creating a container for bean org.superbiz.injection.jpa.MoviesTest: Container(type=MANAGED, id=Default Managed Container)
+INFO - Configuring PersistenceUnit(name=movie-unit)
+INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'.
+INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase)
+INFO - Adjusting PersistenceUnit movie-unit <non-jta-data-source> to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged'
+INFO - Enterprise application "/Users/dblevins/examples/injection-of-entitymanager" loaded.
+INFO - Assembling app: /Users/dblevins/examples/injection-of-entitymanager
+INFO - PersistenceUnit(name=movie-unit, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 462ms
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies!org.superbiz.injection.jpa.Movies")
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest!org.superbiz.injection.jpa.MoviesTest")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest")
+INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Created Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Started Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Deployed Application(path=/Users/dblevins/examples/injection-of-entitymanager)
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.301 sec
+
+Results :
+
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
+----
+
+= APIs Used
+
+- link:../../../jakartaee-9.0/javadoc/jakarta/persistence/Entity.html[jakarta.persistence.Entity]
diff --git a/src/test/resources/ApisUsedTest/multipleInserts/after2.adoc b/src/test/resources/ApisUsedTest/multipleInserts/after2.adoc
new file mode 100644
index 0000000..95aaa88
--- /dev/null
+++ b/src/test/resources/ApisUsedTest/multipleInserts/after2.adoc
@@ -0,0 +1,231 @@
+= Injeção de Entitymanager
+:index-group: JPA
+:jbake-type: page
+:jbake-status: published
+
+Este exemplo mostra o uso de `@PersistenceContext` para ter um `EntityManager` com um contexto de persistência `EXTENDED` injetado em um `@Stateful bean`. Um bean JPA `@ Entity` é usado com o `EntityManager` para criar, persistir e mesclar dados em um banco de dados.
+
+== Criando a entidade JPA
+
+A própria entidade é simplesmente um pote anotado com `@Entity`. Criamos um chamado `Movie`, que podemos usar para armazenar registros de filmes.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.persistence.Entity;
+
+@Entity
+public class Movie {
+
+ @Id @GeneratedValue
+ private long id;
+
+ private String director;
+ private String title;
+ private int year;
+
+ public Movie() {
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Movie(String director, String title, int year) {
+ this.director = director;
+ this.title = title;
+ this.year = year;
+ }
+
+ public String getDirector() {
+ return director;
+ }
+
+ public void setDirector(String director) {
+ this.director = director;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ public void setYear(int year) {
+ this.year = year;
+ }
+}
+----
+
+== Configure o EntityManager por meio de um arquivo persistence.xml
+
+A entidade `Movie` acima pode ser criada, removida, atualizada ou excluída através de um objeto` EntityManager`.
+O próprio `EntityManager` é configurado através de um arquivo `META-INF/persistence.xml` que é colocado no mesmo jar que a entidade `Movie`.
+
+[source,xml,numbered]
+----
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
+
+ <persistence-unit name="movie-unit">
+ <jta-data-source>movieDatabase</jta-data-source>
+ <non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
+ <class>org.superbiz.injection.jpa.Movie</class>
+
+ <properties>
+ <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+ </properties>
+ </persistence-unit>
+</persistence>
+----
+
+Observe que a entidade `Movie` é listada através de um elemento `<class>`. Isso não é necessário, mas pode ajudar no teste ou quando a classe `Movie` estiver localizada em um jar diferente do jar que contém o arquivo `persistence.xml`.
+
+==Injeção via @PersistenceContext
+
+O próprio `EntityManager` é criado pelo contêiner usando as informações no `persistence.xml`, portanto, para usá-lo em tempo de execução, basta solicitar que ele seja injetado em um de nossos componentes. Fazemos isso via `@PersistenceContext`
+
+A anotação `@PersistenceContext` pode ser usada em qualquer bean CDI, EJB, Servlet, Servlet Listener, Servlet Filter ou JSF ManagedBean. Se você não usar um EJB, precisará usar um `UserTransaction` para iniciar e confirmar transações manualmente. É necessária uma transação para que qualquer um dos métodos de criação, atualização ou exclusão do EntityManager funcione.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.ejb.Stateful;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.PersistenceContextType;
+import jakarta.persistence.Query;
+import java.util.List;
+
+@Stateful
+public class Movies {
+
+ @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED)
+ private EntityManager entityManager;
+
+ public void addMovie(Movie movie) throws Exception {
+ entityManager.persist(movie);
+ }
+
+ public void deleteMovie(Movie movie) throws Exception {
+ entityManager.remove(movie);
+ }
+
+ public List<Movie> getMovies() throws Exception {
+ Query query = entityManager.createQuery("SELECT m from Movie as m");
+ return query.getResultList();
+ }
+}
+----
+
+Este `EntityManager` específico é injetado como um contexto de persistência `EXTENDED`, o que significa simplesmente que o `EntityManager` é criado quando o bean `@Stateful` é criado e destruído quando o bean `@Stateful` é destruído. Simplificando, os dados no `EntityManager` são armazenados em cache durante o tempo de vida do bean `@ Stateful`.
+
+O uso de contextos de persistência `EXTENDED` está *apenas* disponível para beans `@Stateful`. Consulte o link: ../../jpa-concepts.html [Conceitos da JPA] para obter uma explicação de alto nível sobre o que realmente é um "contexto de persistência" e como é significativo para a JPA.
+
+== MoviesTest
+
+Testar o JPA é bastante fácil, podemos simplesmente usar a API `EJBContainer` para criar um contêiner em nosso caso de teste.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import junit.framework.TestCase;
+
+import jakarta.ejb.embeddable.EJBContainer;
+import javax.naming.Context;
+import java.util.List;
+import java.util.Properties;
+
+public class MoviesTest extends TestCase {
+
+ public void test() throws Exception {
+
+ final Properties p = new Properties();
+ p.put("movieDatabase", "new://Resource?type=DataSource");
+ p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
+ p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb");
+
+ final Context context = EJBContainer.createEJBContainer(p).getContext();
+
+ Movies movies = (Movies) context.lookup("java:global/injection-of-entitymanager/Movies");
+
+ movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992));
+ movies.addMovie(new Movie("Joel Coen", "Fargo", 1996));
+ movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998));
+
+ List<Movie> list = movies.getMovies();
+ assertEquals("List.size()", 3, list.size());
+
+ for (Movie movie : list) {
+ movies.deleteMovie(movie);
+ }
+
+ assertEquals("Movies.getMovies()", 0, movies.getMovies().size());
+ }
+}
+----
+
+= Executando
+
+Quando executamos nosso caso de teste, devemos ver uma saída semelhante à seguinte.
+
+[source,console]
+----
+-------------------------------------------------------
+ T E S T S
+-------------------------------------------------------
+Running org.superbiz.injection.jpa.MoviesTest
+Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06
+http://tomee.apache.org/
+INFO - openejb.home = /Users/dblevins/examples/injection-of-entitymanager
+INFO - openejb.base = /Users/dblevins/examples/injection-of-entitymanager
+INFO - Using 'jakarta.ejb.embeddable.EJBContainer=true'
+INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
+INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
+INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database)
+INFO - Found EjbModule in classpath: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Beginning load: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Configuring enterprise application: /Users/dblevins/examples/injection-of-entitymanager
+INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container)
+INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container)
+INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
+INFO - Auto-creating a container for bean org.superbiz.injection.jpa.MoviesTest: Container(type=MANAGED, id=Default Managed Container)
+INFO - Configuring PersistenceUnit(name=movie-unit)
+INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'.
+INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase)
+INFO - Adjusting PersistenceUnit movie-unit <non-jta-data-source> to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged'
+INFO - Enterprise application "/Users/dblevins/examples/injection-of-entitymanager" loaded.
+INFO - Assembling app: /Users/dblevins/examples/injection-of-entitymanager
+INFO - PersistenceUnit(name=movie-unit, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 462ms
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies!org.superbiz.injection.jpa.Movies")
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest!org.superbiz.injection.jpa.MoviesTest")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest")
+INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Created Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Started Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Deployed Application(path=/Users/dblevins/examples/injection-of-entitymanager)
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.301 sec
+
+Results :
+
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
+----
+
+= APIs Used
+
+- link:../../../jakartaee-9.0/javadoc/jakarta/persistence/Entity.html[jakarta.persistence.Entity]
+- link:../../../jakartaee-9.0/javadoc/jakarta/persistence/EntityManager.html[jakarta.persistence.EntityManager]
diff --git a/src/test/resources/ApisUsedTest/multipleInserts/after3.adoc b/src/test/resources/ApisUsedTest/multipleInserts/after3.adoc
new file mode 100644
index 0000000..906b6ff
--- /dev/null
+++ b/src/test/resources/ApisUsedTest/multipleInserts/after3.adoc
@@ -0,0 +1,232 @@
+= Injeção de Entitymanager
+:index-group: JPA
+:jbake-type: page
+:jbake-status: published
+
+Este exemplo mostra o uso de `@PersistenceContext` para ter um `EntityManager` com um contexto de persistência `EXTENDED` injetado em um `@Stateful bean`. Um bean JPA `@ Entity` é usado com o `EntityManager` para criar, persistir e mesclar dados em um banco de dados.
+
+== Criando a entidade JPA
+
+A própria entidade é simplesmente um pote anotado com `@Entity`. Criamos um chamado `Movie`, que podemos usar para armazenar registros de filmes.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.persistence.Entity;
+
+@Entity
+public class Movie {
+
+ @Id @GeneratedValue
+ private long id;
+
+ private String director;
+ private String title;
+ private int year;
+
+ public Movie() {
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Movie(String director, String title, int year) {
+ this.director = director;
+ this.title = title;
+ this.year = year;
+ }
+
+ public String getDirector() {
+ return director;
+ }
+
+ public void setDirector(String director) {
+ this.director = director;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ public void setYear(int year) {
+ this.year = year;
+ }
+}
+----
+
+== Configure o EntityManager por meio de um arquivo persistence.xml
+
+A entidade `Movie` acima pode ser criada, removida, atualizada ou excluída através de um objeto` EntityManager`.
+O próprio `EntityManager` é configurado através de um arquivo `META-INF/persistence.xml` que é colocado no mesmo jar que a entidade `Movie`.
+
+[source,xml,numbered]
+----
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
+
+ <persistence-unit name="movie-unit">
+ <jta-data-source>movieDatabase</jta-data-source>
+ <non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
+ <class>org.superbiz.injection.jpa.Movie</class>
+
+ <properties>
+ <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+ </properties>
+ </persistence-unit>
+</persistence>
+----
+
+Observe que a entidade `Movie` é listada através de um elemento `<class>`. Isso não é necessário, mas pode ajudar no teste ou quando a classe `Movie` estiver localizada em um jar diferente do jar que contém o arquivo `persistence.xml`.
+
+==Injeção via @PersistenceContext
+
+O próprio `EntityManager` é criado pelo contêiner usando as informações no `persistence.xml`, portanto, para usá-lo em tempo de execução, basta solicitar que ele seja injetado em um de nossos componentes. Fazemos isso via `@PersistenceContext`
+
+A anotação `@PersistenceContext` pode ser usada em qualquer bean CDI, EJB, Servlet, Servlet Listener, Servlet Filter ou JSF ManagedBean. Se você não usar um EJB, precisará usar um `UserTransaction` para iniciar e confirmar transações manualmente. É necessária uma transação para que qualquer um dos métodos de criação, atualização ou exclusão do EntityManager funcione.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.ejb.Stateful;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.PersistenceContextType;
+import jakarta.persistence.Query;
+import java.util.List;
+
+@Stateful
+public class Movies {
+
+ @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED)
+ private EntityManager entityManager;
+
+ public void addMovie(Movie movie) throws Exception {
+ entityManager.persist(movie);
+ }
+
+ public void deleteMovie(Movie movie) throws Exception {
+ entityManager.remove(movie);
+ }
+
+ public List<Movie> getMovies() throws Exception {
+ Query query = entityManager.createQuery("SELECT m from Movie as m");
+ return query.getResultList();
+ }
+}
+----
+
+Este `EntityManager` específico é injetado como um contexto de persistência `EXTENDED`, o que significa simplesmente que o `EntityManager` é criado quando o bean `@Stateful` é criado e destruído quando o bean `@Stateful` é destruído. Simplificando, os dados no `EntityManager` são armazenados em cache durante o tempo de vida do bean `@ Stateful`.
+
+O uso de contextos de persistência `EXTENDED` está *apenas* disponível para beans `@Stateful`. Consulte o link: ../../jpa-concepts.html [Conceitos da JPA] para obter uma explicação de alto nível sobre o que realmente é um "contexto de persistência" e como é significativo para a JPA.
+
+== MoviesTest
+
+Testar o JPA é bastante fácil, podemos simplesmente usar a API `EJBContainer` para criar um contêiner em nosso caso de teste.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import junit.framework.TestCase;
+
+import jakarta.ejb.embeddable.EJBContainer;
+import javax.naming.Context;
+import java.util.List;
+import java.util.Properties;
+
+public class MoviesTest extends TestCase {
+
+ public void test() throws Exception {
+
+ final Properties p = new Properties();
+ p.put("movieDatabase", "new://Resource?type=DataSource");
+ p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
+ p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb");
+
+ final Context context = EJBContainer.createEJBContainer(p).getContext();
+
+ Movies movies = (Movies) context.lookup("java:global/injection-of-entitymanager/Movies");
+
+ movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992));
+ movies.addMovie(new Movie("Joel Coen", "Fargo", 1996));
+ movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998));
+
+ List<Movie> list = movies.getMovies();
+ assertEquals("List.size()", 3, list.size());
+
+ for (Movie movie : list) {
+ movies.deleteMovie(movie);
+ }
+
+ assertEquals("Movies.getMovies()", 0, movies.getMovies().size());
+ }
+}
+----
+
+= Executando
+
+Quando executamos nosso caso de teste, devemos ver uma saída semelhante à seguinte.
+
+[source,console]
+----
+-------------------------------------------------------
+ T E S T S
+-------------------------------------------------------
+Running org.superbiz.injection.jpa.MoviesTest
+Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06
+http://tomee.apache.org/
+INFO - openejb.home = /Users/dblevins/examples/injection-of-entitymanager
+INFO - openejb.base = /Users/dblevins/examples/injection-of-entitymanager
+INFO - Using 'jakarta.ejb.embeddable.EJBContainer=true'
+INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
+INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
+INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database)
+INFO - Found EjbModule in classpath: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Beginning load: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Configuring enterprise application: /Users/dblevins/examples/injection-of-entitymanager
+INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container)
+INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container)
+INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
+INFO - Auto-creating a container for bean org.superbiz.injection.jpa.MoviesTest: Container(type=MANAGED, id=Default Managed Container)
+INFO - Configuring PersistenceUnit(name=movie-unit)
+INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'.
+INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase)
+INFO - Adjusting PersistenceUnit movie-unit <non-jta-data-source> to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged'
+INFO - Enterprise application "/Users/dblevins/examples/injection-of-entitymanager" loaded.
+INFO - Assembling app: /Users/dblevins/examples/injection-of-entitymanager
+INFO - PersistenceUnit(name=movie-unit, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 462ms
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies!org.superbiz.injection.jpa.Movies")
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest!org.superbiz.injection.jpa.MoviesTest")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest")
+INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Created Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Started Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Deployed Application(path=/Users/dblevins/examples/injection-of-entitymanager)
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.301 sec
+
+Results :
+
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
+----
+
+= APIs Used
+
+- link:../../../jakartaee-9.0/javadoc/jakarta/persistence/Entity.html[jakarta.persistence.Entity]
+- link:../../../jakartaee-9.0/javadoc/jakarta/persistence/EntityManager.html[jakarta.persistence.EntityManager]
+- link:../../../jakartaee-9.0/javadoc/jakarta/persistence/Id.html[jakarta.persistence.Id]
diff --git a/src/test/resources/ApisUsedTest/multipleInserts/before.adoc b/src/test/resources/ApisUsedTest/multipleInserts/before.adoc
new file mode 100644
index 0000000..5a86e09
--- /dev/null
+++ b/src/test/resources/ApisUsedTest/multipleInserts/before.adoc
@@ -0,0 +1,226 @@
+= Injeção de Entitymanager
+:index-group: JPA
+:jbake-type: page
+:jbake-status: published
+
+Este exemplo mostra o uso de `@PersistenceContext` para ter um `EntityManager` com um contexto de persistência `EXTENDED` injetado em um `@Stateful bean`. Um bean JPA `@ Entity` é usado com o `EntityManager` para criar, persistir e mesclar dados em um banco de dados.
+
+== Criando a entidade JPA
+
+A própria entidade é simplesmente um pote anotado com `@Entity`. Criamos um chamado `Movie`, que podemos usar para armazenar registros de filmes.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.persistence.Entity;
+
+@Entity
+public class Movie {
+
+ @Id @GeneratedValue
+ private long id;
+
+ private String director;
+ private String title;
+ private int year;
+
+ public Movie() {
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Movie(String director, String title, int year) {
+ this.director = director;
+ this.title = title;
+ this.year = year;
+ }
+
+ public String getDirector() {
+ return director;
+ }
+
+ public void setDirector(String director) {
+ this.director = director;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ public void setYear(int year) {
+ this.year = year;
+ }
+}
+----
+
+== Configure o EntityManager por meio de um arquivo persistence.xml
+
+A entidade `Movie` acima pode ser criada, removida, atualizada ou excluída através de um objeto` EntityManager`.
+O próprio `EntityManager` é configurado através de um arquivo `META-INF/persistence.xml` que é colocado no mesmo jar que a entidade `Movie`.
+
+[source,xml,numbered]
+----
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
+
+ <persistence-unit name="movie-unit">
+ <jta-data-source>movieDatabase</jta-data-source>
+ <non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
+ <class>org.superbiz.injection.jpa.Movie</class>
+
+ <properties>
+ <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+ </properties>
+ </persistence-unit>
+</persistence>
+----
+
+Observe que a entidade `Movie` é listada através de um elemento `<class>`. Isso não é necessário, mas pode ajudar no teste ou quando a classe `Movie` estiver localizada em um jar diferente do jar que contém o arquivo `persistence.xml`.
+
+==Injeção via @PersistenceContext
+
+O próprio `EntityManager` é criado pelo contêiner usando as informações no `persistence.xml`, portanto, para usá-lo em tempo de execução, basta solicitar que ele seja injetado em um de nossos componentes. Fazemos isso via `@PersistenceContext`
+
+A anotação `@PersistenceContext` pode ser usada em qualquer bean CDI, EJB, Servlet, Servlet Listener, Servlet Filter ou JSF ManagedBean. Se você não usar um EJB, precisará usar um `UserTransaction` para iniciar e confirmar transações manualmente. É necessária uma transação para que qualquer um dos métodos de criação, atualização ou exclusão do EntityManager funcione.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.ejb.Stateful;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.PersistenceContextType;
+import jakarta.persistence.Query;
+import java.util.List;
+
+@Stateful
+public class Movies {
+
+ @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED)
+ private EntityManager entityManager;
+
+ public void addMovie(Movie movie) throws Exception {
+ entityManager.persist(movie);
+ }
+
+ public void deleteMovie(Movie movie) throws Exception {
+ entityManager.remove(movie);
+ }
+
+ public List<Movie> getMovies() throws Exception {
+ Query query = entityManager.createQuery("SELECT m from Movie as m");
+ return query.getResultList();
+ }
+}
+----
+
+Este `EntityManager` específico é injetado como um contexto de persistência `EXTENDED`, o que significa simplesmente que o `EntityManager` é criado quando o bean `@Stateful` é criado e destruído quando o bean `@Stateful` é destruído. Simplificando, os dados no `EntityManager` são armazenados em cache durante o tempo de vida do bean `@ Stateful`.
+
+O uso de contextos de persistência `EXTENDED` está *apenas* disponível para beans `@Stateful`. Consulte o link: ../../jpa-concepts.html [Conceitos da JPA] para obter uma explicação de alto nível sobre o que realmente é um "contexto de persistência" e como é significativo para a JPA.
+
+== MoviesTest
+
+Testar o JPA é bastante fácil, podemos simplesmente usar a API `EJBContainer` para criar um contêiner em nosso caso de teste.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import junit.framework.TestCase;
+
+import jakarta.ejb.embeddable.EJBContainer;
+import javax.naming.Context;
+import java.util.List;
+import java.util.Properties;
+
+public class MoviesTest extends TestCase {
+
+ public void test() throws Exception {
+
+ final Properties p = new Properties();
+ p.put("movieDatabase", "new://Resource?type=DataSource");
+ p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
+ p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb");
+
+ final Context context = EJBContainer.createEJBContainer(p).getContext();
+
+ Movies movies = (Movies) context.lookup("java:global/injection-of-entitymanager/Movies");
+
+ movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992));
+ movies.addMovie(new Movie("Joel Coen", "Fargo", 1996));
+ movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998));
+
+ List<Movie> list = movies.getMovies();
+ assertEquals("List.size()", 3, list.size());
+
+ for (Movie movie : list) {
+ movies.deleteMovie(movie);
+ }
+
+ assertEquals("Movies.getMovies()", 0, movies.getMovies().size());
+ }
+}
+----
+
+= Executando
+
+Quando executamos nosso caso de teste, devemos ver uma saída semelhante à seguinte.
+
+[source,console]
+----
+-------------------------------------------------------
+ T E S T S
+-------------------------------------------------------
+Running org.superbiz.injection.jpa.MoviesTest
+Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06
+http://tomee.apache.org/
+INFO - openejb.home = /Users/dblevins/examples/injection-of-entitymanager
+INFO - openejb.base = /Users/dblevins/examples/injection-of-entitymanager
+INFO - Using 'jakarta.ejb.embeddable.EJBContainer=true'
+INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
+INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
+INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database)
+INFO - Found EjbModule in classpath: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Beginning load: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Configuring enterprise application: /Users/dblevins/examples/injection-of-entitymanager
+INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container)
+INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container)
+INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
+INFO - Auto-creating a container for bean org.superbiz.injection.jpa.MoviesTest: Container(type=MANAGED, id=Default Managed Container)
+INFO - Configuring PersistenceUnit(name=movie-unit)
+INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'.
+INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase)
+INFO - Adjusting PersistenceUnit movie-unit <non-jta-data-source> to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged'
+INFO - Enterprise application "/Users/dblevins/examples/injection-of-entitymanager" loaded.
+INFO - Assembling app: /Users/dblevins/examples/injection-of-entitymanager
+INFO - PersistenceUnit(name=movie-unit, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 462ms
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies!org.superbiz.injection.jpa.Movies")
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest!org.superbiz.injection.jpa.MoviesTest")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest")
+INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Created Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Started Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Deployed Application(path=/Users/dblevins/examples/injection-of-entitymanager)
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.301 sec
+
+Results :
+
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
+----
diff --git a/src/test/resources/ApisUsedTest/noDuplicates/after.adoc b/src/test/resources/ApisUsedTest/noDuplicates/after.adoc
new file mode 100644
index 0000000..f83a09d
--- /dev/null
+++ b/src/test/resources/ApisUsedTest/noDuplicates/after.adoc
@@ -0,0 +1,230 @@
+= Injeção de Entitymanager
+:index-group: JPA
+:jbake-type: page
+:jbake-status: published
+
+Este exemplo mostra o uso de `@PersistenceContext` para ter um `EntityManager` com um contexto de persistência `EXTENDED` injetado em um `@Stateful bean`. Um bean JPA `@ Entity` é usado com o `EntityManager` para criar, persistir e mesclar dados em um banco de dados.
+
+== Criando a entidade JPA
+
+A própria entidade é simplesmente um pote anotado com `@Entity`. Criamos um chamado `Movie`, que podemos usar para armazenar registros de filmes.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.persistence.Entity;
+
+@Entity
+public class Movie {
+
+ @Id @GeneratedValue
+ private long id;
+
+ private String director;
+ private String title;
+ private int year;
+
+ public Movie() {
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Movie(String director, String title, int year) {
+ this.director = director;
+ this.title = title;
+ this.year = year;
+ }
+
+ public String getDirector() {
+ return director;
+ }
+
+ public void setDirector(String director) {
+ this.director = director;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ public void setYear(int year) {
+ this.year = year;
+ }
+}
+----
+
+== Configure o EntityManager por meio de um arquivo persistence.xml
+
+A entidade `Movie` acima pode ser criada, removida, atualizada ou excluída através de um objeto` EntityManager`.
+O próprio `EntityManager` é configurado através de um arquivo `META-INF/persistence.xml` que é colocado no mesmo jar que a entidade `Movie`.
+
+[source,xml,numbered]
+----
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
+
+ <persistence-unit name="movie-unit">
+ <jta-data-source>movieDatabase</jta-data-source>
+ <non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
+ <class>org.superbiz.injection.jpa.Movie</class>
+
+ <properties>
+ <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+ </properties>
+ </persistence-unit>
+</persistence>
+----
+
+Observe que a entidade `Movie` é listada através de um elemento `<class>`. Isso não é necessário, mas pode ajudar no teste ou quando a classe `Movie` estiver localizada em um jar diferente do jar que contém o arquivo `persistence.xml`.
+
+==Injeção via @PersistenceContext
+
+O próprio `EntityManager` é criado pelo contêiner usando as informações no `persistence.xml`, portanto, para usá-lo em tempo de execução, basta solicitar que ele seja injetado em um de nossos componentes. Fazemos isso via `@PersistenceContext`
+
+A anotação `@PersistenceContext` pode ser usada em qualquer bean CDI, EJB, Servlet, Servlet Listener, Servlet Filter ou JSF ManagedBean. Se você não usar um EJB, precisará usar um `UserTransaction` para iniciar e confirmar transações manualmente. É necessária uma transação para que qualquer um dos métodos de criação, atualização ou exclusão do EntityManager funcione.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.ejb.Stateful;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.PersistenceContextType;
+import jakarta.persistence.Query;
+import java.util.List;
+
+@Stateful
+public class Movies {
+
+ @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED)
+ private EntityManager entityManager;
+
+ public void addMovie(Movie movie) throws Exception {
+ entityManager.persist(movie);
+ }
+
+ public void deleteMovie(Movie movie) throws Exception {
+ entityManager.remove(movie);
+ }
+
+ public List<Movie> getMovies() throws Exception {
+ Query query = entityManager.createQuery("SELECT m from Movie as m");
+ return query.getResultList();
+ }
+}
+----
+
+Este `EntityManager` específico é injetado como um contexto de persistência `EXTENDED`, o que significa simplesmente que o `EntityManager` é criado quando o bean `@Stateful` é criado e destruído quando o bean `@Stateful` é destruído. Simplificando, os dados no `EntityManager` são armazenados em cache durante o tempo de vida do bean `@ Stateful`.
+
+O uso de contextos de persistência `EXTENDED` está *apenas* disponível para beans `@Stateful`. Consulte o link: ../../jpa-concepts.html [Conceitos da JPA] para obter uma explicação de alto nível sobre o que realmente é um "contexto de persistência" e como é significativo para a JPA.
+
+== MoviesTest
+
+Testar o JPA é bastante fácil, podemos simplesmente usar a API `EJBContainer` para criar um contêiner em nosso caso de teste.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import junit.framework.TestCase;
+
+import jakarta.ejb.embeddable.EJBContainer;
+import javax.naming.Context;
+import java.util.List;
+import java.util.Properties;
+
+public class MoviesTest extends TestCase {
+
+ public void test() throws Exception {
+
+ final Properties p = new Properties();
+ p.put("movieDatabase", "new://Resource?type=DataSource");
+ p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
+ p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb");
+
+ final Context context = EJBContainer.createEJBContainer(p).getContext();
+
+ Movies movies = (Movies) context.lookup("java:global/injection-of-entitymanager/Movies");
+
+ movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992));
+ movies.addMovie(new Movie("Joel Coen", "Fargo", 1996));
+ movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998));
+
+ List<Movie> list = movies.getMovies();
+ assertEquals("List.size()", 3, list.size());
+
+ for (Movie movie : list) {
+ movies.deleteMovie(movie);
+ }
+
+ assertEquals("Movies.getMovies()", 0, movies.getMovies().size());
+ }
+}
+----
+
+= Executando
+
+Quando executamos nosso caso de teste, devemos ver uma saída semelhante à seguinte.
+
+[source,console]
+----
+-------------------------------------------------------
+ T E S T S
+-------------------------------------------------------
+Running org.superbiz.injection.jpa.MoviesTest
+Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06
+http://tomee.apache.org/
+INFO - openejb.home = /Users/dblevins/examples/injection-of-entitymanager
+INFO - openejb.base = /Users/dblevins/examples/injection-of-entitymanager
+INFO - Using 'jakarta.ejb.embeddable.EJBContainer=true'
+INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
+INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
+INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database)
+INFO - Found EjbModule in classpath: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Beginning load: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Configuring enterprise application: /Users/dblevins/examples/injection-of-entitymanager
+INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container)
+INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container)
+INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
+INFO - Auto-creating a container for bean org.superbiz.injection.jpa.MoviesTest: Container(type=MANAGED, id=Default Managed Container)
+INFO - Configuring PersistenceUnit(name=movie-unit)
+INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'.
+INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase)
+INFO - Adjusting PersistenceUnit movie-unit <non-jta-data-source> to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged'
+INFO - Enterprise application "/Users/dblevins/examples/injection-of-entitymanager" loaded.
+INFO - Assembling app: /Users/dblevins/examples/injection-of-entitymanager
+INFO - PersistenceUnit(name=movie-unit, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 462ms
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies!org.superbiz.injection.jpa.Movies")
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest!org.superbiz.injection.jpa.MoviesTest")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest")
+INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Created Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Started Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Deployed Application(path=/Users/dblevins/examples/injection-of-entitymanager)
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.301 sec
+
+Results :
+
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
+----
+
+= APIs Used
+
+- link:../../../jakartaee-9.0/javadoc/jakarta/persistence/Entity.html[jakarta.persistence.Entity]
diff --git a/src/test/resources/ApisUsedTest/noDuplicates/before.adoc b/src/test/resources/ApisUsedTest/noDuplicates/before.adoc
new file mode 100644
index 0000000..5a86e09
--- /dev/null
+++ b/src/test/resources/ApisUsedTest/noDuplicates/before.adoc
@@ -0,0 +1,226 @@
+= Injeção de Entitymanager
+:index-group: JPA
+:jbake-type: page
+:jbake-status: published
+
+Este exemplo mostra o uso de `@PersistenceContext` para ter um `EntityManager` com um contexto de persistência `EXTENDED` injetado em um `@Stateful bean`. Um bean JPA `@ Entity` é usado com o `EntityManager` para criar, persistir e mesclar dados em um banco de dados.
+
+== Criando a entidade JPA
+
+A própria entidade é simplesmente um pote anotado com `@Entity`. Criamos um chamado `Movie`, que podemos usar para armazenar registros de filmes.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.persistence.Entity;
+
+@Entity
+public class Movie {
+
+ @Id @GeneratedValue
+ private long id;
+
+ private String director;
+ private String title;
+ private int year;
+
+ public Movie() {
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Movie(String director, String title, int year) {
+ this.director = director;
+ this.title = title;
+ this.year = year;
+ }
+
+ public String getDirector() {
+ return director;
+ }
+
+ public void setDirector(String director) {
+ this.director = director;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ public void setYear(int year) {
+ this.year = year;
+ }
+}
+----
+
+== Configure o EntityManager por meio de um arquivo persistence.xml
+
+A entidade `Movie` acima pode ser criada, removida, atualizada ou excluída através de um objeto` EntityManager`.
+O próprio `EntityManager` é configurado através de um arquivo `META-INF/persistence.xml` que é colocado no mesmo jar que a entidade `Movie`.
+
+[source,xml,numbered]
+----
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
+
+ <persistence-unit name="movie-unit">
+ <jta-data-source>movieDatabase</jta-data-source>
+ <non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
+ <class>org.superbiz.injection.jpa.Movie</class>
+
+ <properties>
+ <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+ </properties>
+ </persistence-unit>
+</persistence>
+----
+
+Observe que a entidade `Movie` é listada através de um elemento `<class>`. Isso não é necessário, mas pode ajudar no teste ou quando a classe `Movie` estiver localizada em um jar diferente do jar que contém o arquivo `persistence.xml`.
+
+==Injeção via @PersistenceContext
+
+O próprio `EntityManager` é criado pelo contêiner usando as informações no `persistence.xml`, portanto, para usá-lo em tempo de execução, basta solicitar que ele seja injetado em um de nossos componentes. Fazemos isso via `@PersistenceContext`
+
+A anotação `@PersistenceContext` pode ser usada em qualquer bean CDI, EJB, Servlet, Servlet Listener, Servlet Filter ou JSF ManagedBean. Se você não usar um EJB, precisará usar um `UserTransaction` para iniciar e confirmar transações manualmente. É necessária uma transação para que qualquer um dos métodos de criação, atualização ou exclusão do EntityManager funcione.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import jakarta.ejb.Stateful;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.PersistenceContextType;
+import jakarta.persistence.Query;
+import java.util.List;
+
+@Stateful
+public class Movies {
+
+ @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED)
+ private EntityManager entityManager;
+
+ public void addMovie(Movie movie) throws Exception {
+ entityManager.persist(movie);
+ }
+
+ public void deleteMovie(Movie movie) throws Exception {
+ entityManager.remove(movie);
+ }
+
+ public List<Movie> getMovies() throws Exception {
+ Query query = entityManager.createQuery("SELECT m from Movie as m");
+ return query.getResultList();
+ }
+}
+----
+
+Este `EntityManager` específico é injetado como um contexto de persistência `EXTENDED`, o que significa simplesmente que o `EntityManager` é criado quando o bean `@Stateful` é criado e destruído quando o bean `@Stateful` é destruído. Simplificando, os dados no `EntityManager` são armazenados em cache durante o tempo de vida do bean `@ Stateful`.
+
+O uso de contextos de persistência `EXTENDED` está *apenas* disponível para beans `@Stateful`. Consulte o link: ../../jpa-concepts.html [Conceitos da JPA] para obter uma explicação de alto nível sobre o que realmente é um "contexto de persistência" e como é significativo para a JPA.
+
+== MoviesTest
+
+Testar o JPA é bastante fácil, podemos simplesmente usar a API `EJBContainer` para criar um contêiner em nosso caso de teste.
+
+[source,java,numbered]
+----
+package org.superbiz.injection.jpa;
+
+import junit.framework.TestCase;
+
+import jakarta.ejb.embeddable.EJBContainer;
+import javax.naming.Context;
+import java.util.List;
+import java.util.Properties;
+
+public class MoviesTest extends TestCase {
+
+ public void test() throws Exception {
+
+ final Properties p = new Properties();
+ p.put("movieDatabase", "new://Resource?type=DataSource");
+ p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
+ p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb");
+
+ final Context context = EJBContainer.createEJBContainer(p).getContext();
+
+ Movies movies = (Movies) context.lookup("java:global/injection-of-entitymanager/Movies");
+
+ movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992));
+ movies.addMovie(new Movie("Joel Coen", "Fargo", 1996));
+ movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998));
+
+ List<Movie> list = movies.getMovies();
+ assertEquals("List.size()", 3, list.size());
+
+ for (Movie movie : list) {
+ movies.deleteMovie(movie);
+ }
+
+ assertEquals("Movies.getMovies()", 0, movies.getMovies().size());
+ }
+}
+----
+
+= Executando
+
+Quando executamos nosso caso de teste, devemos ver uma saída semelhante à seguinte.
+
+[source,console]
+----
+-------------------------------------------------------
+ T E S T S
+-------------------------------------------------------
+Running org.superbiz.injection.jpa.MoviesTest
+Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06
+http://tomee.apache.org/
+INFO - openejb.home = /Users/dblevins/examples/injection-of-entitymanager
+INFO - openejb.base = /Users/dblevins/examples/injection-of-entitymanager
+INFO - Using 'jakarta.ejb.embeddable.EJBContainer=true'
+INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
+INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
+INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database)
+INFO - Found EjbModule in classpath: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Beginning load: /Users/dblevins/examples/injection-of-entitymanager/target/classes
+INFO - Configuring enterprise application: /Users/dblevins/examples/injection-of-entitymanager
+INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container)
+INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container)
+INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
+INFO - Auto-creating a container for bean org.superbiz.injection.jpa.MoviesTest: Container(type=MANAGED, id=Default Managed Container)
+INFO - Configuring PersistenceUnit(name=movie-unit)
+INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'.
+INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase)
+INFO - Adjusting PersistenceUnit movie-unit <non-jta-data-source> to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged'
+INFO - Enterprise application "/Users/dblevins/examples/injection-of-entitymanager" loaded.
+INFO - Assembling app: /Users/dblevins/examples/injection-of-entitymanager
+INFO - PersistenceUnit(name=movie-unit, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 462ms
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies!org.superbiz.injection.jpa.Movies")
+INFO - Jndi(name="java:global/injection-of-entitymanager/Movies")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest!org.superbiz.injection.jpa.MoviesTest")
+INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest")
+INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Created Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Started Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container)
+INFO - Deployed Application(path=/Users/dblevins/examples/injection-of-entitymanager)
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.301 sec
+
+Results :
+
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
+----
diff --git a/src/test/resources/SeeLinksTest/insertHref/after.java b/src/test/resources/ExampleLinksTest/finalClass/after.java
similarity index 93%
copy from src/test/resources/SeeLinksTest/insertHref/after.java
copy to src/test/resources/ExampleLinksTest/finalClass/after.java
index 75f3b52..e91e524 100644
--- a/src/test/resources/SeeLinksTest/insertHref/after.java
+++ b/src/test/resources/ExampleLinksTest/finalClass/after.java
@@ -27,9 +27,9 @@
* entity class.
*
* @since Java Persistence 1.0
- * @see <a href="http://example.org/orange.html">Orange Example</a>
+ * @example <a href="http://example.org/orange.html">Orange Example</a>
*/
-public interface Entity {
+final public interface Entity {
/**
* (Optional) The entity name. Defaults to the unqualified
diff --git a/src/test/resources/SeeLinksTest/insertHref/after.java b/src/test/resources/ExampleLinksTest/finalClass/before.java
similarity index 93%
copy from src/test/resources/SeeLinksTest/insertHref/after.java
copy to src/test/resources/ExampleLinksTest/finalClass/before.java
index 75f3b52..eeee40d 100644
--- a/src/test/resources/SeeLinksTest/insertHref/after.java
+++ b/src/test/resources/ExampleLinksTest/finalClass/before.java
@@ -27,9 +27,8 @@
* entity class.
*
* @since Java Persistence 1.0
- * @see <a href="http://example.org/orange.html">Orange Example</a>
*/
-public interface Entity {
+final public interface Entity {
/**
* (Optional) The entity name. Defaults to the unqualified
diff --git a/src/test/resources/SeeLinksTest/hasAnnotations/after.java b/src/test/resources/ExampleLinksTest/hasAnnotations/after.java
similarity index 95%
rename from src/test/resources/SeeLinksTest/hasAnnotations/after.java
rename to src/test/resources/ExampleLinksTest/hasAnnotations/after.java
index f5a3706..ceefe62 100644
--- a/src/test/resources/SeeLinksTest/hasAnnotations/after.java
+++ b/src/test/resources/ExampleLinksTest/hasAnnotations/after.java
@@ -23,7 +23,7 @@
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
- * @see <a href="http://example.org/orange.html">Orange Example</a>
+ * @example <a href="http://example.org/orange.html">Orange Example</a>
*/
@Documented
@Target(TYPE)
diff --git a/src/test/resources/SeeLinksTest/hasAnnotations/before.java b/src/test/resources/ExampleLinksTest/hasAnnotations/before.java
similarity index 100%
rename from src/test/resources/SeeLinksTest/hasAnnotations/before.java
rename to src/test/resources/ExampleLinksTest/hasAnnotations/before.java
diff --git a/src/test/resources/SeeLinksTest/insertHref/after.java b/src/test/resources/ExampleLinksTest/insertHref/after.java
similarity index 95%
rename from src/test/resources/SeeLinksTest/insertHref/after.java
rename to src/test/resources/ExampleLinksTest/insertHref/after.java
index 75f3b52..ef26259 100644
--- a/src/test/resources/SeeLinksTest/insertHref/after.java
+++ b/src/test/resources/ExampleLinksTest/insertHref/after.java
@@ -27,7 +27,7 @@
* entity class.
*
* @since Java Persistence 1.0
- * @see <a href="http://example.org/orange.html">Orange Example</a>
+ * @example <a href="http://example.org/orange.html">Orange Example</a>
*/
public interface Entity {
diff --git a/src/test/resources/SeeLinksTest/insertHref/before.java b/src/test/resources/ExampleLinksTest/insertHref/before.java
similarity index 100%
rename from src/test/resources/SeeLinksTest/insertHref/before.java
rename to src/test/resources/ExampleLinksTest/insertHref/before.java
diff --git a/src/test/resources/SeeLinksTest/multipleInserts/after1.java b/src/test/resources/ExampleLinksTest/multipleInserts/after1.java
similarity index 92%
rename from src/test/resources/SeeLinksTest/multipleInserts/after1.java
rename to src/test/resources/ExampleLinksTest/multipleInserts/after1.java
index 13ae94a..0aa811d 100644
--- a/src/test/resources/SeeLinksTest/multipleInserts/after1.java
+++ b/src/test/resources/ExampleLinksTest/multipleInserts/after1.java
@@ -17,7 +17,7 @@
package javax.persistence;
/**
- * @see <a href="http://example.org/orange.html">Orange Example</a>
+ * @example <a href="http://example.org/orange.html">Orange Example</a>
*/
public enum Shapes {
CIRCLE,
diff --git a/src/test/resources/SeeLinksTest/multipleInserts/after1.java b/src/test/resources/ExampleLinksTest/multipleInserts/after2.java
similarity index 86%
copy from src/test/resources/SeeLinksTest/multipleInserts/after1.java
copy to src/test/resources/ExampleLinksTest/multipleInserts/after2.java
index 13ae94a..7471d5e 100644
--- a/src/test/resources/SeeLinksTest/multipleInserts/after1.java
+++ b/src/test/resources/ExampleLinksTest/multipleInserts/after2.java
@@ -17,7 +17,8 @@
package javax.persistence;
/**
- * @see <a href="http://example.org/orange.html">Orange Example</a>
+ * @example <a href="http://example.org/orange.html">Orange Example</a>
+ * @example <a href="http://example.org/red.html">Red Sample</a>
*/
public enum Shapes {
CIRCLE,
diff --git a/src/test/resources/SeeLinksTest/multipleInserts/after1.java b/src/test/resources/ExampleLinksTest/multipleInserts/after3.java
similarity index 81%
copy from src/test/resources/SeeLinksTest/multipleInserts/after1.java
copy to src/test/resources/ExampleLinksTest/multipleInserts/after3.java
index 13ae94a..5eb5e0d 100644
--- a/src/test/resources/SeeLinksTest/multipleInserts/after1.java
+++ b/src/test/resources/ExampleLinksTest/multipleInserts/after3.java
@@ -17,7 +17,9 @@
package javax.persistence;
/**
- * @see <a href="http://example.org/orange.html">Orange Example</a>
+ * @example <a href="http://example.org/orange.html">Orange Example</a>
+ * @example <a href="http://example.org/red.html">Red Sample</a>
+ * @example <a href="http://example.org/yellow.html">yellow</a>
*/
public enum Shapes {
CIRCLE,
diff --git a/src/test/resources/SeeLinksTest/multipleInserts/before.java b/src/test/resources/ExampleLinksTest/multipleInserts/before.java
similarity index 100%
rename from src/test/resources/SeeLinksTest/multipleInserts/before.java
rename to src/test/resources/ExampleLinksTest/multipleInserts/before.java
diff --git a/src/test/resources/SeeLinksTest/insertHref/after.java b/src/test/resources/ExampleLinksTest/noDuplicates/after.java
similarity index 95%
copy from src/test/resources/SeeLinksTest/insertHref/after.java
copy to src/test/resources/ExampleLinksTest/noDuplicates/after.java
index 75f3b52..ef26259 100644
--- a/src/test/resources/SeeLinksTest/insertHref/after.java
+++ b/src/test/resources/ExampleLinksTest/noDuplicates/after.java
@@ -27,7 +27,7 @@
* entity class.
*
* @since Java Persistence 1.0
- * @see <a href="http://example.org/orange.html">Orange Example</a>
+ * @example <a href="http://example.org/orange.html">Orange Example</a>
*/
public interface Entity {
diff --git a/src/test/resources/SeeLinksTest/noDuplicates/before.java b/src/test/resources/ExampleLinksTest/noDuplicates/before.java
similarity index 100%
rename from src/test/resources/SeeLinksTest/noDuplicates/before.java
rename to src/test/resources/ExampleLinksTest/noDuplicates/before.java
diff --git a/src/test/resources/SeeLinksTest/noJavadoc/after.java b/src/test/resources/ExampleLinksTest/noJavadoc/after.java
similarity index 93%
rename from src/test/resources/SeeLinksTest/noJavadoc/after.java
rename to src/test/resources/ExampleLinksTest/noJavadoc/after.java
index da7abb7..9ed617c 100644
--- a/src/test/resources/SeeLinksTest/noJavadoc/after.java
+++ b/src/test/resources/ExampleLinksTest/noJavadoc/after.java
@@ -17,7 +17,7 @@
package javax.persistence;
/**
- * @see <a href="http://example.org/orange.html">Orange Example</a>
+ * @example <a href="http://example.org/orange.html">Orange Example</a>
*/
public @interface Entity {
diff --git a/src/test/resources/SeeLinksTest/noJavadoc/before.java b/src/test/resources/ExampleLinksTest/noJavadoc/before.java
similarity index 100%
rename from src/test/resources/SeeLinksTest/noJavadoc/before.java
rename to src/test/resources/ExampleLinksTest/noJavadoc/before.java
diff --git a/src/test/resources/SeeLinksTest/multipleInserts/after2.java b/src/test/resources/SeeLinksTest/multipleInserts/after2.java
deleted file mode 100644
index d673789..0000000
--- a/src/test/resources/SeeLinksTest/multipleInserts/after2.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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 javax.persistence;
-
-/**
- * @see <a href="http://example.org/orange.html">Orange Example</a>
- * @see <a href="http://example.org/red.html">Red Sample</a>
- */
-public enum Shapes {
- CIRCLE,
- TRIANGLE,
- SQUARE
-}
\ No newline at end of file
diff --git a/src/test/resources/SeeLinksTest/multipleInserts/after3.java b/src/test/resources/SeeLinksTest/multipleInserts/after3.java
deleted file mode 100644
index a7f36e1..0000000
--- a/src/test/resources/SeeLinksTest/multipleInserts/after3.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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 javax.persistence;
-
-/**
- * @see <a href="http://example.org/orange.html">Orange Example</a>
- * @see <a href="http://example.org/red.html">Red Sample</a>
- * @see <a href="http://example.org/yellow.html">yellow</a>
- */
-public enum Shapes {
- CIRCLE,
- TRIANGLE,
- SQUARE
-}
\ No newline at end of file
diff --git a/src/test/resources/SeeLinksTest/noDuplicates/after.java b/src/test/resources/SeeLinksTest/noDuplicates/after.java
deleted file mode 100644
index 75f3b52..0000000
--- a/src/test/resources/SeeLinksTest/noDuplicates/after.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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 javax.persistence;
-
-import java.lang.annotation.Target;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Documented;
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-/**
- * Specifies that the class is an entity. This annotation is applied to the
- * entity class.
- *
- * @since Java Persistence 1.0
- * @see <a href="http://example.org/orange.html">Orange Example</a>
- */
-public interface Entity {
-
- /**
- * (Optional) The entity name. Defaults to the unqualified
- * name of the entity class. This name is used to refer to the
- * entity in queries. The name must not be a reserved literal
- * in the Java Persistence query language.
- */
- String name();
-}
\ No newline at end of file