Replaced HAL Browser documentation with HAL Explorer documentation.

Removed unnecessary CustomPostForm.js from HAL Explorer. HAL Explorer natively supports Spring Profiles. Update link in README.adoc to the HAL Explorer section in the reference docs Correct typo and incorrect description in HAL-Explorer section.

Fixes #2005.
This commit is contained in:
Kai Toedter
2021-04-26 20:20:27 +02:00
committed by Oliver Drotbohm
parent 44213af672
commit 30bb6de79f
9 changed files with 16 additions and 218 deletions

View File

@@ -17,7 +17,7 @@ The first exporter implemented is a JPA Repository exporter. This takes your JPA
* Allows to https://docs.spring.io/spring-data/rest/docs/current/reference/html/#events[hook into the handling of REST requests] by handling Spring `ApplicationEvents`.
* https://docs.spring.io/spring-data/rest/docs/current/reference/html/#metadata[Exposes metadata] about the model discovered as ALPS and JSON Schema.
* Allows to define client specific representations through https://docs.spring.io/spring-data/rest/docs/current/reference/html/#projections-excerpts[projections].
* Ships a customized variant of the https://docs.spring.io/spring-data/rest/docs/current/reference/html/#_the_hal_browser[HAL Browser] to leverage the exposed metadata.
* Ships the latest release of https://docs.spring.io/spring-data/rest/docs/current/reference/html/#hal-explorer[HAL Explorer] to easily explore HAL based HTTP responses.
* Currently supports JPA, MongoDB, Neo4j, Solr, Cassandra, Gemfire.
* Allows https://docs.spring.io/spring-data/rest/docs/current/reference/html/#customizing-sdr[advanced customizations] of the default resources exposed.

View File

