You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@training.apache.org by rb...@apache.org on 2026/05/24 17:13:04 UTC

(training) branch bval-starter-presentation created (now 98d1ee8)

This is an automated email from the ASF dual-hosted git repository.

rbowen pushed a change to branch bval-starter-presentation
in repository https://gitbox.apache.org/repos/asf/training.git


      at 98d1ee8  Add BVal starter presentation

This branch includes the following new commits:

     new 98d1ee8  Add BVal starter presentation

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(training) 01/01: Add BVal starter presentation

Posted by rb...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rbowen pushed a commit to branch bval-starter-presentation
in repository https://gitbox.apache.org/repos/asf/training.git

commit 98d1ee8fa14035363f05a77c17d4aa3298a1bb1b
Author: Rich Bowen <rb...@rcbowen.com>
AuthorDate: Sun May 24 13:12:00 2026 -0400

    Add BVal starter presentation
    
    Generated training module for Apache BVal.
    Content researched from bval.apache.org.
    Requires human review before publishing.
---
 content/Apache/BVal/metadata.yaml                  |  28 ++
 content/Apache/BVal/pom.xml                        |  39 ++
 .../Apache/BVal/src/main/asciidoc/_settings.adoc   |  36 ++
 .../BVal/src/main/asciidoc/images/project-logo.png | Bin 0 -> 68018 bytes
 content/Apache/BVal/src/main/asciidoc/index.adoc   | 392 ++++++++++++++++++
 content/Apache/BVal/src/main/theme/apache.css      | 457 +++++++++++++++++++++
 6 files changed, 952 insertions(+)

