Set up reference documentation and JavaDoc
Closes gh-76
This commit is contained in:
@@ -6,6 +6,8 @@ ext {
|
||||
moduleProjects = subprojects.findAll { it.name.startsWith("spring-") }
|
||||
}
|
||||
|
||||
description = "Spring GraphQL"
|
||||
|
||||
subprojects {
|
||||
apply plugin: 'io.spring.dependency-management'
|
||||
|
||||
|
||||
@@ -90,6 +90,14 @@ jobs:
|
||||
build_number: "${BUILD_PIPELINE_NAME}-${BUILD_JOB_NAME}-${BUILD_NAME}"
|
||||
disable_checksum_uploads: true
|
||||
threads: 8
|
||||
artifact_set:
|
||||
- include:
|
||||
- "/**/spring-graphql-*-docs.zip"
|
||||
properties:
|
||||
"zip.name": "spring-graphql"
|
||||
"zip.displayname": "Spring GraphQL"
|
||||
"zip.deployed": "false"
|
||||
"zip.type": "docs"
|
||||
get_params:
|
||||
threads: 8
|
||||
- name: stage-milestone
|
||||
|
||||
152
docs/build.gradle
Normal file
152
docs/build.gradle
Normal file
@@ -0,0 +1,152 @@
|
||||
plugins {
|
||||
id 'org.asciidoctor.jvm.convert' version '3.1.0'
|
||||
id 'de.undercouch.download' version '4.1.1'
|
||||
}
|
||||
|
||||
description = "Spring GraphQL reference documentation"
|
||||
|
||||
configurations {
|
||||
asciidoctorExt
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url "https://repo.spring.io/release"
|
||||
mavenContent {
|
||||
includeGroup "io.spring.asciidoctor"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
asciidoctorExt 'io.spring.asciidoctor:spring-asciidoctor-extensions-block-switch:0.6.0'
|
||||
}
|
||||
|
||||
ext.javadocLinks = [
|
||||
"https://docs.oracle.com/javase/8/docs/api/",
|
||||
"https://javadoc.io/doc/com.graphql-java/graphql-java/16.2/",
|
||||
"https://docs.spring.io/spring-framework/docs/5.3.x/javadoc-api/"
|
||||
] as String[]
|
||||
|
||||
/**
|
||||
* Produce Javadoc for all Spring GraphQL modules in "build/docs/javadoc"
|
||||
*/
|
||||
task api(type: Javadoc) {
|
||||
group = "Documentation"
|
||||
description = "Generates aggregated Javadoc API documentation."
|
||||
title = "${rootProject.description} ${version} API"
|
||||
|
||||
dependsOn {
|
||||
moduleProjects.collect {
|
||||
it.tasks.getByName("jar")
|
||||
}
|
||||
}
|
||||
|
||||
options {
|
||||
encoding = "UTF-8"
|
||||
memberLevel = JavadocMemberLevel.PROTECTED
|
||||
author = true
|
||||
header = rootProject.description
|
||||
use = true
|
||||
overview = "src/docs/api/overview.html"
|
||||
stylesheetFile = file("src/docs/api/stylesheet.css")
|
||||
splitIndex = true
|
||||
links(project.ext.javadocLinks)
|
||||
addStringOption('Xdoclint:none', '-quiet')
|
||||
if(JavaVersion.current().isJava9Compatible()) {
|
||||
addBooleanOption('html5', true)
|
||||
}
|
||||
}
|
||||
source = moduleProjects.collect { project ->
|
||||
project.sourceSets.main.allJava
|
||||
}
|
||||
classpath = moduleProjects.collect { project ->
|
||||
project.sourceSets.main.compileClasspath
|
||||
}.sum()
|
||||
maxMemory = "1024m"
|
||||
destinationDir = file("$buildDir/docs/javadoc")
|
||||
}
|
||||
|
||||
task downloadResources(type: Download) {
|
||||
def version = "0.2.5"
|
||||
src "https://repo.spring.io/release/io/spring/docresources/" +
|
||||
"spring-doc-resources/$version/spring-doc-resources-${version}.zip"
|
||||
dest project.file("$buildDir/docs/spring-doc-resources.zip")
|
||||
onlyIfModified true
|
||||
useETag "all"
|
||||
}
|
||||
|
||||
task extractDocResources(type: Copy, dependsOn: downloadResources) {
|
||||
from project.zipTree(downloadResources.dest);
|
||||
into "$buildDir/docs/spring-docs-resources/"
|
||||
}
|
||||
|
||||
asciidoctorj {
|
||||
version = '2.4.3'
|
||||
fatalWarnings ".*"
|
||||
options doctype: 'book', eruby: 'erubis'
|
||||
attributes([
|
||||
icons: 'font',
|
||||
idprefix: '',
|
||||
idseparator: '-',
|
||||
docinfo: 'shared',
|
||||
revnumber: project.version,
|
||||
sectanchors: '',
|
||||
sectnums: '',
|
||||
'source-highlighter': 'highlight.js',
|
||||
highlightjsdir: 'js/highlight',
|
||||
'highlightjs-theme': 'googlecode',
|
||||
stylesdir: 'css/',
|
||||
stylesheet: 'stylesheet.css'
|
||||
])
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the Spring GraphQL Reference documentation from "src/docs/asciidoc"
|
||||
* in "build/docs/reference/html".
|
||||
*/
|
||||
asciidoctor {
|
||||
baseDirFollowsSourceDir()
|
||||
configurations 'asciidoctorExt'
|
||||
sources {
|
||||
include '*.adoc'
|
||||
}
|
||||
outputDir "$buildDir/docs/reference/html"
|
||||
logDocuments = true
|
||||
resources {
|
||||
from(sourceDir) {
|
||||
include 'images/*.png', 'css/**', 'js/**'
|
||||
}
|
||||
from extractDocResources
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Zip all docs into a single archive
|
||||
*/
|
||||
task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor']) {
|
||||
group = "Distribution"
|
||||
description = "Builds -${archiveClassifier} archive containing api and reference " +
|
||||
"for deployment at https://docs.spring.io/spring-graphql/docs."
|
||||
|
||||
archiveBaseName.set("spring-graphql")
|
||||
archiveClassifier.set("docs")
|
||||
from (api) {
|
||||
into "javadoc-api"
|
||||
}
|
||||
from ("$asciidoctor.outputDir") {
|
||||
into "reference/html"
|
||||
}
|
||||
}
|
||||
|
||||
apply from: "${rootDir}/gradle/publishing.gradle"
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
artifact docsZip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
7
docs/src/docs/api/overview.html
Normal file
7
docs/src/docs/api/overview.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<html lang="en">
|
||||
<body>
|
||||
<p>
|
||||
This is the public API documentation for the <a href="https://spring.io/projects/spring-graphql" target="_top">Spring GraphQL project</a>.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
596
docs/src/docs/api/stylesheet.css
Normal file
596
docs/src/docs/api/stylesheet.css
Normal file
@@ -0,0 +1,596 @@
|
||||
/* Javadoc style sheet */
|
||||
/*
|
||||
Overall document style
|
||||
*/
|
||||
body {
|
||||
background-color:#ffffff;
|
||||
color:#353833;
|
||||
font-family:'DejaVu Sans', Arial, Helvetica, sans-serif;
|
||||
font-size:14px;
|
||||
margin:0;
|
||||
}
|
||||
a:link, a:visited {
|
||||
text-decoration:none;
|
||||
color:#4A6782;
|
||||
}
|
||||
a:hover, a:focus {
|
||||
text-decoration:none;
|
||||
color:#bb7a2a;
|
||||
}
|
||||
a:active {
|
||||
text-decoration:none;
|
||||
color:#4A6782;
|
||||
}
|
||||
a[name] {
|
||||
color:#353833;
|
||||
}
|
||||
a[name]:hover {
|
||||
text-decoration:none;
|
||||
color:#353833;
|
||||
}
|
||||
pre {
|
||||
font-family:'DejaVu Sans Mono', monospace;
|
||||
font-size:14px;
|
||||
}
|
||||
h1 {
|
||||
font-size:20px;
|
||||
}
|
||||
h2 {
|
||||
font-size:18px;
|
||||
}
|
||||
h3 {
|
||||
font-size:16px;
|
||||
font-style:italic;
|
||||
}
|
||||
h4 {
|
||||
font-size:13px;
|
||||
}
|
||||
h5 {
|
||||
font-size:12px;
|
||||
}
|
||||
h6 {
|
||||
font-size:11px;
|
||||
}
|
||||
ul {
|
||||
list-style-type:disc;
|
||||
}
|
||||
code, tt {
|
||||
font-family:'DejaVu Sans Mono', monospace;
|
||||
font-size:14px;
|
||||
padding-top:4px;
|
||||
margin-top:8px;
|
||||
line-height:1.4em;
|
||||
}
|
||||
dt code {
|
||||
font-family:'DejaVu Sans Mono', monospace;
|
||||
font-size:14px;
|
||||
padding-top:4px;
|
||||
}
|
||||
table tr td dt code {
|
||||
font-family:'DejaVu Sans Mono', monospace;
|
||||
font-size:14px;
|
||||
vertical-align:top;
|
||||
padding-top:4px;
|
||||
}
|
||||
sup {
|
||||
font-size:8px;
|
||||
}
|
||||
/*
|
||||
Document title and Copyright styles
|
||||
*/
|
||||
.clear {
|
||||
clear:both;
|
||||
height:0px;
|
||||
overflow:hidden;
|
||||
}
|
||||
.aboutLanguage {
|
||||
float:right;
|
||||
padding:0px 21px;
|
||||
font-size:11px;
|
||||
z-index:200;
|
||||
margin-top:-9px;
|
||||
}
|
||||
.legalCopy {
|
||||
margin-left:.5em;
|
||||
}
|
||||
.bar a, .bar a:link, .bar a:visited, .bar a:active {
|
||||
color:#FFFFFF;
|
||||
text-decoration:none;
|
||||
}
|
||||
.bar a:hover, .bar a:focus {
|
||||
color:#bb7a2a;
|
||||
}
|
||||
.tab {
|
||||
background-color:#0066FF;
|
||||
color:#ffffff;
|
||||
padding:8px;
|
||||
width:5em;
|
||||
font-weight:bold;
|
||||
}
|
||||
/*
|
||||
Navigation bar styles
|
||||
*/
|
||||
.bar {
|
||||
background-color:#4D7A97;
|
||||
color:#FFFFFF;
|
||||
padding:.8em .5em .4em .8em;
|
||||
height:auto;/*height:1.8em;*/
|
||||
font-size:11px;
|
||||
margin:0;
|
||||
}
|
||||
.topNav {
|
||||
background-color:#4D7A97;
|
||||
color:#FFFFFF;
|
||||
float:left;
|
||||
padding:0;
|
||||
width:100%;
|
||||
clear:right;
|
||||
height:2.8em;
|
||||
padding-top:10px;
|
||||
overflow:hidden;
|
||||
font-size:12px;
|
||||
}
|
||||
.bottomNav {
|
||||
margin-top:10px;
|
||||
background-color:#4D7A97;
|
||||
color:#FFFFFF;
|
||||
float:left;
|
||||
padding:0;
|
||||
width:100%;
|
||||
clear:right;
|
||||
height:2.8em;
|
||||
padding-top:10px;
|
||||
overflow:hidden;
|
||||
font-size:12px;
|
||||
}
|
||||
.subNav {
|
||||
background-color:#dee3e9;
|
||||
float:left;
|
||||
width:100%;
|
||||
overflow:hidden;
|
||||
font-size:12px;
|
||||
}
|
||||
.subNav div {
|
||||
clear:left;
|
||||
float:left;
|
||||
padding:0 0 5px 6px;
|
||||
text-transform:uppercase;
|
||||
}
|
||||
ul.navList, ul.subNavList {
|
||||
float:left;
|
||||
margin:0 25px 0 0;
|
||||
padding:0;
|
||||
}
|
||||
ul.navList li{
|
||||
list-style:none;
|
||||
float:left;
|
||||
padding: 5px 6px;
|
||||
text-transform:uppercase;
|
||||
}
|
||||
ul.subNavList li{
|
||||
list-style:none;
|
||||
float:left;
|
||||
}
|
||||
.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited {
|
||||
color:#FFFFFF;
|
||||
text-decoration:none;
|
||||
text-transform:uppercase;
|
||||
}
|
||||
.topNav a:hover, .bottomNav a:hover {
|
||||
text-decoration:none;
|
||||
color:#bb7a2a;
|
||||
text-transform:uppercase;
|
||||
}
|
||||
.navBarCell1Rev {
|
||||
background-color:#F8981D;
|
||||
color:#253441;
|
||||
margin: auto 5px;
|
||||
}
|
||||
.skipNav {
|
||||
position:absolute;
|
||||
top:auto;
|
||||
left:-9999px;
|
||||
overflow:hidden;
|
||||
}
|
||||
/*
|
||||
Page header and footer styles
|
||||
*/
|
||||
.header, .footer {
|
||||
clear:both;
|
||||
margin:0 20px;
|
||||
padding:5px 0 0 0;
|
||||
}
|
||||
.indexHeader {
|
||||
margin:10px;
|
||||
position:relative;
|
||||
}
|
||||
.indexHeader span{
|
||||
margin-right:15px;
|
||||
}
|
||||
.indexHeader h1 {
|
||||
font-size:13px;
|
||||
}
|
||||
.title {
|
||||
color:#2c4557;
|
||||
margin:10px 0;
|
||||
}
|
||||
.subTitle {
|
||||
margin:5px 0 0 0;
|
||||
}
|
||||
.header ul {
|
||||
margin:0 0 15px 0;
|
||||
padding:0;
|
||||
}
|
||||
.footer ul {
|
||||
margin:20px 0 5px 0;
|
||||
}
|
||||
.header ul li, .footer ul li {
|
||||
list-style:none;
|
||||
font-size:13px;
|
||||
}
|
||||
/*
|
||||
Heading styles
|
||||
*/
|
||||
div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 {
|
||||
background-color:#dee3e9;
|
||||
border:1px solid #d0d9e0;
|
||||
margin:0 0 6px -8px;
|
||||
padding:7px 5px;
|
||||
}
|
||||
ul.blockList ul.blockList ul.blockList li.blockList h3 {
|
||||
background-color:#dee3e9;
|
||||
border:1px solid #d0d9e0;
|
||||
margin:0 0 6px -8px;
|
||||
padding:7px 5px;
|
||||
}
|
||||
ul.blockList ul.blockList li.blockList h3 {
|
||||
padding:0;
|
||||
margin:15px 0;
|
||||
}
|
||||
ul.blockList li.blockList h2 {
|
||||
padding:0px 0 20px 0;
|
||||
}
|
||||
/*
|
||||
Page layout container styles
|
||||
*/
|
||||
.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer {
|
||||
clear:both;
|
||||
padding:10px 20px;
|
||||
position:relative;
|
||||
}
|
||||
.indexContainer {
|
||||
margin:10px;
|
||||
position:relative;
|
||||
font-size:12px;
|
||||
}
|
||||
.indexContainer h2 {
|
||||
font-size:13px;
|
||||
padding:0 0 3px 0;
|
||||
}
|
||||
.indexContainer ul {
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
.indexContainer ul li {
|
||||
list-style:none;
|
||||
padding-top:2px;
|
||||
}
|
||||
.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt {
|
||||
font-size:12px;
|
||||
font-weight:bold;
|
||||
margin:10px 0 0 0;
|
||||
color:#4E4E4E;
|
||||
}
|
||||
.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd {
|
||||
margin:5px 0 10px 0px;
|
||||
font-size:14px;
|
||||
font-family:'DejaVu Sans Mono',monospace;
|
||||
}
|
||||
.serializedFormContainer dl.nameValue dt {
|
||||
margin-left:1px;
|
||||
font-size:1.1em;
|
||||
display:inline;
|
||||
font-weight:bold;
|
||||
}
|
||||
.serializedFormContainer dl.nameValue dd {
|
||||
margin:0 0 0 1px;
|
||||
font-size:1.1em;
|
||||
display:inline;
|
||||
}
|
||||
/*
|
||||
List styles
|
||||
*/
|
||||
ul.horizontal li {
|
||||
display:inline;
|
||||
font-size:0.9em;
|
||||
}
|
||||
ul.inheritance {
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
ul.inheritance li {
|
||||
display:inline;
|
||||
list-style:none;
|
||||
}
|
||||
ul.inheritance li ul.inheritance {
|
||||
margin-left:15px;
|
||||
padding-left:15px;
|
||||
padding-top:1px;
|
||||
}
|
||||
ul.blockList, ul.blockListLast {
|
||||
margin:10px 0 10px 0;
|
||||
padding:0;
|
||||
}
|
||||
ul.blockList li.blockList, ul.blockListLast li.blockList {
|
||||
list-style:none;
|
||||
margin-bottom:15px;
|
||||
line-height:1.4;
|
||||
}
|
||||
ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList {
|
||||
padding:0px 20px 5px 10px;
|
||||
border:1px solid #ededed;
|
||||
background-color:#f8f8f8;
|
||||
}
|
||||
ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList {
|
||||
padding:0 0 5px 8px;
|
||||
background-color:#ffffff;
|
||||
border:none;
|
||||
}
|
||||
ul.blockList ul.blockList ul.blockList ul.blockList li.blockList {
|
||||
margin-left:0;
|
||||
padding-left:0;
|
||||
padding-bottom:15px;
|
||||
border:none;
|
||||
}
|
||||
ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast {
|
||||
list-style:none;
|
||||
border-bottom:none;
|
||||
padding-bottom:0;
|
||||
}
|
||||
table tr td dl, table tr td dl dt, table tr td dl dd {
|
||||
margin-top:0;
|
||||
margin-bottom:1px;
|
||||
}
|
||||
/*
|
||||
Table styles
|
||||
*/
|
||||
.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary {
|
||||
width:100%;
|
||||
border-left:1px solid #EEE;
|
||||
border-right:1px solid #EEE;
|
||||
border-bottom:1px solid #EEE;
|
||||
}
|
||||
.overviewSummary, .memberSummary {
|
||||
padding:0px;
|
||||
}
|
||||
.overviewSummary caption, .memberSummary caption, .typeSummary caption,
|
||||
.useSummary caption, .constantsSummary caption, .deprecatedSummary caption {
|
||||
position:relative;
|
||||
text-align:left;
|
||||
background-repeat:no-repeat;
|
||||
color:#253441;
|
||||
font-weight:bold;
|
||||
clear:none;
|
||||
overflow:hidden;
|
||||
padding:0px;
|
||||
padding-top:10px;
|
||||
padding-left:1px;
|
||||
margin:0px;
|
||||
white-space:pre;
|
||||
}
|
||||
.overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link,
|
||||
.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link,
|
||||
.overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover,
|
||||
.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover,
|
||||
.overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active,
|
||||
.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active,
|
||||
.overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited,
|
||||
.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited {
|
||||
color:#FFFFFF;
|
||||
}
|
||||
.overviewSummary caption span, .memberSummary caption span, .typeSummary caption span,
|
||||
.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span {
|
||||
white-space:nowrap;
|
||||
padding-top:5px;
|
||||
padding-left:12px;
|
||||
padding-right:12px;
|
||||
padding-bottom:7px;
|
||||
display:inline-block;
|
||||
float:left;
|
||||
background-color:#F8981D;
|
||||
border: none;
|
||||
height:16px;
|
||||
}
|
||||
.memberSummary caption span.activeTableTab span {
|
||||
white-space:nowrap;
|
||||
padding-top:5px;
|
||||
padding-left:12px;
|
||||
padding-right:12px;
|
||||
margin-right:3px;
|
||||
display:inline-block;
|
||||
float:left;
|
||||
background-color:#F8981D;
|
||||
height:16px;
|
||||
}
|
||||
.memberSummary caption span.tableTab span {
|
||||
white-space:nowrap;
|
||||
padding-top:5px;
|
||||
padding-left:12px;
|
||||
padding-right:12px;
|
||||
margin-right:3px;
|
||||
display:inline-block;
|
||||
float:left;
|
||||
background-color:#4D7A97;
|
||||
height:16px;
|
||||
}
|
||||
.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab {
|
||||
padding-top:0px;
|
||||
padding-left:0px;
|
||||
padding-right:0px;
|
||||
background-image:none;
|
||||
float:none;
|
||||
display:inline;
|
||||
}
|
||||
.overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd,
|
||||
.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd {
|
||||
display:none;
|
||||
width:5px;
|
||||
position:relative;
|
||||
float:left;
|
||||
background-color:#F8981D;
|
||||
}
|
||||
.memberSummary .activeTableTab .tabEnd {
|
||||
display:none;
|
||||
width:5px;
|
||||
margin-right:3px;
|
||||
position:relative;
|
||||
float:left;
|
||||
background-color:#F8981D;
|
||||
}
|
||||
.memberSummary .tableTab .tabEnd {
|
||||
display:none;
|
||||
width:5px;
|
||||
margin-right:3px;
|
||||
position:relative;
|
||||
background-color:#4D7A97;
|
||||
float:left;
|
||||
|
||||
}
|
||||
.overviewSummary td, .memberSummary td, .typeSummary td,
|
||||
.useSummary td, .constantsSummary td, .deprecatedSummary td {
|
||||
text-align:left;
|
||||
padding:0px 0px 12px 10px;
|
||||
width:100%;
|
||||
}
|
||||
th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th,
|
||||
td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{
|
||||
vertical-align:top;
|
||||
padding-right:0px;
|
||||
padding-top:8px;
|
||||
padding-bottom:3px;
|
||||
}
|
||||
th.colFirst, th.colLast, th.colOne, .constantsSummary th {
|
||||
background:#dee3e9;
|
||||
text-align:left;
|
||||
padding:8px 3px 3px 7px;
|
||||
}
|
||||
td.colFirst, th.colFirst {
|
||||
white-space:nowrap;
|
||||
font-size:13px;
|
||||
}
|
||||
td.colLast, th.colLast {
|
||||
font-size:13px;
|
||||
}
|
||||
td.colOne, th.colOne {
|
||||
font-size:13px;
|
||||
}
|
||||
.overviewSummary td.colFirst, .overviewSummary th.colFirst,
|
||||
.overviewSummary td.colOne, .overviewSummary th.colOne,
|
||||
.memberSummary td.colFirst, .memberSummary th.colFirst,
|
||||
.memberSummary td.colOne, .memberSummary th.colOne,
|
||||
.typeSummary td.colFirst{
|
||||
width:25%;
|
||||
vertical-align:top;
|
||||
}
|
||||
td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover {
|
||||
font-weight:bold;
|
||||
}
|
||||
.tableSubHeadingColor {
|
||||
background-color:#EEEEFF;
|
||||
}
|
||||
.altColor {
|
||||
background-color:#FFFFFF;
|
||||
}
|
||||
.rowColor {
|
||||
background-color:#EEEEEF;
|
||||
}
|
||||
/*
|
||||
Content styles
|
||||
*/
|
||||
.description pre {
|
||||
margin-top:0;
|
||||
}
|
||||
.deprecatedContent {
|
||||
margin:0;
|
||||
padding:10px 0;
|
||||
}
|
||||
.docSummary {
|
||||
padding:0;
|
||||
}
|
||||
|
||||
ul.blockList ul.blockList ul.blockList li.blockList h3 {
|
||||
font-style:normal;
|
||||
}
|
||||
|
||||
div.block {
|
||||
font-size:14px;
|
||||
font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif;
|
||||
}
|
||||
|
||||
td.colLast div {
|
||||
padding-top:0px;
|
||||
}
|
||||
|
||||
|
||||
td.colLast a {
|
||||
padding-bottom:3px;
|
||||
}
|
||||
/*
|
||||
Formatting effect styles
|
||||
*/
|
||||
.sourceLineNo {
|
||||
color:green;
|
||||
padding:0 30px 0 0;
|
||||
}
|
||||
h1.hidden {
|
||||
visibility:hidden;
|
||||
overflow:hidden;
|
||||
font-size:10px;
|
||||
}
|
||||
.block {
|
||||
display:block;
|
||||
margin:3px 10px 2px 0px;
|
||||
color:#474747;
|
||||
}
|
||||
.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink,
|
||||
.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel,
|
||||
.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink {
|
||||
font-weight:bold;
|
||||
}
|
||||
.deprecationComment, .emphasizedPhrase, .interfaceName {
|
||||
font-style:italic;
|
||||
}
|
||||
|
||||
div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase,
|
||||
div.block div.block span.interfaceName {
|
||||
font-style:normal;
|
||||
}
|
||||
|
||||
div.contentContainer ul.blockList li.blockList h2{
|
||||
padding-bottom:0px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Spring
|
||||
*/
|
||||
|
||||
pre.code {
|
||||
background-color: #F8F8F8;
|
||||
border: 1px solid #CCCCCC;
|
||||
border-radius: 3px 3px 3px 3px;
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
margin: 4px 20px 2px 0px;
|
||||
}
|
||||
|
||||
pre.code code, pre.code code * {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
pre.code code, pre.code code * {
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
47
docs/src/docs/asciidoc/css/stylesheet.css
Normal file
47
docs/src/docs/asciidoc/css/stylesheet.css
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
@import 'css/spring.css';
|
||||
|
||||
.listingblock .switch {
|
||||
border-style: none;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
bottom: -3px;
|
||||
}
|
||||
|
||||
.listingblock .switch--item {
|
||||
padding: 10px;
|
||||
background-color: #e6e1dc;
|
||||
color: #282c34;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
|
||||
.listingblock .switch--item:not(:first-child) {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
.listingblock .switch--item.selected {
|
||||
background-color: #282c34;
|
||||
color: #e6e1dc;
|
||||
}
|
||||
|
||||
.listingblock pre.highlightjs {
|
||||
padding: 0;
|
||||
}
|
||||
277
docs/src/docs/asciidoc/index.adoc
Normal file
277
docs/src/docs/asciidoc/index.adoc
Normal file
@@ -0,0 +1,277 @@
|
||||
= Spring GraphQL Documentation
|
||||
:toc: left
|
||||
:toclevels: 4
|
||||
:tabsize: 4
|
||||
:docinfo1:
|
||||
|
||||
|
||||
https://graphql.org/[GraphQL] support for Spring applications with https://github.com/graphql-java/graphql-java[GraphQL Java].
|
||||
|
||||
== Getting started
|
||||
|
||||
This project is tested against Spring Boot 2.4+.
|
||||
|
||||
You can start by creating a project on https://start.spring.io and select the `spring-boot-starter-web` or `spring-boot-starter-webflux` starter,
|
||||
depending on the type of web application you'd like to build. Once the project is generated, you can manually add the
|
||||
`org.springframework.experimental:graphql-spring-boot-starter` dependency.
|
||||
|
||||
`build.gradle` snippet:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
dependencies {
|
||||
implementation 'org.springframework.experimental:graphql-spring-boot-starter:1.0.0-SNAPSHOT'
|
||||
|
||||
// Spring Web MVC starter
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||
// OR Spring WebFlux starter
|
||||
implementation 'org.springframework.boot:spring-boot-starter-webflux'
|
||||
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
// don't forget to add spring milestone or snapshot repositories
|
||||
maven { url 'https://repo.spring.io/milestone' }
|
||||
maven { url 'https://repo.spring.io/snapshot' }
|
||||
}
|
||||
----
|
||||
|
||||
`pom.xml` snippet:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.experimental</groupId>
|
||||
<artifactId>graphql-spring-boot-starter</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Web MVC starter -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<!-- OR Spring WebFlux starter -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
</dependency>
|
||||
<!-- ... -->
|
||||
</dependencies>
|
||||
|
||||
<!-- Don't forget to add spring milestone or snapshot repositories -->
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spring-snapshots</id>
|
||||
<name>Spring Snapshots</name>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
----
|
||||
|
||||
You can now add a GraphQL schema in `src/main/resources/graphql/schema.graphqls` such as:
|
||||
|
||||
[source,javascript,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
type Query {
|
||||
people: [Person]!
|
||||
}
|
||||
|
||||
type Person {
|
||||
id: ID!
|
||||
name: String!
|
||||
}
|
||||
----
|
||||
|
||||
Then you should configure the data fetching process using a `RuntimeWiringCustomizer` and custom components like
|
||||
Spring Data repositories, `WebClient` instances for Web APIs, a `@Service` bean, etc.
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@Component
|
||||
public class PersonDataWiring implements RuntimeWiringCustomizer {
|
||||
|
||||
private final PersonService personService;
|
||||
|
||||
public PersonDataWiring(PersonService personService) {
|
||||
this.personService = personService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(RuntimeWiring.Builder builder) {
|
||||
builder.type("Query", typeWiring -> typeWiring
|
||||
.dataFetcher("people", env -> this.personService.findAll()));
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
You can now start your application!
|
||||
A GraphiQL web interface is available at `http://localhost:8080/graphql` and you can use GraphQL clients
|
||||
to POST queries at the same location.
|
||||
|
||||
|
||||
== Features
|
||||
|
||||
=== Core configuration
|
||||
The Spring GraphQL project offers a few configuration properties to customize your application:
|
||||
|
||||
[source,properties,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
# web path to the graphql endpoint
|
||||
spring.graphql.path=/graphql
|
||||
# locations of the graphql '*.graphqls' schema files
|
||||
spring.graphql.schema.locations=classpath:graphql/
|
||||
# schema printer endpoint configuration
|
||||
# endpoint path is concatenated with the main path, so "/graphql/schema" by default
|
||||
spring.graphql.schema.printer.enabled=false
|
||||
spring.graphql.schema.printer.path=/schema
|
||||
# GraphiQL UI configuration
|
||||
spring.graphql.graphiql.enabled=true
|
||||
spring.graphql.graphiql.path=/graphiql
|
||||
# whether micrometer metrics should be collected for graphql queries
|
||||
management.metrics.graphql.autotime.enabled=true
|
||||
----
|
||||
|
||||
You can contribute `RuntimeWiringCustomizer` beans to the context in order to configure the runtime wiring of your GraphQL application.
|
||||
|
||||
=== WebSocket support
|
||||
|
||||
This project also supports WebSocket as a transport for GraphQL requests - you can use it to build [`Subscription` queries](http://spec.graphql.org/draft/#sec-Subscription).
|
||||
This use case is powered by Reactor `Flux`, check out the `samples/webflux-websocket` sample application for more.
|
||||
|
||||
To enable this support, you need to configure the `spring.graphql.websocket.path` property in your application
|
||||
and have the required dependencies on classpath. In the case of a Servlet application, adding the `spring-boot-starter-websocket` should be enough.
|
||||
|
||||
WebSocket support comes with dedicated properties:
|
||||
|
||||
[source,properties,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
# Path of the GraphQL WebSocket subscription endpoint.
|
||||
spring.graphql.websocket.path=/graphql/websocket
|
||||
# Time within which the initial {@code CONNECTION_INIT} type message must be received.
|
||||
spring.graphql.websocket.connection-init-timeout=60s
|
||||
----
|
||||
|
||||
=== Extension points
|
||||
|
||||
You can contribute [`WebInterceptor` beans](https://github.com/spring-projects-experimental/spring-graphql/blob/master/spring-graphql/src/main/java/org/springframework/graphql/WebInterceptor.java)
|
||||
to the application context, so as to customize the `ExecutionInput` or the `ExecutionResult` of the query.
|
||||
A custom `WebInterceptor` can, for example, change the HTTP request/response headers.
|
||||
|
||||
=== Testing support
|
||||
|
||||
When the `spring-boot-starter-test` dependency is on the classpath, Spring GraphQL provides a testing infrastructure for your application.
|
||||
|
||||
Spring Boot allows you to test your web application with [with a mock environment](https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.testing.spring-boot-applications.with-mock-environment)
|
||||
or [with a running server](https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.testing.spring-boot-applications.with-running-server).
|
||||
In both cases, adding the `@AutoConfigureGraphQlTester` annotation on your test class will contribute a `GraphQlTester` bean you can inject and use in your tests:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@AutoConfigureGraphQlTester
|
||||
public class MockMvcGraphQlTests {
|
||||
|
||||
@Autowired
|
||||
private GraphQlTester graphQlTester;
|
||||
|
||||
@Test
|
||||
void jsonPath() {
|
||||
String query = "{" +
|
||||
" project(slug:\"spring-framework\") {" +
|
||||
" releases {" +
|
||||
" version" +
|
||||
" }" +
|
||||
" }" +
|
||||
"}";
|
||||
|
||||
this.graphQlTester.query(query)
|
||||
.execute()
|
||||
.path("project.releases[*].version")
|
||||
.entityList(String.class)
|
||||
.hasSizeGreaterThan(1);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
=== Metrics
|
||||
|
||||
If the `spring-boot-starter-actuator` dependency is on the classpath, metrics will be collected for GraphQL requests.
|
||||
You can see those metrics by exposing the metrics endpoint with `application.properties`:
|
||||
|
||||
[source,properties,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
management.endpoints.web.exposure.include=health,metrics,info
|
||||
----
|
||||
|
||||
==== GraphQL Request (timer)
|
||||
|
||||
A Request metric timer is available at `/actuator/metrics/graphql.request`.
|
||||
|
||||
[cols="1,2,2"]
|
||||
|===
|
||||
|Tag | Description| Sample values
|
||||
|
||||
|outcome
|
||||
|Request outcome
|
||||
|"SUCCESS", "ERROR"
|
||||
|===
|
||||
|
||||
==== GraphQL Data Fetcher (timer)
|
||||
|
||||
A Data Fetcher metric timer is available at `/actuator/metrics/graphql.datafetcher`.
|
||||
|
||||
[cols="1,2,2"]
|
||||
|===
|
||||
|Tag | Description| Sample values
|
||||
|
||||
|path
|
||||
|data fetcher path
|
||||
|"Query.project"
|
||||
|
||||
|outcome
|
||||
|data fetching outcome
|
||||
|"SUCCESS", "ERROR"
|
||||
|===
|
||||
|
||||
|
||||
==== GraphQL Error (counter)
|
||||
|
||||
A counter metric counter is available at `/actuator/metrics/graphql.error`.
|
||||
|
||||
[cols="1,2,2"]
|
||||
|===
|
||||
|Tag | Description| Sample values
|
||||
|
||||
|errorType
|
||||
|error type
|
||||
|"DataFetchingException"
|
||||
|
||||
|errorPath
|
||||
|error JSON Path
|
||||
|"$.project"
|
||||
|===
|
||||
|
||||
|
||||
== Sample applications
|
||||
|
||||
This repository contains sample applications that the team is using to test new features and ideas.
|
||||
|
||||
You can run them by cloning this repository and typing on the command line:
|
||||
|
||||
[source,bash,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
$ ./gradlew :samples:webmvc-http:bootRun
|
||||
$ ./gradlew :samples:webflux-websocket:bootRun
|
||||
----
|
||||
@@ -1,94 +1,97 @@
|
||||
apply plugin: "maven-publish"
|
||||
|
||||
javadoc {
|
||||
description = "Generates project-level javadoc for use in -javadoc jar"
|
||||
plugins.withType(JavaPlugin) {
|
||||
javadoc {
|
||||
description = "Generates project-level javadoc for use in -javadoc jar"
|
||||
|
||||
options.encoding = "UTF-8"
|
||||
options.memberLevel = JavadocMemberLevel.PROTECTED
|
||||
options.author = true
|
||||
options.header = project.name
|
||||
options.use = true
|
||||
options.addStringOption("Xdoclint:none", "-quiet")
|
||||
options.encoding = "UTF-8"
|
||||
options.memberLevel = JavadocMemberLevel.PROTECTED
|
||||
options.author = true
|
||||
options.header = project.name
|
||||
options.use = true
|
||||
options.addStringOption("Xdoclint:none", "-quiet")
|
||||
|
||||
// Suppress warnings due to cross-module @see and @link references.
|
||||
// Note that global 'api' task does display all warnings.
|
||||
logging.captureStandardError LogLevel.INFO
|
||||
logging.captureStandardOutput LogLevel.INFO // suppress "## warnings" message
|
||||
}
|
||||
// Suppress warnings due to cross-module @see and @link references.
|
||||
// Note that global 'api' task does display all warnings.
|
||||
logging.captureStandardError LogLevel.INFO
|
||||
logging.captureStandardOutput LogLevel.INFO // suppress "## warnings" message
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar, dependsOn: classes) {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
archiveClassifier.set("sources")
|
||||
from sourceSets.main.allSource
|
||||
}
|
||||
task sourcesJar(type: Jar, dependsOn: classes) {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
archiveClassifier.set("sources")
|
||||
from sourceSets.main.allSource
|
||||
}
|
||||
|
||||
task javadocJar(type: Jar) {
|
||||
archiveClassifier.set("javadoc")
|
||||
from javadoc
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
pom {
|
||||
afterEvaluate {
|
||||
name = project.description
|
||||
description = project.description
|
||||
}
|
||||
url = "https://github.com/spring-projects/spring-graphql"
|
||||
organization {
|
||||
name = "Spring IO"
|
||||
url = "https://spring.io/projects"
|
||||
}
|
||||
licenses {
|
||||
license {
|
||||
name = "Apache License, Version 2.0"
|
||||
url = "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
distribution = "repo"
|
||||
task javadocJar(type: Jar) {
|
||||
archiveClassifier.set("javadoc")
|
||||
from javadoc
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
pom {
|
||||
afterEvaluate {
|
||||
name = project.description
|
||||
description = project.description
|
||||
}
|
||||
}
|
||||
scm {
|
||||
url = "https://github.com/spring-projects/spring-graphql"
|
||||
connection = "scm:git:git://github.com/spring-projects/spring-graphql"
|
||||
developerConnection = "scm:git:git://github.com/spring-projects/spring-graphql"
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id = "andimarek"
|
||||
name = "Andreas Marek"
|
||||
email = "andimarek@fastmail.fm"
|
||||
organization {
|
||||
name = "Spring IO"
|
||||
url = "https://spring.io/projects"
|
||||
}
|
||||
developer {
|
||||
id = "rstoyanchev"
|
||||
name = "Rossen Stoyanchev"
|
||||
email = "rstoyanchev@vmware.com"
|
||||
licenses {
|
||||
license {
|
||||
name = "Apache License, Version 2.0"
|
||||
url = "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
distribution = "repo"
|
||||
}
|
||||
}
|
||||
developer {
|
||||
id = "bclozel"
|
||||
name = "Brian Clozel"
|
||||
email = "bclozel@vmware.com"
|
||||
scm {
|
||||
url = "https://github.com/spring-projects/spring-graphql"
|
||||
connection = "scm:git:git://github.com/spring-projects/spring-graphql"
|
||||
developerConnection = "scm:git:git://github.com/spring-projects/spring-graphql"
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id = "andimarek"
|
||||
name = "Andreas Marek"
|
||||
email = "andimarek@fastmail.fm"
|
||||
}
|
||||
developer {
|
||||
id = "rstoyanchev"
|
||||
name = "Rossen Stoyanchev"
|
||||
email = "rstoyanchev@vmware.com"
|
||||
}
|
||||
developer {
|
||||
id = "bclozel"
|
||||
name = "Brian Clozel"
|
||||
email = "bclozel@vmware.com"
|
||||
}
|
||||
}
|
||||
issueManagement {
|
||||
system = "GitHub"
|
||||
url = "https://github.com/spring-projects/spring-graphql/issues"
|
||||
}
|
||||
}
|
||||
issueManagement {
|
||||
system = "GitHub"
|
||||
url = "https://github.com/spring-projects/spring-graphql/issues"
|
||||
versionMapping {
|
||||
usage('java-api') {
|
||||
fromResolutionResult()
|
||||
}
|
||||
usage('java-runtime') {
|
||||
fromResolutionResult()
|
||||
}
|
||||
}
|
||||
from components.java
|
||||
artifact sourcesJar
|
||||
artifact javadocJar
|
||||
}
|
||||
versionMapping {
|
||||
usage('java-api') {
|
||||
fromResolutionResult()
|
||||
}
|
||||
usage('java-runtime') {
|
||||
fromResolutionResult()
|
||||
}
|
||||
}
|
||||
from components.java
|
||||
artifact sourcesJar
|
||||
artifact javadocJar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
configureDeploymentRepository(project)
|
||||
|
||||
void configureDeploymentRepository(Project project) {
|
||||
|
||||
@@ -21,4 +21,5 @@ include 'spring-graphql',
|
||||
'samples:webmvc-http',
|
||||
'samples:webmvc-http-security',
|
||||
'samples:webflux-security',
|
||||
'samples:webflux-websocket'
|
||||
'samples:webflux-websocket',
|
||||
'docs'
|
||||
|
||||
Reference in New Issue
Block a user