diff --git a/documentation/build.gradle b/documentation/build.gradle index b87c03847..94e42c62c 100644 --- a/documentation/build.gradle +++ b/documentation/build.gradle @@ -105,14 +105,23 @@ task renderReferenceDocumentation(type: AsciidoctorTask, group: 'Documentation') include 'index.adoc' } - outputDir = new File("$buildDir/asciidoc/reference/html_single") + resources { + from(sourceDir) { + include 'images/**' + include 'css/**' + } + } + + outputDir = new File("$buildDir/asciidoc/reference/html_single") options logDocuments: true - attributes icons: 'font', experimental: true, - 'source-highlighter': 'prettify', + attributes icons: 'font', + 'source-highlighter': 'rouge', + experimental: true, linkcss: true, majorMinorVersion: project.version.family, fullVersion: project.version.toString(), docinfo: 'private' + } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/documentation/src/main/asciidoc/reference/css/hibernate.css b/documentation/src/main/asciidoc/reference/css/hibernate.css new file mode 100644 index 000000000..bffef8d93 --- /dev/null +++ b/documentation/src/main/asciidoc/reference/css/hibernate.css @@ -0,0 +1,227 @@ +/* Asciidoctor default stylesheets */ +@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; +@import "https://cdn.jsdelivr.net/gh/asciidoctor/asciidoctor@2.0/data/stylesheets/asciidoctor-default.css"; + +body:before { + content: url(../images/hibernate_logo_smaller.png); + box-shadow: 0 2px 2px #ddd; + display: block; + padding: 20px 20px 10px 15px; +} + +/* + * I'm using the '!important' because the plugin includes the hibernate.css file before the rouge one, + * I cannot override the default any other way. + * Everything else is the same as the default rouge CSS. + */ +pre.rouge .cm { + color: #999988; + font-style: italic; +} +pre.rouge .cp { + color: #999999; + font-weight: normal !important; +} +pre.rouge .c1 { + color: #999988; + font-style: italic; +} +pre.rouge .cs { + color: #999999; + font-weight: normal !important; + font-style: italic; +} +pre.rouge .c, pre.rouge .ch, pre.rouge .cd, pre.rouge .cpf { + color: #999988; + font-style: italic; +} +pre.rouge .err { + color: #a61717; + background-color: #e3d2d2; +} +pre.rouge .gd { + color: #000000; + background-color: #ffdddd; +} +pre.rouge .ge { + color: #000000; + font-style: italic; +} +pre.rouge .gr { + color: #aa0000; +} +pre.rouge .gh { + color: #999999; +} +pre.rouge .gi { + color: #000000; + background-color: #ddffdd; +} +pre.rouge .go { + color: #888888; +} +pre.rouge .gp { + color: #555555; +} +pre.rouge .gs { + font-weight: normal !important; +} +pre.rouge .gu { + color: #aaaaaa; +} +pre.rouge .gt { + color: #aa0000; +} +pre.rouge .kc { + color: #008 !important; + font-weight: normal !important; +} +pre.rouge .kd { + color: #008 !important; + font-weight: normal !important; +} +pre.rouge .kn { + color: #000000; + font-weight: normal !important; +} +pre.rouge .kp { + color: #000000; + font-weight: normal !important; +} +pre.rouge .kr { + color: #000000; + font-weight: normal !important; +} +pre.rouge .kt { + color: #445588; + font-weight: normal !important; +} +pre.rouge .k, pre.rouge .kv { + color: #606 !important; + font-weight: normal !important; +} +pre.rouge .mf { + color: #009999; +} +pre.rouge .mh { + color: #009999; +} +pre.rouge .il { + color: #009999; +} +pre.rouge .mi { + color: #009999; +} +pre.rouge .mo { + color: #009999; +} +pre.rouge .m, pre.rouge .mb, pre.rouge .mx { + color: #009999; +} +pre.rouge .sa { + color: #000000; + font-weight: normal !important; +} +pre.rouge .sb { + color: #d14; +} +pre.rouge .sc { + color: #d14; +} +pre.rouge .sd { + color: #d14; +} +pre.rouge .s2 { + color: #d14; +} +pre.rouge .se { + color: #d14; +} +pre.rouge .sh { + color: #d14; +} +pre.rouge .si { + color: #d14; +} +pre.rouge .sx { + color: #d14; +} +pre.rouge .sr { + color: #009926; +} +pre.rouge .s1 { + color: #d14; +} +pre.rouge .ss { + color: #990073; +} +pre.rouge .s, pre.rouge .dl { + color: #080 !important; +} +pre.rouge .na { + color: #000 !important; +} +pre.rouge .bp { + color: #999999; +} +pre.rouge .nb { + color: #0086B3; +} +pre.rouge .nc { + color: #606 !important; + font-weight: normal !important; +} +pre.rouge .no { + color: #008080; +} +pre.rouge .nd { + color: #066 !important; + font-weight: normal !important; +} +pre.rouge .ni { + color: #800080; +} +pre.rouge .ne { + color: #990000; + font-weight: normal !important; +} +pre.rouge .nf, pre.rouge .fm { + color: #990000; + font-weight: normal !important; +} +pre.rouge .nl { + color: #990000; + font-weight: normal !important; +} +pre.rouge .nn { + color: #555555; +} +pre.rouge .nt { + color: #000080; +} +pre.rouge .vc { + color: #008080; +} +pre.rouge .vg { + color: #008080; +} +pre.rouge .vi { + color: #008080; +} +pre.rouge .nv, pre.rouge .vm { + color: #008080; +} +pre.rouge .ow { + color: #000000; + font-weight: normal !important; +} +pre.rouge .o { + color: #000000; + font-weight: normal !important; +} +pre.rouge .w { + color: #bbbbbb; +} +pre.rouge { + background-color: #f8f8f8; +} \ No newline at end of file diff --git a/documentation/src/main/asciidoc/reference/images/hibernate_logo_smaller.png b/documentation/src/main/asciidoc/reference/images/hibernate_logo_smaller.png new file mode 100644 index 000000000..a5a5b1953 Binary files /dev/null and b/documentation/src/main/asciidoc/reference/images/hibernate_logo_smaller.png differ diff --git a/documentation/src/main/asciidoc/reference/index.adoc b/documentation/src/main/asciidoc/reference/index.adoc index 4e8ac923b..3acdb5b73 100644 --- a/documentation/src/main/asciidoc/reference/index.adoc +++ b/documentation/src/main/asciidoc/reference/index.adoc @@ -1,11 +1,10 @@ = Hibernate Reactive {fullVersion} Reference Documentation Davide D'Alto ; Gavin King +:stylesheet: css/hibernate.css :toc2: :toclevels: 3 :sectanchors: -:source-highlighter: pygments :sourcedir: src/main/asciidoc/reference - :leveloffset: +1 include::{sourcedir}/preface.adoc[] diff --git a/documentation/src/main/asciidoc/reference/introduction.adoc b/documentation/src/main/asciidoc/reference/introduction.adoc index ef9a23143..4715324e4 100644 --- a/documentation/src/main/asciidoc/reference/introduction.adoc +++ b/documentation/src/main/asciidoc/reference/introduction.adoc @@ -678,7 +678,7 @@ Whatever you decide, the first step to getting a reactive session is to obtain a JPA `EntityManagerFactory` just as you usually would in plain ol' regular JPA, for example, by calling: -[source, JAVA, indent=0] +[source,java] ---- EntityManagerFactory emf = Persistence.createEntityManagerFactory("example"); ---- @@ -687,7 +687,7 @@ Now, `unwrap()` the reactive `SessionFactory`. If you want to use ``CompletionStage``s for chaining reactive operations, ask for a `Stage.SessionFactory`: -[source, JAVA, indent=0] +[source,java] ---- Stage.SessionFactory sessionFactory = emf.unwrap(Stage.SessionFactory.class); ---- @@ -695,7 +695,7 @@ Stage.SessionFactory sessionFactory = emf.unwrap(Stage.SessionFactory.class); Or, if you prefer to use the Mutiny-based API, `unwrap()` the type `Mutiny.SessionFactory`: -[source, JAVA, indent=0] +[source,java] ---- Mutiny.SessionFactory sessionFactory = emf.unwrap(Mutiny.SessionFactory.class); ---- @@ -724,7 +724,7 @@ concurrent reactive streams! To obtain a reactive `Session` from the `SessionFactory`, use `withSession()`: -[source, JAVA, indent=0] +[source,java] ---- sessionFactory.withSession( session -> session.find(Book.class, id) @@ -743,7 +743,7 @@ the session when you're done. And you must take great care to only access each session from within exactly one Vert.x context. (See <<_sessions_and_vert_x_contexts>> more on this). -[source, JAVA, indent=0] +[source,java] ---- Uni sessionUni = sessionFactory.openSession(); sessionUni.chain( @@ -801,7 +801,7 @@ Now, _here's where Hibernate Reactive is different:_ in the reactive API, each of these methods returns its result in a non-blocking fashion via a Java `CompletionStage` (or Mutiny `Uni`). For example: -[source, JAVA, indent=0] +[source,java] ---- session.find(Book.class, book.id) .invoke( book -> System.out.println(book.title + " is a great book!") ) @@ -810,7 +810,7 @@ session.find(Book.class, book.id) On the other hand, methods with no meaningful return value just return `CompletionStage` (or `Uni`). -[source, JAVA, indent=0] +[source,java] ---- session.find(Book.class, id) .call( book -> session.remove(book) ) @@ -828,7 +828,7 @@ chain the return value of a "void-like" method. For example, in the following code, the `flush()` operation is never executed, because `invoke()` doesn't chain its return value to the tip of the stream. -[source, JAVA, indent=0] +[source,java] ---- session.find(Book.class, id) .call( book -> session.remove(book) ) @@ -845,7 +845,7 @@ So remember: The same problem occurs in the following code, but this time it's `remove()` that never gets called: -[source, JAVA, indent=0] +[source,java] ---- session.find(Book.class, id) .call( book -> { @@ -879,7 +879,7 @@ That `createQuery()` method produces a reactive `Query`, allowing HQL / JPQL queries to be executed asynchronously, always returning their results via a `CompletionStage` (or `Uni`): -[source, JAVA, indent=0] +[source,java] ---- session.createQuery("select title from Book order by title desc") .getResultList() @@ -910,7 +910,7 @@ For JPA criteria queries, you must first obtain the `CriteriaBuilder` using `SessionFactory.getCriteriaBuilder()`, and execute your query using `Session.createQuery()`. -[source, JAVA, indent=0] +[source,java] ---- CriteriaQuery query = factory.getCriteriaBuilder().createQuery(Book.class); Root a = query.from(Author.class); @@ -932,7 +932,7 @@ produces a result via a `CompletionStage` (or `Uni`). Therefore, lazy fetching is an explicit operation named `fetch()`, a static method of `Stage` and `Mutiny`: -[source, JAVA, indent=0] +[source,java] ---- session.find(Author.class, author.id) .chain( author -> Mutiny.fetch(author.books) ) @@ -949,7 +949,7 @@ patterns like "open session in view" will _not help at all_. Sometimes you might need to chain multiple calls to `fetch()`, for example: -[source, JAVA, indent=0] +[source,java] ---- Mutiny.fetch( session.getReference(detachedAuthor) ) .chain( author -> Mutiny.fetch(author.books) ) @@ -968,7 +968,7 @@ bytecode enhancer—is also an explicit operation. To declare a lazy field we usually use the JPA `@Basic` annotation: -[source, JAVA, indent=0] +[source,java] ---- @Basic(fetch=LAZY) String isbn; ---- @@ -987,7 +987,7 @@ there. A lazy field is only fetched if we explicitly request it by calling an overloaded version of the `fetch()` operation: -[source, JAVA, indent=0] +[source,java] ---- session.find(Book.class, book.id) .chain( book -> session.fetch(book, Book_.isbn) ) @@ -1006,7 +1006,7 @@ as vulnerable to N+1 selects as lazy association fetching. The `withTransaction()` method performs work within the scope of a database transaction. -[source, JAVA, indent=0] +[source,java] ---- session.withTransaction( tx -> session.persist(book) ) ---- @@ -1025,7 +1025,7 @@ transactions. For extra convenience, there's a method that opens a session and starts a transaction in one call: -[source, JAVA, indent=0] +[source,java] ---- sessionFactory.withTransaction( (session, tx) -> session.persist(book) ) ---- @@ -1083,7 +1083,7 @@ puff of pixie dust. That's not how these things work. For example, I bet you would like to be able to write code like this: -[source, JAVA, indent=0] +[source,java] ---- List list = ... for (Entity entity : entities) { @@ -1103,7 +1103,7 @@ Vert.x `Context` object using {vertx-get-context}[`getOrCreateContext()`] and then call {vertx-runon-context}[`runOnContext()`] to execute the code in that context. -[source, JAVA, indent=0] +[source,java] ---- Context currentContext = Vertx.currentContext(); currentContext.runOnContext( event -> { @@ -1122,7 +1122,7 @@ needed. But if your program requires control over how the Vert.x instance is created, or how it's obtained, you can override the default implementation and provide your own `VertxInstance`. Let's consider this example: -[source, JAVA, indent=0] +[source,java] ---- public class MyVertx implements VertxInstance { @@ -1143,7 +1143,7 @@ public class MyVertx implements VertxInstance { One way to register this implementation is to configure Hibernate programmatically, for example: -[source, JAVA, indent=0] +[source,java] ---- Configuration configuration = new Configuration(); StandardServiceRegistryBuilder builder = new ReactiveServiceRegistryBuilder() @@ -1155,7 +1155,7 @@ SessionFactory sessionFactory = configuration.buildSessionFactory( registry ); Alternatively, you could implement the `ServiceContributor` interface. -[source, JAVA, indent=0] +[source,java] ---- public class MyServiceContributor implements ServiceContributor { @Override @@ -1168,7 +1168,7 @@ public class MyServiceContributor implements ServiceContributor { To register this `ServiceContributor`, add a text file named `org.hibernate.service.spi.ServiceContributor` to `/META-INF/services/`. -[source, JAVA, indent=0] +[source,java] ---- org.myproject.MyServiceContributor ---- @@ -1177,7 +1177,7 @@ org.myproject.MyServiceContributor //or `Mutiny.SessionFactory` using the `org.hibernate.reactive.common.spi.Implementor` //interface: // -//[source, JAVA, indent=0] +//[source,java] //---- //Mutiny.SessionFactory sessionFactory = ... //VertxInstance vertxInstance = ((Implementor) sessionFactory) @@ -1391,7 +1391,7 @@ interacting with the database. You may obtain a reactive stateless session from the `SessionFactory`: -[source, JAVA, indent=0] +[source,java] ---- Stage.StatelessSession ss = getSessionFactory().openStatelessSession(); ----