diff --git a/content/Apache/BVal/metadata.yaml b/content/Apache/BVal/metadata.yaml
new file mode 100644
index 0000000..c07bf00
--- /dev/null
+++ b/content/Apache/BVal/metadata.yaml
@@ -0,0 +1,28 @@
+# 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.
+
+title: "Apache BVal"
+project_id: bval
+description: "Jakarta Bean Validation implementation - TCK compliant, Apache licensed"
+tags:
+  - libraries
+  - jvm
+  - intro
+  - developer
+duration: "45-60 min"
+level: beginner
+language: java
+slides: 25
+updated: "2026-05-24"
diff --git a/content/Apache/BVal/pom.xml b/content/Apache/BVal/pom.xml
new file mode 100644
index 0000000..86124d3
--- /dev/null
+++ b/content/Apache/BVal/pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.training</groupId>
+    <artifactId>content-parent-pom</artifactId>
+    <version>1.5.0-SNAPSHOT</version>
+    <relativePath>../../../tools/content-parent-pom/pom.xml</relativePath>
+  </parent>
+
+  <groupId>org.apache.training.content</groupId>
+  <artifactId>training-content-apache-bval</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>war</packaging>
+
+  <name>Training: Content: Apache: BVal</name>
+  <description>Training module for Apache BVal - Jakarta Bean Validation implementation</description>
+
+</project>
diff --git a/content/Apache/BVal/src/main/asciidoc/_settings.adoc b/content/Apache/BVal/src/main/asciidoc/_settings.adoc
new file mode 100644
index 0000000..9a16917
--- /dev/null
+++ b/content/Apache/BVal/src/main/asciidoc/_settings.adoc
@@ -0,0 +1,36 @@
+////
+
+  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.
+
+////
+
+:goto:
+:menu:
+:navigation:
+:status:
+:arrows:
+:revealjs_theme: black
+:revealjs_progress: true
+:revealjs_slidenumber: true
+:revealjs_center: false
+:revealjs_history: true
+:customcss: reveal.js-5.2.1/dist/theme/apache.css
+:favicon: https://apache.org/favicon.ico
+:icons: font
+:imagesdir: images
+:sourcedir: ../java
+:idprefix:
+:idseparator: -
diff --git a/content/Apache/BVal/src/main/asciidoc/images/project-logo.png b/content/Apache/BVal/src/main/asciidoc/images/project-logo.png
new file mode 100644
index 0000000..35e1dfc
Binary files /dev/null and b/content/Apache/BVal/src/main/asciidoc/images/project-logo.png differ
diff --git a/content/Apache/BVal/src/main/asciidoc/index.adoc b/content/Apache/BVal/src/main/asciidoc/index.adoc
new file mode 100644
index 0000000..e427c10
--- /dev/null
+++ b/content/Apache/BVal/src/main/asciidoc/index.adoc
@@ -0,0 +1,392 @@
+////
+
+  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.
+
+////
+
+include::_settings.adoc[]
+
+== Apache BVal
+
+image::project-logo.png[Apache BVal, 500]
+
+Jakarta Bean Validation Implementation — TCK Compliant, Apache Licensed
+
+[.notes]
+--
+Apache BVal delivers an implementation of the Jakarta Bean Validation 3.0 Specification which is TCK compliant, works on Java SE 11 or later, and uses the Apache Software License v2.0.
+--
+
+== What Is Bean Validation?
+
+* A standard way to declare constraints on Java objects
+* Annotations on fields, methods, and classes
+* Validate data at any application layer
+* Part of the Jakarta EE platform
+
+[.notes]
+--
+Bean Validation provides a unified way to express constraints on your domain model using annotations. Instead of writing validation logic scattered throughout your code, you declare what valid data looks like right on the model class itself. It works in any Java SE or Jakarta EE environment.
+--
+
+== Why Do We Need It?
+
+* Data validation is everywhere — forms, APIs, persistence
+* Without a standard, validation logic gets duplicated
+* Each layer re-implements the same checks
+* Bean Validation: write once, validate anywhere
+
+[.notes]
+--
+Before Bean Validation existed, developers would write validation logic in the UI layer, then again in the service layer, then again before persistence. Each copy could diverge. Bean Validation consolidates this into a single set of constraint declarations that can be enforced at any tier.
+--
+
+== What Is Apache BVal?
+
+* Apache's implementation of Jakarta Bean Validation
+* Current release: 3.0.2 (Jakarta Bean Validation 3.0)
+* TCK (Technology Compatibility Kit) compliant
+* Licensed under Apache License 2.0
+
+[.notes]
+--
+Apache BVal is the ASF's implementation of the Jakarta Bean Validation specification. The current stable release is 3.0.2, released March 15, 2025, implementing Jakarta Bean Validation 3.0. It passes the official TCK tests, ensuring full specification compliance.
+--
+
+== Project History
+
+* Originally donated by Agimatec GmbH (SGA)
+* Incubated at the ASF
+* Became a top-level project: February 15, 2012
+* Active development continues on the master/3.1.x branch
+
+[.notes]
+--
+The initial 0.x/1.x codebase was donated to the ASF by a Software Grant Agreement from Agimatec GmbH. After a successful incubation period, Apache BVal graduated to become a top-level project on February 15, 2012. Current development targets Jakarta Validation 3.1 on the master branch.
+--
+
+== Release History
+
+[cols="1,1,1", options="header"]
+|===
+| Version | Bean Validation | Java Requirement
+
+| 3.0.x
+| Jakarta Bean Validation 3.0
+| Java 11+
+
+| 2.0.x
+| Bean Validation 2.0 (JSR-380)
+| Java 8+
+
+| 1.1.x
+| Bean Validation 1.1 (JSR-349)
+| Java 6+
+
+| 0.5
+| Bean Validation 1.0 (JSR-303)
+| Java 5+
+|===
+
+[.notes]
+--
+BVal has evolved through multiple specification versions. The 3.0.x line uses the Jakarta namespace (jakarta.validation). The 2.0.x line uses the older javax.validation namespace. Choose the version matching your application server or Jakarta EE level.
+--
+
+// ============================================================
+// PART 2: GETTING STARTED
+// ============================================================
+
+== Getting Started
+
+image::project-logo.png[Apache BVal, 300]
+
+Adding BVal to Your Project
+
+[.notes]
+--
+Let's walk through how to add Apache BVal to a Maven project and start validating beans. The setup is straightforward since BVal artifacts are published to Maven Central under the org.apache.bval groupId.
+--
+
+== Maven Dependencies
+
+[source,xml]
+----
+<dependency>
+  <groupId>org.apache.bval</groupId>
+  <artifactId>bval-jsr</artifactId>
+  <version>3.0.2</version>
+</dependency> <!-- also: bval-extras, bval-bundle -->
+----
+* **bval-jsr** — Core validation provider
+* **bval-extras** — Additional constraints beyond the spec
+* **bval-bundle** — OSGi bundle (includes bval-jsr)
+
+[.notes]
+--
+Add bval-jsr to your pom.xml to get started. Maven will pull in the Jakarta Validation API and transitive dependencies automatically. The groupId is org.apache.bval for all modules. The bval-extras module provides additional constraints beyond the spec. The bval-bundle artifact packages everything with OSGi metadata for modular environments.
+--
+
+== Basic Usage: Create a Validator
+
+[source,java]
+----
+ValidatorFactory validatorFactory = Validation
+    .byProvider(ApacheValidationProvider.class)
+    .configure()
+    .buildValidatorFactory();
+
+Validator validator =
+    validatorFactory.getValidator();
+----
+
+[.notes]
+--
+This code explicitly requests the Apache BVal provider. You can also use Validation.buildDefaultValidatorFactory() which will discover BVal through the ServiceLoader mechanism if it's on the classpath. The explicit form shown here is useful when multiple providers are available.
+--
+
+== Basic Usage: Validate a Bean
+
+[source,java]
+----
+Set<ConstraintViolation<MyBean>> violations =
+    validator.validate(myBean);
+
+for (ConstraintViolation<MyBean> v : violations) {
+    System.out.println(
+        v.getPropertyPath() + ": "
+        + v.getMessage());
+}
+----
+
+[.notes]
+--
+Call validator.validate() passing your annotated bean. It returns a Set of ConstraintViolation objects — one per failed constraint. Each violation tells you which property failed and the error message. An empty set means the bean is valid.
+--
+
+== Built-in Constraints (Jakarta Spec)
+
+* `@NotNull`, `@NotBlank`, `@NotEmpty`, `@Size`
+* `@Min`, `@Max`, `@DecimalMin`, `@DecimalMax`
+* `@Pattern(regexp=)`, `@Email`
+* `@Past`, `@Future`, `@PastOrPresent`, `@FutureOrPresent`
+* `@Positive`, `@Negative`, `@Digits`, `@AssertTrue`
+
+[.notes]
+--
+These are the standard constraints defined by the Jakarta Bean Validation specification. Any compliant implementation, including BVal, supports all of these out of the box. They cover nullability, size, numeric ranges, regex patterns, email format, temporal checks, sign constraints, and boolean assertions.
+--
+
+== Annotated Bean Example
+
+[source,java]
+----
+public class User {
+    @NotBlank private String name;
+    @Email @NotNull private String email;
+    @Min(18) @Max(150) private int age;
+    @Past private LocalDate birthDate;
+    @Size(max = 100) private String bio;
+}
+----
+
+[.notes]
+--
+Here's a practical example. The User class declares that name must not be blank, email must be a valid email and not null, and age must be between 18 and 150. When you validate an instance of this class, BVal checks all these constraints and reports any violations.
+--
+
+== Custom Constraints
+
+[source,java]
+----
+@Target({FIELD, METHOD})
+@Retention(RUNTIME)
+@Constraint(validatedBy = PhoneValidator.class)
+public @interface ValidPhone {
+    String message() default "Invalid phone";
+    Class<?>[] groups() default {};
+}
+----
+
+[.notes]
+--
+You can define your own constraint annotations. Create an annotation with @Constraint pointing to a validator class. The message, groups, and payload attributes are required by the spec. Your custom validator implements ConstraintValidator and provides the isValid() logic.
+--
+
+== Validation Groups
+
+[source,java]
+----
+public interface OnCreate {}
+public interface OnUpdate {}
+
+public class Order {
+    @Null(groups = OnCreate.class)
+    @NotNull(groups = OnUpdate.class)
+    private Long id;
+}
+----
+
+* Apply different rules in different contexts
+* Pass groups to `validator.validate(bean, OnCreate.class)`
+
+[.notes]
+--
+Groups let you apply different validation rules depending on the context. For example, an ID should be null when creating a new entity but required when updating. You specify which groups to validate by passing them to the validate method.
+--
+
+== Integration with Jakarta EE
+
+* Works with CDI — inject ValidatorFactory
+* JAX-RS validates request/response automatically
+* JPA can trigger validation on persist/update
+* Works in any Jakarta EE compliant server
+
+[.notes]
+--
+Bean Validation integrates deeply with the Jakarta EE platform. CDI containers can inject validators. JAX-RS will validate annotated parameters automatically. JPA fires validation events on lifecycle callbacks. BVal works anywhere a Jakarta Bean Validation provider is expected.
+--
+
+// ============================================================
+// PART 3: COMMUNITY
+// ============================================================
+
+== Community
+
+image::project-logo.png[Apache BVal, 300]
+
+How to Get Involved
+
+[.notes]
+--
+Like all Apache projects, BVal is a community-driven effort. Let's look at how to connect with the project, report issues, and contribute.
+--
+
+== Mailing Lists
+
+* **dev@bval.apache.org** — Development discussions
+* **commits@bval.apache.org** — Source commit notifications
+* Subscribe via: dev-subscribe@bval.apache.org
+
+[.notes]
+--
+The dev mailing list is where design discussions, release votes, and community decisions happen. All development communication is done on-list for transparency. Subscribe by sending an empty email to dev-subscribe@bval.apache.org.
+--
+
+== Source Code
+
+* Git repository: https://gitbox.apache.org/repos/asf/bval.git
+* GitHub mirror: https://github.com/apache/bval
+* Branches:
+** `master` / `3.1.x` — Jakarta Validation 3.1 (Java 17+)
+** `3.0.x` — Jakarta Bean Validation 3.0 (Java 11+)
+** `2.x` — Bean Validation 2.0 (Java 8+)
+
+[.notes]
+--
+The canonical source is on ASF GitBox, with a read-only mirror on GitHub. The master branch targets the next major version — Jakarta Validation 3.1 requiring Java 17. If you need to patch the current stable release, work against the 3.0.x branch.
+--
+
+== Issue Tracker
+
+* JIRA: https://issues.apache.org/jira/browse/BVAL
+* File bugs, feature requests, improvements
+* Check existing issues before filing new ones
+
+[.notes]
+--
+Apache BVal uses the ASF JIRA instance for issue tracking. The project key is BVAL. Before filing a new issue, search existing ones to avoid duplicates. Include a minimal reproducer when reporting bugs — it dramatically speeds up diagnosis.
+--
+
+== Project Governance
+
+* Apache Software Foundation top-level project
+* PMC (Project Management Committee): 15 members
+* Established: February 2012
+* Decisions made by consensus on dev@ list
+
+[.notes]
+--
+BVal follows the standard Apache governance model. The PMC has 15 members who oversee releases, community health, and project direction. All binding decisions happen on the public mailing list. New committers and PMC members are nominated and voted on by existing PMC members.
+--
+
+== How to Contribute
+
+* Start by subscribing to dev@bval.apache.org
+* Look for open JIRA issues
+* Submit patches via GitHub pull requests
+* Follow the Apache contributor guidelines
+* No contribution is too small!
+
+[.notes]
+--
+The easiest way to start contributing is to pick up a bug or improvement from JIRA. Fork the GitHub mirror, make your changes, and submit a pull request. Introduce yourself on the dev list. Documentation improvements, test cases, and bug reports are all valuable contributions.
+--
+
+== Building from Source
+
+[source,bash]
+----
+git clone \
+  https://gitbox.apache.org/repos/asf/bval.git
+cd bval
+mvn clean install
+----
+
+* Standard Maven build
+* Requires Java 11+ (3.0.x branch) or Java 17+ (master)
+
+[.notes]
+--
+Building BVal from source is straightforward. Clone the repo and run mvn clean install. Make sure your JAVA_HOME points to the appropriate JDK version for the branch you're building. The TCK tests run as part of the normal build to verify compliance.
+--
+
+== Summary
+
+* Apache BVal = Jakarta Bean Validation implementation
+* TCK compliant, Apache 2.0 licensed
+* Current stable: 3.0.2 (Java 11+, Jakarta Bean Validation 3.0)
+* Next: 3.1.x (Java 17+, Jakarta Validation 3.1)
+* Community-driven ASF top-level project
+
+[.notes]
+--
+To recap: Apache BVal gives you a fully compliant, Apache-licensed implementation of Jakarta Bean Validation. It's lightweight, well-tested against the TCK, and actively maintained. Whether you're building microservices or enterprise applications, BVal provides reliable constraint validation for your Java beans.
+--
+
+== Resources
+
+* Website: https://bval.apache.org
+* Downloads: https://bval.apache.org/downloads.html
+* Source: https://github.com/apache/bval
+* Issues: https://issues.apache.org/jira/browse/BVAL
+* Dev list: dev@bval.apache.org
+
+[.notes]
+--
+Here are the key links for Apache BVal. The website has download links and documentation. The GitHub mirror is convenient for browsing code and submitting pull requests. The JIRA issue tracker is where bugs and features are tracked. And the dev mailing list is where the community conversation happens.
+--
+
+== Thank You
+
+image::project-logo.png[Apache BVal, 300]
+
+https://bval.apache.org
+
+[.notes]
+--
+Thank you for attending this session on Apache BVal. Visit bval.apache.org for more information, and consider joining the community if you're interested in contributing to a Jakarta Bean Validation implementation.
+--
diff --git a/content/Apache/BVal/src/main/theme/apache.css b/content/Apache/BVal/src/main/theme/apache.css
new file mode 100644
index 0000000..d8f2a14
--- /dev/null
+++ b/content/Apache/BVal/src/main/theme/apache.css
@@ -0,0 +1,457 @@
+/*
+  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
+
+    https://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+*/
+
+/*********************************************
+ * APACHE TRAINING DARK THEME
+ * White text on black, large fonts for
+ * conference room visibility.
+ *********************************************/
+
+/*********************************************
+ * GLOBAL STYLES
+ *********************************************/
+body {
+  background-color: #1a1a1a;
+  background-image: none;
+}
+
+.reveal-viewport {
+  background-color: #1a1a1a;
+  color: #f0f0f0;
+  background-image: none !important;
+}
+
+.reveal {
+  font-family: "Segoe UI", Helvetica, Arial, sans-serif;
+  font-size: 32px;
+  font-weight: normal;
+  color: #f0f0f0;
+}
+
+/*********************************************
+ * SLIDE OVERFLOW — allow scrolling if content
+ * exceeds slide height
+ *********************************************/
+.reveal .slides section {
+  height: auto !important;
+  overflow-y: auto !important;
+}
+
+::selection {
+  color: #fff;
+  background: #42affa;
+  text-shadow: none;
+}
+
+.reveal .slides > section, .reveal .slides > section > section {
+  line-height: 1.4;
+  font-weight: inherit;
+}
+
+/*********************************************
+ * HEADERS — smaller than default
+ *********************************************/
+.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 {
+  margin: 0 0 20px 0;
+  color: #ffffff;
+  font-family: "Segoe UI", Helvetica, Arial, sans-serif;
+  font-weight: 600;
+  line-height: 1.2;
+  letter-spacing: normal;
+  text-transform: none;
+  text-shadow: none;
+  word-wrap: break-word;
+}
+
+.reveal h1 {
+  font-size: 1.4em;
+}
+
+.reveal h2 {
+  font-size: 1.0em;
+}
+
+.reveal h3 {
+  font-size: 0.9em;
+}
+
+.reveal h4 {
+  font-size: 0.8em;
+}
+
+/*********************************************
+ * BODY TEXT — large for back-of-room
+ *********************************************/
+.reveal p {
+  margin: 20px 0;
+  line-height: 1.4;
+  font-size: 1em;
+}
+
+.reveal li {
+  font-size: 0.95em;
+  margin-bottom: 0.3em;
+}
+
+/* Ensure certain elements are never larger than the slide itself */
+.reveal img, .reveal video, .reveal iframe {
+  max-width: 95%;
+  max-height: 85%;
+}
+
+.reveal strong, .reveal b {
+  font-weight: bold;
+  color: #ffffff;
+}
+
+.reveal em {
+  font-style: italic;
+}
+
+.reveal ol, .reveal dl, .reveal ul {
+  display: inline-block;
+  text-align: left;
+  margin: 0 0 0 1em;
+}
+
+.reveal ol {
+  list-style-type: decimal;
+}
+
+.reveal ul {
+  list-style-type: disc;
+}
+
+.reveal ul ul {
+  list-style-type: square;
+}
+
+.reveal ul ul ul {
+  list-style-type: circle;
+}
+
+.reveal ul ul, .reveal ul ol, .reveal ol ol, .reveal ol ul {
+  display: block;
+  margin-left: 40px;
+}
+
+.reveal dt {
+  font-weight: bold;
+}
+
+.reveal dd {
+  margin-left: 40px;
+}
+
+.reveal q, .reveal blockquote {
+  quotes: none;
+}
+
+.reveal blockquote {
+  display: block;
+  position: relative;
+  width: 70%;
+  margin: 20px auto;
+  padding: 5px;
+  font-style: italic;
+  background: rgba(255, 255, 255, 0.05);
+  box-shadow: 0 0 2px rgba(255, 255, 255, 0.2);
+  color: #ccc;
+}
+
+.reveal blockquote p:first-child, .reveal blockquote p:last-child {
+  display: inline-block;
+}
+
+.reveal q {
+  font-style: italic;
+}
+
+/*********************************************
+ * CODE
+ *********************************************/
+.reveal pre {
+  display: block;
+  position: relative;
+  width: 90%;
+  margin: 20px auto;
+  text-align: left;
+  font-size: 0.55em;
+  font-family: "Fira Code", "Consolas", monospace;
+  line-height: 1.3em;
+  word-wrap: break-word;
+  box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
+}
+
+.reveal code {
+  font-family: "Fira Code", "Consolas", monospace;
+}
+
+.reveal pre code {
+  display: block;
+  padding: 10px;
+  overflow: auto;
+  max-height: 450px;
+  word-wrap: normal;
+  background: #2d2d2d;
+  color: #e0e0e0;
+  border-radius: 4px;
+}
+
+/*********************************************
+ * TABLES
+ *********************************************/
+.reveal table {
+  margin: auto;
+  border-collapse: collapse;
+  border-spacing: 0;
+}
+
+.reveal table th {
+  font-weight: bold;
+  color: #ffffff;
+}
+
+.reveal table th, .reveal table td {
+  text-align: left;
+  padding: 0.3em 0.6em;
+  border-bottom: 1px solid #555;
+  color: #e0e0e0;
+}
+
+.reveal table th[align="center"], .reveal table td[align="center"] {
+  text-align: center;
+}
+
+.reveal table th[align="right"], .reveal table td[align="right"] {
+  text-align: right;
+}
+
+.reveal table tr:last-child td {
+  border-bottom: none;
+}
+
+.reveal sup {
+  vertical-align: super;
+}
+
+.reveal sub {
+  vertical-align: sub;
+}
+
+.reveal small {
+  display: inline-block;
+  font-size: 0.6em;
+  line-height: 1.2em;
+  vertical-align: top;
+}
+
+.reveal small * {
+  vertical-align: top;
+}
+
+/*********************************************
+ * LINKS
+ *********************************************/
+.reveal a {
+  color: #42affa;
+  text-decoration: none;
+  -webkit-transition: color 0.15s ease;
+  -moz-transition: color 0.15s ease;
+  transition: color 0.15s ease;
+}
+
+.reveal a:hover {
+  color: #8dcffc;
+  text-shadow: none;
+  border: none;
+}
+
+.reveal .roll span:after {
+  color: #fff;
+  background: #068ee9;
+}
+
+/*********************************************
+ * IMAGES
+ *********************************************/
+.reveal section img {
+  margin: 15px 0;
+}
+
+.reveal a img {
+  -webkit-transition: all 0.15s linear;
+  -moz-transition: all 0.15s linear;
+  transition: all 0.15s linear;
+}
+
+.reveal a:hover img {
+  background: rgba(255, 255, 255, 0.2);
+  border-color: #42affa;
+  box-shadow: 0 0 20px rgba(0, 0, 0, 0.55);
+}
+
+/*********************************************
+ * NAVIGATION CONTROLS
+ *********************************************/
+.reveal .controls div.navigate-left, .reveal .controls div.navigate-left.enabled {
+  border-right-color: #42affa;
+}
+
+.reveal .controls div.navigate-right, .reveal .controls div.navigate-right.enabled {
+  border-left-color: #42affa;
+}
+
+.reveal .controls div.navigate-up, .reveal .controls div.navigate-up.enabled {
+  border-bottom-color: #42affa;
+}
+
+.reveal .controls div.navigate-down, .reveal .controls div.navigate-down.enabled {
+  border-top-color: #42affa;
+}
+
+.reveal .controls div.navigate-left.enabled:hover {
+  border-right-color: #8dcffc;
+}
+
+.reveal .controls div.navigate-right.enabled:hover {
+  border-left-color: #8dcffc;
+}
+
+.reveal .controls div.navigate-up.enabled:hover {
+  border-bottom-color: #8dcffc;
+}
+
+.reveal .controls div.navigate-down.enabled:hover {
+  border-top-color: #8dcffc;
+}
+
+/*********************************************
+ * PROGRESS BAR
+ *********************************************/
+.reveal .progress {
+  background: rgba(255, 255, 255, 0.2);
+}
+
+.reveal .progress span {
+  background: #42affa;
+  -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
+  -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
+  transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
+}
+
+/*********************************************
+ * SLIDE NUMBER
+ *********************************************/
+.reveal .slide-number {
+  color: #888;
+  background-color: rgba(0, 0, 0, 0);
+}
+
+/*********************************************
+ * GENERAL PURPOSE COLORS
+ *********************************************/
+.reveal .red {
+  color: #ff4444;
+}
+
+.reveal .orange {
+  color: #ffaa44;
+}
+
+.reveal .yellow {
+  color: #ffff44;
+}
+
+.reveal .green {
+  color: #44ff44;
+}
+
+/*********************************************
+ * HIDE THE PERSISTENT HEADER/FOOTER from
+ * document.html.slim template
+ *********************************************/
+.header,
+.footer {
+  display: none !important;
+}
+
+/*********************************************
+ * PROJECT LOGO — small, top left of every slide
+ * Each module should place a project-logo.png
+ * in src/main/asciidoc/images/ OR override
+ * this rule in a local customcss with the
+ * project's logo URL.
+ *********************************************/
+.reveal::before {
+  content: "";
+  position: fixed;
+  top: 16px;
+  left: 16px;
+  width: 120px;
+  height: 36px;
+  background-image: url("../../../images/project-logo.png");
+  background-size: contain;
+  background-repeat: no-repeat;
+  opacity: 0.7;
+  z-index: 100;
+  pointer-events: none;
+}
+
+/*********************************************
+ * APACHE OAK LEAF — bottom right of every slide
+ *********************************************/
+.reveal::after {
+  content: "";
+  position: fixed;
+  bottom: 16px;
+  left: 16px;
+  width: 36px;
+  height: 36px;
+  background-image: url("../../../images/logo-apache.png");
+  background-size: contain;
+  background-repeat: no-repeat;
+  opacity: 0.6;
+  z-index: 100;
+  pointer-events: none;
+}
+
+/*********************************************
+ * C3JS Charts (dark mode)
+ *********************************************/
+.c3 {
+  fill: white;
+}
+
+.c3 line, .c3 path {
+  stroke: white !important;
+}
+
+/*********************************************
+ * Column layout
+ *********************************************/
+.reveal .west {
+  position: fixed;
+  left: 5%;
+}
+
+.reveal .east {
+  position: fixed;
+  right: 5%;
+}