Skip to content

Commit

Permalink
WIP - draft of DevUI pages for Hibernate ORM
Browse files Browse the repository at this point in the history
* provide information about persistence units and their managed entities
* allow user to generate create-schema script
  • Loading branch information
TomasHofman committed Apr 29, 2021
1 parent 3b461a2 commit ed51b55
Show file tree
Hide file tree
Showing 15 changed files with 498 additions and 3 deletions.
4 changes: 4 additions & 0 deletions extensions/hibernate-orm/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-panache-hibernate-common-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-vertx-http-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-internal</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package io.quarkus.hibernate.orm.deployment.devconsole;

import static io.quarkus.deployment.annotations.ExecutionTime.RUNTIME_INIT;

import io.quarkus.arc.deployment.SyntheticBeansRuntimeInitBuildItem;
import io.quarkus.deployment.IsDevelopment;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.Consume;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.devconsole.spi.DevConsoleRuntimeTemplateInfoBuildItem;
import io.quarkus.hibernate.orm.runtime.HibernateOrmDevConsoleRecorder;
import io.quarkus.hibernate.orm.runtime.PersistenceUnitInfoSupplier;
import io.quarkus.vertx.http.deployment.NonApplicationRootPathBuildItem;
import io.quarkus.vertx.http.deployment.RouteBuildItem;