@@ -1,203 +0,0 @@
/**
* Custom Backbone view that uses JSON Schema metadata to create pop-up dialog with actual field names instead of
* asking user to input raw JSON.
*
* NOTE: Because JSON Schema lists all properties, including those that are links, they have to be filtered out.
* Links have to be set via a PUT operation with the proper media type.
*
* @author Greg Turnquist
* @author Gregory Frank
* @since 2.4
* @see DATAREST-627, DATAREST-1077
*/
/* jshint strict: true */
/* globals HAL, Backbone, _, $, window, jqxhr */
'use strict';
var CustomPostForm = Backbone.View.extend({
initialize: function (opts) {
this.href = opts.href.split('{')[0];
this.vent = opts.vent;
_.bindAll(this, 'createNewResource');
},
events: {
'submit form': 'createNewResource'
},
className: 'modal fade',
/**
* Perform a POST/PUT operation on the resource.
*
* @param e
*/
createNewResource: function (e) {
e.preventDefault();
var self = this;
var opts = {
url: this.$('.url').val(),
headers: _.defaults({'Content-Type': 'application/json'}, HAL.client.getHeaders()),
method: this.$('.method').val(),
data: this.getNewResourceData()
};
HAL.client.request(opts).done(function (response) {
self.vent.trigger('response', {resource: response, jqxhr: jqxhr});
}).fail(function (e) {
self.vent.trigger('fail-response', {jqxhr: jqxhr});
}).always(function (e) {
self.vent.trigger('response-headers', {jqxhr: jqxhr});
window.location.hash = 'NON-GET:' + opts.url;
});
this.$el.modal('hide');
},
/**
* Draw the dialog after fetching the resource's JSON Schema metadata. If no metadata is available, use the
* fallback editor.
*
* @param opts
* @returns {CustomPostForm}
*/
render: function (opts) {
var self = this;
try {
HAL.client.request({
method: 'HEAD',
headers: HAL.client.getHeaders(),
url: this.href
}).done(function (message, text, jqXHR) {
self.$el.html(self.template({href: self.href}));
try {
var hal = self.w3cLinksToHalLinks(jqXHR.getResponseHeader('Link'));
HAL.client.request({
method: 'GET',
url: hal._links.profile.href,
headers: _.defaults({'Accept': 'application/schema+json'}, HAL.client.getHeaders())
}).done(function (schema) {
self.loadJsonEditor(schema);
});
} catch (e) {
self.loadFallbackEditor();
}
self.$el.modal();
});
} catch (e) {
self.loadFallbackEditor();
self.$el.modal();
}
return this;
},
/**
* Load the JSON Schema-driven editor.
*
* @see https://github.com/jdorn/json-editor
*/
loadJsonEditor: function (schema) {
var self = this;
/**
* Remove URI-based fields since this dialog doesn't handle relationships.
*/
Object.keys(schema.properties).forEach(function (property) {
if (schema.properties[property].hasOwnProperty('format') &&
schema.properties[property].format === 'uri') {
delete schema.properties[property];
}
});
/**
* See https://github.com/jdorn/json-editor#options for more customizing options.
*/
this.editor = new window.JSONEditor(this.$('#jsoneditor')[0], {
theme: 'bootstrap2',
schema: schema,
disable_collapse: true,
disable_edit_json: true,
disable_properties: true
});
this.getNewResourceData = function() {
return JSON.stringify(self.editor.getValue());
}
},
/**
* Load fallback editor that doesn't depend on any form of metadata.
*/
loadFallbackEditor: function () {
var editor = this.$('#jsoneditor');
editor.append($('<h4>' + this.href + '</h4>'));
var inputBox = $('<textarea name="body" class="body" style="height: 200px">{\n}</textarea>');
editor.append(inputBox);
this.getNewResourceData = function() {
return inputBox.val();
}
},
/**
* Convert a W3C link header into a HAL-based set of _links.
*
* e.g.
* <http://localhost:8080/persons>; rel="persons",<http://localhost:8080/profile/persons>; rel="profile"
* to
* {
* _links: {
* persons: {
* href: http://localhost:8080/persons
* },
* profile: {
* href: http://localhost:8080/profile/persons
* }
* }
* }
*
* @param linkHeader - HTTP Response header containing a list of W3C compliant links with rels.
* @see https://www.w3.org/wiki/LinkHeader
*/
w3cLinksToHalLinks: function (linkHeader) {
var w3cLinks = linkHeader.split(',');
var halLinks = {_links: {}};
w3cLinks.forEach(function (w3cLink) {
var parts = w3cLink.split(';');
var hrefWrappedWithBrackets = parts[0];
var href = hrefWrappedWithBrackets.slice(1, parts[0].length - 1);
var w3cRel = parts[1];
var relWrappedWithQuotes = w3cRel.split('=')[1];
var rel = relWrappedWithQuotes.slice(1, relWrappedWithQuotes.length - 1);
halLinks._links[rel] = { "href": href };
});
return halLinks;
},
/**
* Look up the HTML template.
*/
template: _.template($('#dynamic-request-template').html())
});
/**
* Inject the form into the HAL Browser.
*/
HAL.customPostForm = CustomPostForm;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 356 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@@ -2,9 +2,10 @@
= Tools
:spring-data-rest-root: ../../../..
== The HAL Browser
[[hal-explorer]]
== HAL Explorer
The developer of the http://stateless.co/hal_specification.html[HAL specification] has a useful application: https://github.com/mikekelly/hal-browser[the HAL Browser]. It is a web application that stirs in a little HAL-powered JavaScript. You can point it at any Spring Data REST API and use it to navigate the app and create new resources.
Kai Tödter has created a useful application: https://github.com/toedter/hal-explorer[HAL Explorer]. It is an Angular based web application that lets you easily explore HAL and HAL-FORMS based HTTP responses. It also supports Spring profiles generated by Spring Data REST. You can point it at any Spring Data REST API and use it to navigate the app and create new resources.
Instead of pulling down the files, embedding them in your application, and crafting a Spring MVC controller to serve them up, all you need to do is add a single dependency.
@@ -16,7 +17,7 @@ The following listing shows how to add the dependency in Maven:
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-hal-browser</artifactId>
<artifactId>spring-data-rest-hal-explorer</artifactId>
</dependency>
</dependencies>
----
@@ -28,29 +29,29 @@ The following listing shows how to add the dependency in Gradle:
[source,groovy]
----
dependencies {
compile 'org.springframework.data:spring-data-rest-hal-browser'
implementation 'org.springframework.data:spring-data-rest-hal-explorer'
}
----
====
NOTE: If you use Spring Boot or the Spring Data BOM (bill of materials), you do not need to specify the version.
This dependency auto-configures the HAL Browser to be served up when you visit your application's root URI in a browser. (NOTE: http://localhost:8080 was plugged into the browser, and it redirected to the URL shown in the following image.)
This dependency auto-configures the HAL Explorer to be served up when you visit your application's root URI in a browser. (NOTE: http://localhost:8080/api was plugged into the browser, and it redirected to the URL shown in the following image.)
image::hal-browser-1.png[]
image::hal-explorer-1.png[]
The preceding screen shot shows the root path of the API. On the right side are details from the response, including headers and the body (a HAL document).
The preceding screenshot shows the root path of the API. On the right side are details from the response, including headers, and the body (a HAL document).
The HAL Browser reads the links from the response and puts them in a list on the left side. You can either click on the *GET* button and navigate to one of the collections, or click on the *NON-GET* option to make changes.
The HAL Explorer reads the links from the response and puts them in a list on the left side. You can either click on the green *GET* button and navigate to one of the collections, or click on the other buttons to make changes (POST, PUT, PATCH) or delete resources.
The HAL Browser speaks *URI Template*. Above the *GET* button and next to *persons*, the UI has a question mark icon. An expansion dialog pops up if you choose to navigate to it, as follows:
The HAL Explorer understands *URI Templates*. Whenever a link contains a URI template, a modal dialog pops up where you can enter the template parameters.
image::hal-browser-3.png[]
image::hal-explorer-3.png[]
If you click *Follow URI* without entering anything, the variables are essentially ignored. For situations like <<projections-excerpts>> or <<paging-and-sorting>>, this can be useful.
If you click *Go!* without entering anything, the variables are essentially ignored. For situations like <<projections-excerpts>> or <<paging-and-sorting>>, this can be useful.
When you click on a *NON-GET* button, a pop-up dialog appears. By default, it shows *POST*. This field can be adjusted to either *PUT* or *PATCH*. The headers are filled out to properly to submit a new JSON document.
When you click on a *NON-GET* button with a `+` or a `>` sign on it, a modal dialog appears. It shows the HTTP method belonging to the clicked button. You can fill the body and submit the new JSON document.
Below the URI, method, and headers are the fields. These are automatically supplied, depending on the metadata of the resources, which was automatically generated by Spring Data REST. If you update your domain objects, the pop-up reflects it, as the following image shows:
Below the URI and HTTP method are the fields. These are automatically supplied, depending on the metadata of the resources, which was automatically generated by Spring Data REST. If you update your domain objects, the pop-up reflects it, as the following image shows:
image::hal-browser-2.png[height="150"]
image::hal-explorer-2.png[]