public class DevConsoleProcessor {

/**
* Collect a list of available persistence units for the DevUI templates.
*/
/*
* @BuildStep(onlyIf = IsDevelopment.class)
* public DevConsoleTemplateInfoBuildItem collectDeploymentUnits(List<PersistenceUnitDescriptorBuildItem> persistenceUnits)
* {
* return new DevConsoleTemplateInfoBuildItem("persistenceUnits", persistenceUnits);
* }
*/

@BuildStep(onlyIf = IsDevelopment.class)
public DevConsoleRuntimeTemplateInfoBuildItem collectDeploymentUnits() {
return new DevConsoleRuntimeTemplateInfoBuildItem("persistence", new PersistenceUnitInfoSupplier());
}

/**
* Register an endpoint that generates create-schema script for given PU.
*/
@BuildStep(onlyIf = IsDevelopment.class)
@Record(RUNTIME_INIT)
@Consume(SyntheticBeansRuntimeInitBuildItem.class)
public RouteBuildItem schemaGenerationRoute(NonApplicationRootPathBuildItem nonApplicationRootPathBuildItem,
HibernateOrmDevConsoleRecorder hibernateOrmRecorder) {
return nonApplicationRootPathBuildItem.routeBuilder()
.route("pu-schema/:name")
.handler(hibernateOrmRecorder.schemaGenerationHandler())
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<a href="{urlbase}/persistence-units" class="badge badge-light">
<i class="fa fa-boxes fa-fw"></i>
Persistence units <span class="badge badge-light">{info:persistence.persistenceUnits.size}</span></a>

<a href="{urlbase}/managed-entities" class="badge badge-light">
<i class="fa fa-table fa-fw"></i>
Entities <span class="badge badge-light">{info:persistence.managedEntities.size}</span></a>

<a href="{urlbase}/named-queries" class="badge badge-light">
<i class="fa fa-question-circle fa-fw"></i>
Named Queries <span class="badge badge-light">{info:persistence.allNamedQueries.size}</span></a>

{!
{#for unit in info:persistenceUnits}
<a href="/q/pu-schema/{unit.persistenceUnitName}" class="badge badge-light">
{unit.persistenceUnitName}</a>
{/for}
!}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{#include main}
{#style}
.annotation {
color: gray;
}
{/style}
{#title}Managed Entities{/title}
{#body}

{#if info:persistence.managedEntities.isEmpty}
<p>No entities were found.</p>
{#else}
<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th scope="col">#</th>
<th scope="col">Class name</th>
<th scope="col">Table name</th>
<th scope="col">Persistence Unit</th>
</tr>
</thead>
<tbody>
{#for entity in info:persistence.managedEntities}
<tr>
<td>{count}</td>
<td>{entity.className}</td>
<td>{entity.tableName}</td>
<td>{entity.persistenceUnitName}</td>
</tr>
{/for}
</tbody>
</table>
{/if}

{/body}
{/include}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{#include main}
{#style}
.annotation {
color: gray;
}
{/style}
{#title}Named Queries{/title}
{#body}

{#if info:persistence.allNamedQueries.isEmpty}
<p>No named queries were found.</p>
{#else}
<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Query</th>
<th scope="col">Lock Mode</th>
<th scope="col">Cacheable</th>
<th scope="col">Query Type</th>
</tr>
</thead>
<tbody>
{#for query in info:persistence.allNamedQueries}
<tr>
<td>{count}</td>
<td>{query.name}</td>
<td>{query.query}</td>
<td>{query.lockMode}</td>
<td>{query.cacheable}</td>
<td>{query.type}</td>
</tr>
{/for}
</tbody>
</table>
{/if}

{/body}
{/include}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{#include main}
{#style}
.ddl-script {
background-color: white;
padding: 5px;
}
{/style}
{#title}Persistence Units{/title}
{#body}

{#if info:persistence.persistenceUnits.isEmpty}
<p>No persistence units found.</p>
{#else}
<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th scope="col">#</th>
<th scope="col">Persistence Unit Name</th>
<th scope="col">DDL</th>
</tr>
</thead>
<tbody>
{#for unit in info:persistence.persistenceUnits}
<tr>
<td>{count}</td>
<td>{unit.name}</td>
<td>
<p>
<b>Create script:</b>
<a href="#" onclick="copyToClipboard('create-script-{count}');">
<i class="fa fa-clipboard"></i><span class="badge">Copy</span></a>
</p>

<pre id="create-script-{count}" class="ddl-script"></pre>
<script>
<!--
window.onload = (event) => {
jQuery.get( "http://localhost:8080/q/pu-schema/%3Cdefault%3E", function( data ) {
$( "#create-script-{count}" ).html( data );
});
};
//-->


</script>
</td>
</tr>
{/for}
</tbody>
</table>
{/if}

<script>
<!--
function copyToClipboard(elementId) {
var element = document.getElementById(elementId);
var range = document.createRange();
range.setStartBefore(element.firstChild);
range.setEndAfter(element.lastChild);
var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
document.execCommand('copy');
}
//-->

</script>

{/body}
{/include}
4 changes: 4 additions & 0 deletions extensions/hibernate-orm/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-narayana-jta</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-vertx-http</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.quarkus.hibernate.orm.runtime;

import java.io.StringWriter;
import java.util.Collections;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -99,6 +100,28 @@ public boolean generateSchema(String persistenceUnitName, Map map) {
return true;
}

/**
* TODO: Figure out how to provide separate "create" and "drop" scripts. Currently this only do "create".
*
* A variant of {@link #generateSchema(String persistenceUnitName, Map map)} that returns the SQL script as a string.
*
* @param persistenceUnitName PU name
* @param map should be always null, as Quarkus doesn't allow to provide any properties in runtime.
* @return schema as string
*/
@SuppressWarnings("rawtypes")
public String generateSchemaToString(String persistenceUnitName, Map map) {
final FastBootEntityManagerFactoryBuilder builder = (FastBootEntityManagerFactoryBuilder) getEntityManagerFactoryBuilderOrNull(
persistenceUnitName, map);
if (builder == null) {
log.trace("Could not obtain matching EntityManagerFactoryBuilder, returning null");
return null;
}
StringWriter createWriter = new StringWriter();
builder.generateSchema(createWriter);
return createWriter.toString();
}

@Override
public ProviderUtil getProviderUtil() {
return providerUtil;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.quarkus.hibernate.orm.runtime;

import io.quarkus.runtime.annotations.Recorder;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;

@Recorder
public class HibernateOrmDevConsoleRecorder {

public Handler<RoutingContext> schemaGenerationHandler() {
return new PersistenceUnitSchemaGenerationHandler();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -118,5 +118,4 @@ protected Session delegate() {
}
};
}

}
Loading

0 comments on commit ed51b55

Please sign in to comment.