Sync docs from v1.0.0.M2 to gh-pages

This commit is contained in:
Dave Syer
2017-11-28 13:46:13 +00:00
parent 4393800b8f
commit b7a2b56034
51 changed files with 1964 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
/*
code highlight CSS resemblign the Eclipse IDE default color schema
@author Costin Leau
*/
.hl-keyword {
color: #7F0055;
font-weight: bold;
}
.hl-comment {
color: #3F5F5F;
font-style: italic;
}
.hl-multiline-comment {
color: #3F5FBF;
font-style: italic;
}
.hl-tag {
color: #3F7F7F;
}
.hl-attribute {
color: #7F007F;
}
.hl-value {
color: #2A00FF;
}
.hl-string {
color: #2A00FF;
}

View File

@@ -0,0 +1,9 @@
@IMPORT url("manual.css");
body.firstpage {
background: url("../images/background.png") no-repeat center top;
}
div.part h1 {
border-top: none;
}

View File

@@ -0,0 +1,6 @@
@IMPORT url("manual.css");
body {
background: url("../images/background.png") no-repeat center top;
}

View File

@@ -0,0 +1,344 @@
@IMPORT url("highlight.css");
html {
padding: 0pt;
margin: 0pt;
}
body {
color: #333333;
margin: 15px 30px;
font-family: Helvetica, Arial, Freesans, Clean, Sans-serif;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
code {
font-size: 16px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
:not(a)>code {
color: #6D180B;
}
:not(pre)>code {
background-color: #F2F2F2;
border: 1px solid #CCCCCC;
border-radius: 4px;
padding: 1px 3px 0;
text-shadow: none;
white-space: nowrap;
}
body>*:first-child {
margin-top: 0 !important;
}
div {
margin: 0pt;
}
hr {
border: 1px solid #CCCCCC;
background: #CCCCCC;
}
h1,h2,h3,h4,h5,h6 {
color: #000000;
cursor: text;
font-weight: bold;
margin: 30px 0 10px;
padding: 0;
}
h1,h2,h3 {
margin: 40px 0 10px;
}
h1 {
margin: 70px 0 30px;
padding-top: 20px;
}
div.part h1 {
border-top: 1px dotted #CCCCCC;
}
h1,h1 code {
font-size: 32px;
}
h2,h2 code {
font-size: 24px;
}
h3,h3 code {
font-size: 20px;
}
h4,h1 code,h5,h5 code,h6,h6 code {
font-size: 18px;
}
div.book,div.chapter,div.appendix,div.part,div.preface {
min-width: 300px;
max-width: 1200px;
margin: 0 auto;
}
p.releaseinfo {
font-weight: bold;
margin-bottom: 40px;
margin-top: 40px;
}
div.authorgroup {
line-height: 1;
}
p.copyright {
line-height: 1;
margin-bottom: -5px;
}
.legalnotice p {
font-style: italic;
font-size: 14px;
line-height: 1;
}
div.titlepage+p,div.titlepage+p {
margin-top: 0;
}
pre {
line-height: 1.0;
color: black;
}
a {
color: #4183C4;
text-decoration: none;
}
p {
margin: 15px 0;
text-align: left;
}
ul,ol {
padding-left: 30px;
}
li p {
margin: 0;
}
div.table {
margin: 1em;
padding: 0.5em;
text-align: center;
}
div.table table,div.informaltable table {
display: table;
width: 100%;
}
div.table td {
padding-left: 7px;
padding-right: 7px;
}
.sidebar {
line-height: 1.4;
padding: 0 20px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
}
.sidebar p.title {
color: #6D180B;
}
pre.programlisting,pre.screen {
font-size: 15px;
padding: 6px 10px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
clear: both;
overflow: auto;
line-height: 1.4;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #DDDDDD !important;
border-radius: 4px !important;
border-collapse: separate !important;
line-height: 1.6;
}
table thead {
background: #F5F5F5;
}
table tr {
border: none;
border-bottom: none;
}
table th {
font-weight: bold;
}
table th,table td {
border: none !important;
padding: 6px 13px;
}
table tr:nth-child(2n) {
background-color: #F8F8F8;
}
td p {
margin: 0 0 15px 0;
}
div.table-contents td p {
margin: 0;
}
div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist *
{
border: none !important;
background: none !important;
margin: 0;
}
div.important p,div.note p,div.tip p,div.warning p {
color: #6F6F6F;
line-height: 1.6;
}
div.important code,div.note code,div.tip code,div.warning code {
background-color: #F2F2F2 !important;
border: 1px solid #CCCCCC !important;
border-radius: 4px !important;
padding: 1px 3px 0 !important;
text-shadow: none !important;
white-space: nowrap !important;
}
.note th,.tip th,.warning th {
display: none;
}
.note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td
{
border-right: 1px solid #CCCCCC !important;
padding-top: 10px;
}
div.calloutlist p,div.calloutlist td {
padding: 0;
margin: 0;
}
div.calloutlist>table>tbody>tr>td:first-child {
padding-left: 10px;
width: 30px !important;
}
div.important,div.note,div.tip,div.warning {
margin-left: 0px !important;
margin-right: 20px !important;
margin-top: 20px;
margin-bottom: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
div.toc {
line-height: 1.2;
}
dl,dt {
margin-top: 1px;
margin-bottom: 0;
}
div.toc>dl>dt {
font-size: 32px;
font-weight: bold;
margin: 30px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dt {
font-size: 24px;
font-weight: bold;
margin: 20px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dd>dl>dt {
font-weight: bold;
font-size: 20px;
margin: 10px 0 0 0;
}
tbody.footnotes * {
border: none !important;
}
div.footnote p {
margin: 0;
line-height: 1;
}
div.footnote p sup {
margin-right: 6px;
vertical-align: middle;
}
div.navheader {
border-bottom: 1px solid #CCCCCC;
}
div.navfooter {
border-top: 1px solid #CCCCCC;
}
.title {
margin-left: -1em;
padding-left: 1em;
}
.title>a {
position: absolute;
visibility: hidden;
display: block;
font-size: 0.85em;
margin-top: 0.05em;
margin-left: -1em;
vertical-align: text-top;
color: black;
}
.title>a:before {
content: "\00A7";
}
.title:hover>a,.title>a:hover,.title:hover>a:hover {
visibility: visible;
}
.title:focus>a,.title>a:focus,.title:focus>a:focus {
outline: 0;
}

View File

@@ -0,0 +1,330 @@
#!/bin/bash -x
set -e
# Set default props like MAVEN_PATH, ROOT_FOLDER etc.
function set_default_props() {
# The script should be executed from the root folder
ROOT_FOLDER=`pwd`
echo "Current folder is ${ROOT_FOLDER}"
if [[ ! -e "${ROOT_FOLDER}/.git" ]]; then
echo "You're not in the root folder of the project!"
exit 1
fi
# Prop that will let commit the changes
COMMIT_CHANGES="no"
MAVEN_PATH=${MAVEN_PATH:-}
echo "Path to Maven is [${MAVEN_PATH}]"
REPO_NAME=${PWD##*/}
echo "Repo name is [${REPO_NAME}]"
SPRING_CLOUD_STATIC_REPO=${SPRING_CLOUD_STATIC_REPO:-git@github.com:spring-cloud/spring-cloud-static.git}
echo "Spring Cloud Static repo is [${SPRING_CLOUD_STATIC_REPO}"
}
# Check if gh-pages exists and docs have been built
function check_if_anything_to_sync() {
git remote set-url --push origin `git config remote.origin.url | sed -e 's/^git:/https:/'`
if ! (git remote set-branches --add origin gh-pages && git fetch -q); then
echo "No gh-pages, so not syncing"
exit 0
fi
if ! [ -d docs/target/generated-docs ] && ! [ "${BUILD}" == "yes" ]; then
echo "No gh-pages sources in docs/target/generated-docs, so not syncing"
exit 0
fi
}
function retrieve_current_branch() {
# Code getting the name of the current branch. For master we want to publish as we did until now
# http://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch
# If there is a branch already passed will reuse it - otherwise will try to find it
CURRENT_BRANCH=${BRANCH}
if [[ -z "${CURRENT_BRANCH}" ]] ; then
CURRENT_BRANCH=$(git symbolic-ref -q HEAD)
CURRENT_BRANCH=${CURRENT_BRANCH##refs/heads/}
CURRENT_BRANCH=${CURRENT_BRANCH:-HEAD}
fi
echo "Current branch is [${CURRENT_BRANCH}]"
git checkout ${CURRENT_BRANCH} || echo "Failed to check the branch... continuing with the script"
}
# Switches to the provided value of the release version. We always prefix it with `v`
function switch_to_tag() {
git checkout v${VERSION}
}
# Build the docs if switch is on
function build_docs_if_applicable() {
if [[ "${BUILD}" == "yes" ]] ; then
./mvnw clean install -P docs -pl docs -DskipTests
fi
}
# Get the name of the `docs.main` property
# Get whitelisted branches - assumes that a `docs` module is available under `docs` profile
function retrieve_doc_properties() {
MAIN_ADOC_VALUE=$("${MAVEN_PATH}"mvn -q \
-Dexec.executable="echo" \
-Dexec.args='${docs.main}' \
--non-recursive \
org.codehaus.mojo:exec-maven-plugin:1.3.1:exec)
echo "Extracted 'main.adoc' from Maven build [${MAIN_ADOC_VALUE}]"
WHITELIST_PROPERTY=${WHITELIST_PROPERTY:-"docs.whitelisted.branches"}
WHITELISTED_BRANCHES_VALUE=$("${MAVEN_PATH}"mvn -q \
-Dexec.executable="echo" \
-Dexec.args="\${${WHITELIST_PROPERTY}}" \
org.codehaus.mojo:exec-maven-plugin:1.3.1:exec \
-P docs \
-pl docs)
echo "Extracted '${WHITELIST_PROPERTY}' from Maven build [${WHITELISTED_BRANCHES_VALUE}]"
}
# Stash any outstanding changes
function stash_changes() {
git diff-index --quiet HEAD && dirty=$? || (echo "Failed to check if the current repo is dirty. Assuming that it is." && dirty="1")
if [ "$dirty" != "0" ]; then git stash; fi
}
# Switch to gh-pages branch to sync it with current branch
function add_docs_from_target() {
local DESTINATION_REPO_FOLDER
if [[ -z "${DESTINATION}" && -z "${CLONE}" ]] ; then
DESTINATION_REPO_FOLDER=${ROOT_FOLDER}
elif [[ "${CLONE}" == "yes" ]]; then
mkdir -p ${ROOT_FOLDER}/target
local clonedStatic=${ROOT_FOLDER}/target/spring-cloud-static
if [[ ! -e "${clonedStatic}/.git" ]]; then
echo "Cloning Spring Cloud Static to target"
git clone ${SPRING_CLOUD_STATIC_REPO} ${clonedStatic} && git checkout gh-pages
else
echo "Spring Cloud Static already cloned - will pull changes"
cd ${clonedStatic} && git checkout gh-pages && git pull origin gh-pages
fi
DESTINATION_REPO_FOLDER=${clonedStatic}/${REPO_NAME}
mkdir -p ${DESTINATION_REPO_FOLDER}
else
if [[ ! -e "${DESTINATION}/.git" ]]; then
echo "[${DESTINATION}] is not a git repository"
exit 1
fi
DESTINATION_REPO_FOLDER=${DESTINATION}/${REPO_NAME}
mkdir -p ${DESTINATION_REPO_FOLDER}
echo "Destination was provided [${DESTINATION}]"
fi
cd ${DESTINATION_REPO_FOLDER}
git checkout gh-pages
git pull origin gh-pages
# Add git branches
###################################################################
if [[ -z "${VERSION}" ]] ; then
copy_docs_for_current_version
else
copy_docs_for_provided_version
fi
commit_changes_if_applicable
}
# Copies the docs by using the retrieved properties from Maven build
function copy_docs_for_current_version() {
if [[ "${CURRENT_BRANCH}" == "master" ]] ; then
echo -e "Current branch is master - will copy the current docs only to the root folder"
for f in docs/target/generated-docs/*; do
file=${f#docs/target/generated-docs/*}
if ! git ls-files -i -o --exclude-standard --directory | grep -q ^$file$; then
# Not ignored...
cp -rf $f ${ROOT_FOLDER}/
git add -A ${ROOT_FOLDER}/$file
fi
done
COMMIT_CHANGES="yes"
else
echo -e "Current branch is [${CURRENT_BRANCH}]"
# http://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin
if [[ ",${WHITELISTED_BRANCHES_VALUE}," = *",${CURRENT_BRANCH},"* ]] ; then
mkdir -p ${ROOT_FOLDER}/${CURRENT_BRANCH}
echo -e "Branch [${CURRENT_BRANCH}] is whitelisted! Will copy the current docs to the [${CURRENT_BRANCH}] folder"
for f in docs/target/generated-docs/*; do
file=${f#docs/target/generated-docs/*}
if ! git ls-files -i -o --exclude-standard --directory | grep -q ^$file$; then
# Not ignored...
# We want users to access 1.0.0.RELEASE/ instead of 1.0.0.RELEASE/spring-cloud.sleuth.html
if [[ "${file}" == "${MAIN_ADOC_VALUE}.html" ]] ; then
# We don't want to copy the spring-cloud-sleuth.html
# we want it to be converted to index.html
cp -rf $f ${ROOT_FOLDER}/${CURRENT_BRANCH}/index.html
git add -A ${ROOT_FOLDER}/${CURRENT_BRANCH}/index.html
else
cp -rf $f ${ROOT_FOLDER}/${CURRENT_BRANCH}
git add -A ${ROOT_FOLDER}/${CURRENT_BRANCH}/$file
fi
fi
done
COMMIT_CHANGES="yes"
else
echo -e "Branch [${CURRENT_BRANCH}] is not on the white list! Check out the Maven [${WHITELIST_PROPERTY}] property in
[docs] module available under [docs] profile. Won't commit any changes to gh-pages for this branch."
fi
fi
}
# Copies the docs by using the explicitly provided version
function copy_docs_for_provided_version() {
local FOLDER=${DESTINATION_REPO_FOLDER}/${VERSION}
mkdir -p ${FOLDER}
echo -e "Current tag is [v${VERSION}] Will copy the current docs to the [${FOLDER}] folder"
for f in ${ROOT_FOLDER}/docs/target/generated-docs/*; do
file=${f#${ROOT_FOLDER}/docs/target/generated-docs/*}
copy_docs_for_branch ${file} ${FOLDER}
done
COMMIT_CHANGES="yes"
CURRENT_BRANCH="v${VERSION}"
}
# Copies the docs from target to the provided destination
# Params:
# $1 - file from target
# $2 - destination to which copy the files
function copy_docs_for_branch() {
local file=$1
local destination=$2
if ! git ls-files -i -o --exclude-standard --directory | grep -q ^${file}$; then
# Not ignored...
# We want users to access 1.0.0.RELEASE/ instead of 1.0.0.RELEASE/spring-cloud.sleuth.html
if [[ ("${file}" == "${MAIN_ADOC_VALUE}.html") || ("${file}" == "${REPO_NAME}.html") ]] ; then
# We don't want to copy the spring-cloud-sleuth.html
# we want it to be converted to index.html
cp -rf $f ${destination}/index.html
git add -A ${destination}/index.html
else
cp -rf $f ${destination}
git add -A ${destination}/$file
fi
fi
}
function commit_changes_if_applicable() {
if [[ "${COMMIT_CHANGES}" == "yes" ]] ; then
COMMIT_SUCCESSFUL="no"
git commit -a -m "Sync docs from ${CURRENT_BRANCH} to gh-pages" && COMMIT_SUCCESSFUL="yes" || echo "Failed to commit changes"
# Uncomment the following push if you want to auto push to
# the gh-pages branch whenever you commit to master locally.
# This is a little extreme. Use with care!
###################################################################
if [[ "${COMMIT_SUCCESSFUL}" == "yes" ]] ; then
git push origin gh-pages
fi
fi
}
# Switch back to the previous branch and exit block
function checkout_previous_branch() {
# If -version was provided we need to come back to root project
cd ${ROOT_FOLDER}
git checkout ${CURRENT_BRANCH} || echo "Failed to check the branch... continuing with the script"
if [ "$dirty" != "0" ]; then git stash pop; fi
exit 0
}
# Assert if properties have been properly passed
function assert_properties() {
echo "VERSION [${VERSION}], DESTINATION [${DESTINATION}], CLONE [${CLONE}]"
if [[ "${VERSION}" != "" && (-z "${DESTINATION}" && -z "${CLONE}") ]] ; then echo "Version was set but destination / clone was not!"; exit 1;fi
if [[ ("${DESTINATION}" != "" && "${CLONE}" != "") && -z "${VERSION}" ]] ; then echo "Destination / clone was set but version was not!"; exit 1;fi
if [[ "${DESTINATION}" != "" && "${CLONE}" == "yes" ]] ; then echo "Destination and clone was set. Pick one!"; exit 1;fi
}
# Prints the usage
function print_usage() {
cat <<EOF
The idea of this script is to update gh-pages branch with the generated docs. Without any options
the script will work in the following manner:
- if there's no gh-pages / target for docs module then the script ends
- for master branch the generated docs are copied to the root of gh-pages branch
- for any other branch (if that branch is whitelisted) a subfolder with branch name is created
and docs are copied there
- if the version switch is passed (-v) then a tag with (v) prefix will be retrieved and a folder
with that version number will be created in the gh-pages branch. WARNING! No whitelist verification will take place
- if the destination switch is passed (-d) then the script will check if the provided dir is a git repo and then will
switch to gh-pages of that repo and copy the generated docs to `docs/<project-name>/<version>`
- if the destination switch is passed (-d) then the script will check if the provided dir is a git repo and then will
switch to gh-pages of that repo and copy the generated docs to `docs/<project-name>/<version>`
USAGE:
You can use the following options:
-v|--version - the script will apply the whole procedure for a particular library version
-d|--destination - the root of destination folder where the docs should be copied. You have to use the full path.
E.g. point to spring-cloud-static folder. Can't be used with (-c)
-b|--build - will run the standard build process after checking out the branch
-c|--clone - will automatically clone the spring-cloud-static repo instead of providing the destination.
Obviously can't be used with (-d)
EOF
}
# ==========================================
# ____ ____ _____ _____ _____ _______
# / ____|/ ____| __ \|_ _| __ \__ __|
# | (___ | | | |__) | | | | |__) | | |
# \___ \| | | _ / | | | ___/ | |
# ____) | |____| | \ \ _| |_| | | |
# |_____/ \_____|_| \_\_____|_| |_|
#
# ==========================================
while [[ $# > 0 ]]
do
key="$1"
case ${key} in
-v|--version)
VERSION="$2"
shift # past argument
;;
-d|--destination)
DESTINATION="$2"
shift # past argument
;;
-b|--build)
BUILD="yes"
;;
-c|--clone)
CLONE="yes"
;;
-h|--help)
print_usage
exit 0
;;
*)
echo "Invalid option: [$1]"
print_usage
exit 1
;;
esac
shift # past argument or value
done
assert_properties
set_default_props
check_if_anything_to_sync
if [[ -z "${VERSION}" ]] ; then
retrieve_current_branch
else
switch_to_tag
fi
build_docs_if_applicable
retrieve_doc_properties
stash_changes
add_docs_from_target
checkout_previous_branch

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1 @@
please remove once this directory is not empty

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

View File

@@ -0,0 +1,117 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 1.5.5">
<title>spring-cloud-function</title>
<link rel="stylesheet" href="css/manual-singlepage.css">
<style>
.hidden {
display: none;
}
.switch {
border-width: 1px 1px 0 1px;
border-style: solid;
border-color: #7a2518;
display: inline-block;
}
.switch--item {
padding: 10px;
background-color: #ffffff;
color: #7a2518;
display: inline-block;
cursor: pointer;
}
.switch--item.selected {
background-color: #7a2519;
color: #ffffff;
}
</style>
<script src="http://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script>
<script type="text/javascript">
function addBlockSwitches() {
$('.primary').each(function() {
primary = $(this);
createSwitchItem(primary, createBlockSwitch(primary)).item.addClass("selected");
primary.children('.title').remove();
});
$('.secondary').each(function(idx, node) {
secondary = $(node);
primary = findPrimary(secondary);
switchItem = createSwitchItem(secondary, primary.children('.switch'));
switchItem.content.addClass('hidden');
findPrimary(secondary).append(switchItem.content);
secondary.remove();
});
}
function createBlockSwitch(primary) {
blockSwitch = $('<div class="switch"></div>');
primary.prepend(blockSwitch);
return blockSwitch;
}
function findPrimary(secondary) {
candidate = secondary.prev();
while (!candidate.is('.primary')) {
candidate = candidate.prev();
}
return candidate;
}
function createSwitchItem(block, blockSwitch) {
blockName = block.children('.title').text();
content = block.children('.content').first().append(block.next('.colist'));
item = $('<div class="switch--item">' + blockName + '</div>');
item.on('click', '', content, function(e) {
$(this).addClass('selected');
$(this).siblings().removeClass('selected');
e.data.siblings('.content').addClass('hidden');
e.data.removeClass('hidden');
});
blockSwitch.append(item);
return {'item': item, 'content': content};
}
$(addBlockSwitches);
</script>
</head>
<body class="article">
<div id="header">
<h1>spring-cloud-function</h1>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>1.0.0.M2</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_pick_the_documentation_option">Pick The Documentation Option</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p><a href="single/spring-cloud-function.html">Single HTML</a></p>
</li>
<li>
<p><a href="multi/multi_spring-cloud-function.html">Multi HTML</a></p>
</li>
</ul>
</div>
</div>
</div>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js"></script>
<script>prettyPrint()</script>
</body>
</html>

View File

@@ -0,0 +1,35 @@
/*
code highlight CSS resemblign the Eclipse IDE default color schema
@author Costin Leau
*/
.hl-keyword {
color: #7F0055;
font-weight: bold;
}
.hl-comment {
color: #3F5F5F;
font-style: italic;
}
.hl-multiline-comment {
color: #3F5FBF;
font-style: italic;
}
.hl-tag {
color: #3F7F7F;
}
.hl-attribute {
color: #7F007F;
}
.hl-value {
color: #2A00FF;
}
.hl-string {
color: #2A00FF;
}

View File

@@ -0,0 +1,9 @@
@IMPORT url("manual.css");
body.firstpage {
background: url("../images/background.png") no-repeat center top;
}
div.part h1 {
border-top: none;
}

View File

@@ -0,0 +1,6 @@
@IMPORT url("manual.css");
body {
background: url("../images/background.png") no-repeat center top;
}

View File

@@ -0,0 +1,344 @@
@IMPORT url("highlight.css");
html {
padding: 0pt;
margin: 0pt;
}
body {
color: #333333;
margin: 15px 30px;
font-family: Helvetica, Arial, Freesans, Clean, Sans-serif;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
code {
font-size: 16px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
:not(a)>code {
color: #6D180B;
}
:not(pre)>code {
background-color: #F2F2F2;
border: 1px solid #CCCCCC;
border-radius: 4px;
padding: 1px 3px 0;
text-shadow: none;
white-space: nowrap;
}
body>*:first-child {
margin-top: 0 !important;
}
div {
margin: 0pt;
}
hr {
border: 1px solid #CCCCCC;
background: #CCCCCC;
}
h1,h2,h3,h4,h5,h6 {
color: #000000;
cursor: text;
font-weight: bold;
margin: 30px 0 10px;
padding: 0;
}
h1,h2,h3 {
margin: 40px 0 10px;
}
h1 {
margin: 70px 0 30px;
padding-top: 20px;
}
div.part h1 {
border-top: 1px dotted #CCCCCC;
}
h1,h1 code {
font-size: 32px;
}
h2,h2 code {
font-size: 24px;
}
h3,h3 code {
font-size: 20px;
}
h4,h1 code,h5,h5 code,h6,h6 code {
font-size: 18px;
}
div.book,div.chapter,div.appendix,div.part,div.preface {
min-width: 300px;
max-width: 1200px;
margin: 0 auto;
}
p.releaseinfo {
font-weight: bold;
margin-bottom: 40px;
margin-top: 40px;
}
div.authorgroup {
line-height: 1;
}
p.copyright {
line-height: 1;
margin-bottom: -5px;
}
.legalnotice p {
font-style: italic;
font-size: 14px;
line-height: 1;
}
div.titlepage+p,div.titlepage+p {
margin-top: 0;
}
pre {
line-height: 1.0;
color: black;
}
a {
color: #4183C4;
text-decoration: none;
}
p {
margin: 15px 0;
text-align: left;
}
ul,ol {
padding-left: 30px;
}
li p {
margin: 0;
}
div.table {
margin: 1em;
padding: 0.5em;
text-align: center;
}
div.table table,div.informaltable table {
display: table;
width: 100%;
}
div.table td {
padding-left: 7px;
padding-right: 7px;
}
.sidebar {
line-height: 1.4;
padding: 0 20px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
}
.sidebar p.title {
color: #6D180B;
}
pre.programlisting,pre.screen {
font-size: 15px;
padding: 6px 10px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
clear: both;
overflow: auto;
line-height: 1.4;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #DDDDDD !important;
border-radius: 4px !important;
border-collapse: separate !important;
line-height: 1.6;
}
table thead {
background: #F5F5F5;
}
table tr {
border: none;
border-bottom: none;
}
table th {
font-weight: bold;
}
table th,table td {
border: none !important;
padding: 6px 13px;
}
table tr:nth-child(2n) {
background-color: #F8F8F8;
}
td p {
margin: 0 0 15px 0;
}
div.table-contents td p {
margin: 0;
}
div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist *
{
border: none !important;
background: none !important;
margin: 0;
}
div.important p,div.note p,div.tip p,div.warning p {
color: #6F6F6F;
line-height: 1.6;
}
div.important code,div.note code,div.tip code,div.warning code {
background-color: #F2F2F2 !important;
border: 1px solid #CCCCCC !important;
border-radius: 4px !important;
padding: 1px 3px 0 !important;
text-shadow: none !important;
white-space: nowrap !important;
}
.note th,.tip th,.warning th {
display: none;
}
.note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td
{
border-right: 1px solid #CCCCCC !important;
padding-top: 10px;
}
div.calloutlist p,div.calloutlist td {
padding: 0;
margin: 0;
}
div.calloutlist>table>tbody>tr>td:first-child {
padding-left: 10px;
width: 30px !important;
}
div.important,div.note,div.tip,div.warning {
margin-left: 0px !important;
margin-right: 20px !important;
margin-top: 20px;
margin-bottom: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
div.toc {
line-height: 1.2;
}
dl,dt {
margin-top: 1px;
margin-bottom: 0;
}
div.toc>dl>dt {
font-size: 32px;
font-weight: bold;
margin: 30px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dt {
font-size: 24px;
font-weight: bold;
margin: 20px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dd>dl>dt {
font-weight: bold;
font-size: 20px;
margin: 10px 0 0 0;
}
tbody.footnotes * {
border: none !important;
}
div.footnote p {
margin: 0;
line-height: 1;
}
div.footnote p sup {
margin-right: 6px;
vertical-align: middle;
}
div.navheader {
border-bottom: 1px solid #CCCCCC;
}
div.navfooter {
border-top: 1px solid #CCCCCC;
}
.title {
margin-left: -1em;
padding-left: 1em;
}
.title>a {
position: absolute;
visibility: hidden;
display: block;
font-size: 0.85em;
margin-top: 0.05em;
margin-left: -1em;
vertical-align: text-top;
color: black;
}
.title>a:before {
content: "\00A7";
}
.title:hover>a,.title>a:hover,.title:hover>a:hover {
visibility: visible;
}
.title:focus>a,.title>a:focus,.title:focus>a:focus {
outline: 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

View File

@@ -0,0 +1,20 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>3.&nbsp;Building and Running a Function</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-function.html" title="Spring Cloud Function"><link rel="up" href="multi_spring-cloud-function.html" title="Spring Cloud Function"><link rel="prev" href="multi__getting_started.html" title="2.&nbsp;Getting Started"><link rel="next" href="multi__deploying_a_packaged_function.html" title="4.&nbsp;Deploying a Packaged Function"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">3.&nbsp;Building and Running a Function</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__getting_started.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__deploying_a_packaged_function.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_building_and_running_a_function" href="#_building_and_running_a_function"></a>3.&nbsp;Building and Running a Function</h1></div></div></div><p>The sample <code class="literal">@SpringBootApplication</code> above has a function that can be
decorated at runtime by Spring Cloud Function to be an HTTP endpoint,
or a Stream processor, for instance with RabbitMQ, Apache Kafka or
JMS.</p><p>The <code class="literal">@Beans</code> can be <code class="literal">Function</code>, <code class="literal">Consumer</code> or <code class="literal">Supplier</code> (all from
<code class="literal">java.util</code>), and their parametric types can be String or POJO. A
<code class="literal">Function</code> is exposed as an HTTP POST if <code class="literal">spring-cloud-function-web</code>
is on the classpath, and as a Spring Cloud Stream <code class="literal">Processor</code> if
<code class="literal">spring-cloud-function-stream</code> is on the classpath and a
<code class="literal">spring.cloud.function.stream.endpoint</code> property is configured in the Spring
environment. A <code class="literal">Consumer</code> is also exposed as an HTTP POST, or as a Stream
<code class="literal">Sink</code>. A <code class="literal">Supplier</code> translates to an HTTP GET, or a Stream <code class="literal">Source</code>.</p><p>Functions can be of <code class="literal">Flux&lt;String&gt;</code> or <code class="literal">Flux&lt;Pojo&gt;</code> and Spring Cloud
Function takes care of converting the data to and from the desired
types, as long as it comes in as plain text or (in the case of the
POJO) JSON. TBD: support for <code class="literal">Flux&lt;Message&lt;Pojo&gt;&gt;</code> and maybe plain
<code class="literal">Pojo</code> types (Fluxes implied and implemented by the framework).</p><p>Functions can be grouped together in a single application, or deployed
one-per-jar. It&#8217;s up to the developer to choose. An app with multiple
functions can be deployed multiple times in different "personalities",
exposing different functions over different physical transports.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__getting_started.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__deploying_a_packaged_function.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">2.&nbsp;Getting Started&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-function.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;4.&nbsp;Deploying a Packaged Function</td></tr></table></div></body></html>

View File

@@ -0,0 +1,3 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>4.&nbsp;Deploying a Packaged Function</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-function.html" title="Spring Cloud Function"><link rel="up" href="multi_spring-cloud-function.html" title="Spring Cloud Function"><link rel="prev" href="multi__building_and_running_a_function.html" title="3.&nbsp;Building and Running a Function"><link rel="next" href="multi__dynamic_compilation.html" title="5.&nbsp;Dynamic Compilation"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">4.&nbsp;Deploying a Packaged Function</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__building_and_running_a_function.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__dynamic_compilation.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_deploying_a_packaged_function" href="#_deploying_a_packaged_function"></a>4.&nbsp;Deploying a Packaged Function</h1></div></div></div><p>TBD: describe the deployer app.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__building_and_running_a_function.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__dynamic_compilation.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">3.&nbsp;Building and Running a Function&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-function.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;5.&nbsp;Dynamic Compilation</td></tr></table></div></body></html>

View File

@@ -0,0 +1,19 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>5.&nbsp;Dynamic Compilation</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-function.html" title="Spring Cloud Function"><link rel="up" href="multi_spring-cloud-function.html" title="Spring Cloud Function"><link rel="prev" href="multi__deploying_a_packaged_function.html" title="4.&nbsp;Deploying a Packaged Function"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">5.&nbsp;Dynamic Compilation</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__deploying_a_packaged_function.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;</td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_dynamic_compilation" href="#_dynamic_compilation"></a>5.&nbsp;Dynamic Compilation</h1></div></div></div><p>To run these examples, change into the <code class="literal">scripts</code> directory:</p><pre class="screen">cd scripts</pre><p>Also, start a RabbitMQ server locally (e.g. execute <code class="literal">rabbitmq-server</code>).</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_start_the_function_registry_service" href="#_start_the_function_registry_service"></a>5.1&nbsp;Start the Function Registry Service:</h2></div></div></div><pre class="screen">./function-registry.sh</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_register_a_function" href="#_register_a_function"></a>5.2&nbsp;Register a Function:</h2></div></div></div><pre class="screen">./registerFunction.sh -n uppercase -f "f-&gt;f.map(s-&gt;s.toString().toUpperCase())"</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_run_a_rest_microservice_using_that_function" href="#_run_a_rest_microservice_using_that_function"></a>5.3&nbsp;Run a REST Microservice using that Function:</h2></div></div></div><pre class="screen">./web.sh -f uppercase -p 9000
curl -H "Content-Type: text/plain" -H "Accept: text/plain" localhost:9000/uppercase -d foo</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_register_a_supplier" href="#_register_a_supplier"></a>5.4&nbsp;Register a Supplier:</h2></div></div></div><pre class="screen">./registerSupplier.sh -n words -f "()-&gt;Flux.just(\"foo\",\"bar\")"</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_run_a_rest_microservice_using_that_supplier" href="#_run_a_rest_microservice_using_that_supplier"></a>5.5&nbsp;Run a REST Microservice using that Supplier:</h2></div></div></div><pre class="screen">./web.sh -s words -p 9001
curl -H "Accept: application/json" localhost:9001/words</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_register_a_consumer" href="#_register_a_consumer"></a>5.6&nbsp;Register a Consumer:</h2></div></div></div><pre class="screen">./registerConsumer.sh -n print -t String -f "System.out::println"</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_run_a_rest_microservice_using_that_consumer" href="#_run_a_rest_microservice_using_that_consumer"></a>5.7&nbsp;Run a REST Microservice using that Consumer:</h2></div></div></div><pre class="screen">./web.sh -c print -p 9002
curl -X POST -H "Content-Type: text/plain" -d foo localhost:9002/print</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_run_stream_processing_microservices" href="#_run_stream_processing_microservices"></a>5.8&nbsp;Run Stream Processing Microservices:</h2></div></div></div><p>First register a streaming words supplier:</p><pre class="screen">./registerSupplier.sh -n wordstream -f "()-&gt;Flux.intervalMillis(1000).map(i-&gt;\"message-\"+i)"</pre><p>Then start the source (supplier), processor (function), and sink (consumer) apps
(in reverse order):</p><pre class="screen">./stream.sh -p 9103 -i uppercaseWords -c print
./stream.sh -p 9102 -i words -f uppercase -o uppercaseWords
./stream.sh -p 9101 -s wordstream -o words</pre><p>The output will appear in the console of the sink app (one message per second, converted to uppercase):</p><pre class="screen">MESSAGE-0
MESSAGE-1
MESSAGE-2
MESSAGE-3
MESSAGE-4
MESSAGE-5
MESSAGE-6
MESSAGE-7
MESSAGE-8
MESSAGE-9
...</pre></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__deploying_a_packaged_function.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;</td></tr><tr><td width="40%" align="left" valign="top">4.&nbsp;Deploying a Packaged Function&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-function.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;</td></tr></table></div></body></html>

View File

@@ -0,0 +1,9 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>2.&nbsp;Getting Started</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-function.html" title="Spring Cloud Function"><link rel="up" href="multi_spring-cloud-function.html" title="Spring Cloud Function"><link rel="prev" href="multi__introduction.html" title="1.&nbsp;Introduction"><link rel="next" href="multi__building_and_running_a_function.html" title="3.&nbsp;Building and Running a Function"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">2.&nbsp;Getting Started</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__introduction.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__building_and_running_a_function.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_getting_started" href="#_getting_started"></a>2.&nbsp;Getting Started</h1></div></div></div><p>Build from the command line (and "install" the samples):</p><pre class="screen">$ ./mvnw clean install</pre><p>(If you like to YOLO add <code class="literal">-DskipTests</code>.)</p><p>Run one of the samples, e.g.</p><pre class="screen">$ java -jar spring-cloud-function-samples/spring-cloud-function-sample/target/*.jar</pre><p>This runs the app and exposes its functions over HTTP, so you can
convert a string to uppercase, like this:</p><pre class="screen">$ curl -H "Content-Type: text/plain" localhost:8080/uppercase -d Hello
HELLO</pre><p>You can convert multiple strings (a <code class="literal">Flux&lt;String&gt;</code>) by separating them
with new lines</p><pre class="screen">$ curl -H "Content-Type: text/plain" localhost:8080/uppercase -d 'Hello
&gt; World'
HELLOWORLD</pre><p>(You can use <code class="literal"><sup>Q</sup>J</code> in a terminal to insert a new line in a literal
string like that.)</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__introduction.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__building_and_running_a_function.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">1.&nbsp;Introduction&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-function.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;3.&nbsp;Building and Running a Function</td></tr></table></div></body></html>

View File

@@ -0,0 +1,27 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>1.&nbsp;Introduction</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-function.html" title="Spring Cloud Function"><link rel="up" href="multi_spring-cloud-function.html" title="Spring Cloud Function"><link rel="prev" href="multi_pr01.html" title=""><link rel="next" href="multi__getting_started.html" title="2.&nbsp;Getting Started"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">1.&nbsp;Introduction</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_pr01.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__getting_started.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_introduction" href="#_introduction"></a>1.&nbsp;Introduction</h1></div></div></div><p>Spring Cloud Function is a project with the following high-level goals:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><span class="emphasis"><em>Promote the implementation of business logic via functions.</em></span></li><li class="listitem"><span class="emphasis"><em>Decouple the development lifecycle of business logic from any specific runtime target so that the same code can run as a web endpoint, a stream processor, or a task.</em></span></li><li class="listitem"><span class="emphasis"><em>Support a uniform programming model across serverless providers, as well as the ability to run standalone (locally or in a PaaS).</em></span></li><li class="listitem"><span class="emphasis"><em>Enable Spring Boot features (auto-configuration, dependency injection, metrics) on serverless providers.</em></span></li></ul></div><p>It abstracts away all of the transport details and
infrastructure, allowing the developer to keep all the familiar tools
and processes, and focus firmly on business logic.</p><p>Here&#8217;s a complete, executable, testable Spring Boot application
(implementing a simple string manipulation):</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@SpringBootApplication</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Function&lt;Flux&lt;String&gt;, Flux&lt;String&gt;&gt; uppercase() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> flux -&gt; flux.map(value -&gt; value.toUpperCase());
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> main(String[] args) {
SpringApplication.run(Application.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>, args);
}
}</pre><p>It&#8217;s just a Spring Boot application, so it can be built, run and
tested, locally and in a CI build, the same way as any other Spring
Boot application. The <code class="literal">Function</code> is from <code class="literal">java.util</code> and <code class="literal">Flux</code> is a
<a class="link" href="http://www.reactive-streams.org/" target="_top">Reactive Streams</a> <code class="literal">Publisher</code> from
<a class="link" href="https://projectreactor.io/" target="_top">Project Reactor</a>. The function can be
accessed over HTTP or messaging.</p><p>Spring Cloud Function has 4 main features:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">Wrappers for <code class="literal">@Beans</code> of type <code class="literal">Function</code>, <code class="literal">Consumer</code> and
<code class="literal">Supplier</code>, exposing them to the outside world as either HTTP
endpoints and/or message stream listeners/publishers with RabbitMQ, Kafka etc.</li><li class="listitem">Compiling strings which are Java function bodies into bytecode, and
then turning them into <code class="literal">@Beans</code> that can be wrapped as above.</li><li class="listitem">Deploying a JAR file containing such an application context with an
isolated classloader, so that you can pack them together in a single
JVM.</li><li class="listitem">Adapters for <a class="link" href="https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-aws" target="_top">AWS Lambda</a>, <a class="link" href="https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-openwhisk" target="_top">Apache OpenWhisk</a> and possibly other "serverless" service providers.</li></ol></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Spring Cloud is released under the non-restrictive Apache 2.0 license. If you would like to contribute to this section of the documentation or if you find an error, please find the source code and issue trackers in the project at <a class="link" href="https://github.com/spring-cloud/spring-cloud-function/tree/master/docs/src/main/asciidoc" target="_top">github</a>.</p></td></tr></table></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_pr01.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__getting_started.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-function.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;2.&nbsp;Getting Started</td></tr></table></div></body></html>

View File

@@ -0,0 +1,3 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title></title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-function.html" title="Spring Cloud Function"><link rel="up" href="multi_spring-cloud-function.html" title="Spring Cloud Function"><link rel="prev" href="multi_spring-cloud-function.html" title="Spring Cloud Function"><link rel="next" href="multi__introduction.html" title="1.&nbsp;Introduction"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center"></th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_spring-cloud-function.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__introduction.html">Next</a></td></tr></table><hr></div><div class="preface"><div class="titlepage"><div><div><h1 class="title"><a name="d0e9" href="#d0e9"></a></h1></div></div></div><p>Mark Fisher, Dave Syer</p><p></p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_spring-cloud-function.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__introduction.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Spring Cloud Function&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-function.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;1.&nbsp;Introduction</td></tr></table></div></body></html>

View File

@@ -0,0 +1,3 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring Cloud Function</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-function.html" title="Spring Cloud Function"><link rel="next" href="multi_pr01.html" title=""></head><body class="firstpage" bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Spring Cloud Function</th></tr><tr><td width="20%" align="left">&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi_pr01.html">Next</a></td></tr></table><hr></div><div lang="en" class="book"><div class="titlepage"><div><div><h1 class="title"><a name="d0e3"></a>Spring Cloud Function</h1></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="preface"><a href="multi_pr01.html"></a></span></dt><dt><span class="chapter"><a href="multi__introduction.html">1. Introduction</a></span></dt><dt><span class="chapter"><a href="multi__getting_started.html">2. Getting Started</a></span></dt><dt><span class="chapter"><a href="multi__building_and_running_a_function.html">3. Building and Running a Function</a></span></dt><dt><span class="chapter"><a href="multi__deploying_a_packaged_function.html">4. Deploying a Packaged Function</a></span></dt><dt><span class="chapter"><a href="multi__dynamic_compilation.html">5. Dynamic Compilation</a></span></dt><dd><dl><dt><span class="section"><a href="multi__dynamic_compilation.html#_start_the_function_registry_service">5.1. Start the Function Registry Service:</a></span></dt><dt><span class="section"><a href="multi__dynamic_compilation.html#_register_a_function">5.2. Register a Function:</a></span></dt><dt><span class="section"><a href="multi__dynamic_compilation.html#_run_a_rest_microservice_using_that_function">5.3. Run a REST Microservice using that Function:</a></span></dt><dt><span class="section"><a href="multi__dynamic_compilation.html#_register_a_supplier">5.4. Register a Supplier:</a></span></dt><dt><span class="section"><a href="multi__dynamic_compilation.html#_run_a_rest_microservice_using_that_supplier">5.5. Run a REST Microservice using that Supplier:</a></span></dt><dt><span class="section"><a href="multi__dynamic_compilation.html#_register_a_consumer">5.6. Register a Consumer:</a></span></dt><dt><span class="section"><a href="multi__dynamic_compilation.html#_run_a_rest_microservice_using_that_consumer">5.7. Run a REST Microservice using that Consumer:</a></span></dt><dt><span class="section"><a href="multi__dynamic_compilation.html#_run_stream_processing_microservices">5.8. Run Stream Processing Microservices:</a></span></dt></dl></dd></dl></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left">&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi_pr01.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right" valign="top">&nbsp;</td></tr></table></div></body></html>

View File

@@ -0,0 +1,35 @@
/*
code highlight CSS resemblign the Eclipse IDE default color schema
@author Costin Leau
*/
.hl-keyword {
color: #7F0055;
font-weight: bold;
}
.hl-comment {
color: #3F5F5F;
font-style: italic;
}
.hl-multiline-comment {
color: #3F5FBF;
font-style: italic;
}
.hl-tag {
color: #3F7F7F;
}
.hl-attribute {
color: #7F007F;
}
.hl-value {
color: #2A00FF;
}
.hl-string {
color: #2A00FF;
}

View File

@@ -0,0 +1,9 @@
@IMPORT url("manual.css");
body.firstpage {
background: url("../images/background.png") no-repeat center top;
}
div.part h1 {
border-top: none;
}

View File

@@ -0,0 +1,6 @@
@IMPORT url("manual.css");
body {
background: url("../images/background.png") no-repeat center top;
}

View File

@@ -0,0 +1,344 @@
@IMPORT url("highlight.css");
html {
padding: 0pt;
margin: 0pt;
}
body {
color: #333333;
margin: 15px 30px;
font-family: Helvetica, Arial, Freesans, Clean, Sans-serif;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
code {
font-size: 16px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
:not(a)>code {
color: #6D180B;
}
:not(pre)>code {
background-color: #F2F2F2;
border: 1px solid #CCCCCC;
border-radius: 4px;
padding: 1px 3px 0;
text-shadow: none;
white-space: nowrap;
}
body>*:first-child {
margin-top: 0 !important;
}
div {
margin: 0pt;
}
hr {
border: 1px solid #CCCCCC;
background: #CCCCCC;
}
h1,h2,h3,h4,h5,h6 {
color: #000000;
cursor: text;
font-weight: bold;
margin: 30px 0 10px;
padding: 0;
}
h1,h2,h3 {
margin: 40px 0 10px;
}
h1 {
margin: 70px 0 30px;
padding-top: 20px;
}
div.part h1 {
border-top: 1px dotted #CCCCCC;
}
h1,h1 code {
font-size: 32px;
}
h2,h2 code {
font-size: 24px;
}
h3,h3 code {
font-size: 20px;
}
h4,h1 code,h5,h5 code,h6,h6 code {
font-size: 18px;
}
div.book,div.chapter,div.appendix,div.part,div.preface {
min-width: 300px;
max-width: 1200px;
margin: 0 auto;
}
p.releaseinfo {
font-weight: bold;
margin-bottom: 40px;
margin-top: 40px;
}
div.authorgroup {
line-height: 1;
}
p.copyright {
line-height: 1;
margin-bottom: -5px;
}
.legalnotice p {
font-style: italic;
font-size: 14px;
line-height: 1;
}
div.titlepage+p,div.titlepage+p {
margin-top: 0;
}
pre {
line-height: 1.0;
color: black;
}
a {
color: #4183C4;
text-decoration: none;
}
p {
margin: 15px 0;
text-align: left;
}
ul,ol {
padding-left: 30px;
}
li p {
margin: 0;
}
div.table {
margin: 1em;
padding: 0.5em;
text-align: center;
}
div.table table,div.informaltable table {
display: table;
width: 100%;
}
div.table td {
padding-left: 7px;
padding-right: 7px;
}
.sidebar {
line-height: 1.4;
padding: 0 20px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
}
.sidebar p.title {
color: #6D180B;
}
pre.programlisting,pre.screen {
font-size: 15px;
padding: 6px 10px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
clear: both;
overflow: auto;
line-height: 1.4;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #DDDDDD !important;
border-radius: 4px !important;
border-collapse: separate !important;
line-height: 1.6;
}
table thead {
background: #F5F5F5;
}
table tr {
border: none;
border-bottom: none;
}
table th {
font-weight: bold;
}
table th,table td {
border: none !important;
padding: 6px 13px;
}
table tr:nth-child(2n) {
background-color: #F8F8F8;
}
td p {
margin: 0 0 15px 0;
}
div.table-contents td p {
margin: 0;
}
div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist *
{
border: none !important;
background: none !important;
margin: 0;
}
div.important p,div.note p,div.tip p,div.warning p {
color: #6F6F6F;
line-height: 1.6;
}
div.important code,div.note code,div.tip code,div.warning code {
background-color: #F2F2F2 !important;
border: 1px solid #CCCCCC !important;
border-radius: 4px !important;
padding: 1px 3px 0 !important;
text-shadow: none !important;
white-space: nowrap !important;
}
.note th,.tip th,.warning th {
display: none;
}
.note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td
{
border-right: 1px solid #CCCCCC !important;
padding-top: 10px;
}
div.calloutlist p,div.calloutlist td {
padding: 0;
margin: 0;
}
div.calloutlist>table>tbody>tr>td:first-child {
padding-left: 10px;
width: 30px !important;
}
div.important,div.note,div.tip,div.warning {
margin-left: 0px !important;
margin-right: 20px !important;
margin-top: 20px;
margin-bottom: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
div.toc {
line-height: 1.2;
}
dl,dt {
margin-top: 1px;
margin-bottom: 0;
}
div.toc>dl>dt {
font-size: 32px;
font-weight: bold;
margin: 30px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dt {
font-size: 24px;
font-weight: bold;
margin: 20px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dd>dl>dt {
font-weight: bold;
font-size: 20px;
margin: 10px 0 0 0;
}
tbody.footnotes * {
border: none !important;
}
div.footnote p {
margin: 0;
line-height: 1;
}
div.footnote p sup {
margin-right: 6px;
vertical-align: middle;
}
div.navheader {
border-bottom: 1px solid #CCCCCC;
}
div.navfooter {
border-top: 1px solid #CCCCCC;
}
.title {
margin-left: -1em;
padding-left: 1em;
}
.title>a {
position: absolute;
visibility: hidden;
display: block;
font-size: 0.85em;
margin-top: 0.05em;
margin-left: -1em;
vertical-align: text-top;
color: black;
}
.title>a:before {
content: "\00A7";
}
.title:hover>a,.title>a:hover,.title:hover>a:hover {
visibility: visible;
}
.title:focus>a,.title>a:focus,.title:focus>a:focus {
outline: 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

View File

@@ -0,0 +1,66 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring Cloud Function</title><link rel="stylesheet" type="text/css" href="css/manual-singlepage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div lang="en" class="book"><div class="titlepage"><div><div><h1 class="title"><a name="d0e3"></a>Spring Cloud Function</h1></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="preface"><a href="#d0e9"></a></span></dt><dt><span class="chapter"><a href="#_introduction">1. Introduction</a></span></dt><dt><span class="chapter"><a href="#_getting_started">2. Getting Started</a></span></dt><dt><span class="chapter"><a href="#_building_and_running_a_function">3. Building and Running a Function</a></span></dt><dt><span class="chapter"><a href="#_deploying_a_packaged_function">4. Deploying a Packaged Function</a></span></dt><dt><span class="chapter"><a href="#_dynamic_compilation">5. Dynamic Compilation</a></span></dt><dd><dl><dt><span class="section"><a href="#_start_the_function_registry_service">5.1. Start the Function Registry Service:</a></span></dt><dt><span class="section"><a href="#_register_a_function">5.2. Register a Function:</a></span></dt><dt><span class="section"><a href="#_run_a_rest_microservice_using_that_function">5.3. Run a REST Microservice using that Function:</a></span></dt><dt><span class="section"><a href="#_register_a_supplier">5.4. Register a Supplier:</a></span></dt><dt><span class="section"><a href="#_run_a_rest_microservice_using_that_supplier">5.5. Run a REST Microservice using that Supplier:</a></span></dt><dt><span class="section"><a href="#_register_a_consumer">5.6. Register a Consumer:</a></span></dt><dt><span class="section"><a href="#_run_a_rest_microservice_using_that_consumer">5.7. Run a REST Microservice using that Consumer:</a></span></dt><dt><span class="section"><a href="#_run_stream_processing_microservices">5.8. Run Stream Processing Microservices:</a></span></dt></dl></dd></dl></div><div class="preface"><div class="titlepage"><div><div><h1 class="title"><a name="d0e9" href="#d0e9"></a></h1></div></div></div><p>Mark Fisher, Dave Syer</p><p></p></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_introduction" href="#_introduction"></a>1.&nbsp;Introduction</h1></div></div></div><p>Spring Cloud Function is a project with the following high-level goals:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><span class="emphasis"><em>Promote the implementation of business logic via functions.</em></span></li><li class="listitem"><span class="emphasis"><em>Decouple the development lifecycle of business logic from any specific runtime target so that the same code can run as a web endpoint, a stream processor, or a task.</em></span></li><li class="listitem"><span class="emphasis"><em>Support a uniform programming model across serverless providers, as well as the ability to run standalone (locally or in a PaaS).</em></span></li><li class="listitem"><span class="emphasis"><em>Enable Spring Boot features (auto-configuration, dependency injection, metrics) on serverless providers.</em></span></li></ul></div><p>It abstracts away all of the transport details and
infrastructure, allowing the developer to keep all the familiar tools
and processes, and focus firmly on business logic.</p><p>Here&#8217;s a complete, executable, testable Spring Boot application
(implementing a simple string manipulation):</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@SpringBootApplication</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Function&lt;Flux&lt;String&gt;, Flux&lt;String&gt;&gt; uppercase() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> flux -&gt; flux.map(value -&gt; value.toUpperCase());
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> main(String[] args) {
SpringApplication.run(Application.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>, args);
}
}</pre><p>It&#8217;s just a Spring Boot application, so it can be built, run and
tested, locally and in a CI build, the same way as any other Spring
Boot application. The <code class="literal">Function</code> is from <code class="literal">java.util</code> and <code class="literal">Flux</code> is a
<a class="link" href="http://www.reactive-streams.org/" target="_top">Reactive Streams</a> <code class="literal">Publisher</code> from
<a class="link" href="https://projectreactor.io/" target="_top">Project Reactor</a>. The function can be
accessed over HTTP or messaging.</p><p>Spring Cloud Function has 4 main features:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">Wrappers for <code class="literal">@Beans</code> of type <code class="literal">Function</code>, <code class="literal">Consumer</code> and
<code class="literal">Supplier</code>, exposing them to the outside world as either HTTP
endpoints and/or message stream listeners/publishers with RabbitMQ, Kafka etc.</li><li class="listitem">Compiling strings which are Java function bodies into bytecode, and
then turning them into <code class="literal">@Beans</code> that can be wrapped as above.</li><li class="listitem">Deploying a JAR file containing such an application context with an
isolated classloader, so that you can pack them together in a single
JVM.</li><li class="listitem">Adapters for <a class="link" href="https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-aws" target="_top">AWS Lambda</a>, <a class="link" href="https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-openwhisk" target="_top">Apache OpenWhisk</a> and possibly other "serverless" service providers.</li></ol></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Spring Cloud is released under the non-restrictive Apache 2.0 license. If you would like to contribute to this section of the documentation or if you find an error, please find the source code and issue trackers in the project at <a class="link" href="https://github.com/spring-cloud/spring-cloud-function/tree/master/docs/src/main/asciidoc" target="_top">github</a>.</p></td></tr></table></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_getting_started" href="#_getting_started"></a>2.&nbsp;Getting Started</h1></div></div></div><p>Build from the command line (and "install" the samples):</p><pre class="screen">$ ./mvnw clean install</pre><p>(If you like to YOLO add <code class="literal">-DskipTests</code>.)</p><p>Run one of the samples, e.g.</p><pre class="screen">$ java -jar spring-cloud-function-samples/spring-cloud-function-sample/target/*.jar</pre><p>This runs the app and exposes its functions over HTTP, so you can
convert a string to uppercase, like this:</p><pre class="screen">$ curl -H "Content-Type: text/plain" localhost:8080/uppercase -d Hello
HELLO</pre><p>You can convert multiple strings (a <code class="literal">Flux&lt;String&gt;</code>) by separating them
with new lines</p><pre class="screen">$ curl -H "Content-Type: text/plain" localhost:8080/uppercase -d 'Hello
&gt; World'
HELLOWORLD</pre><p>(You can use <code class="literal"><sup>Q</sup>J</code> in a terminal to insert a new line in a literal
string like that.)</p></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_building_and_running_a_function" href="#_building_and_running_a_function"></a>3.&nbsp;Building and Running a Function</h1></div></div></div><p>The sample <code class="literal">@SpringBootApplication</code> above has a function that can be
decorated at runtime by Spring Cloud Function to be an HTTP endpoint,
or a Stream processor, for instance with RabbitMQ, Apache Kafka or
JMS.</p><p>The <code class="literal">@Beans</code> can be <code class="literal">Function</code>, <code class="literal">Consumer</code> or <code class="literal">Supplier</code> (all from
<code class="literal">java.util</code>), and their parametric types can be String or POJO. A
<code class="literal">Function</code> is exposed as an HTTP POST if <code class="literal">spring-cloud-function-web</code>
is on the classpath, and as a Spring Cloud Stream <code class="literal">Processor</code> if
<code class="literal">spring-cloud-function-stream</code> is on the classpath and a
<code class="literal">spring.cloud.function.stream.endpoint</code> property is configured in the Spring
environment. A <code class="literal">Consumer</code> is also exposed as an HTTP POST, or as a Stream
<code class="literal">Sink</code>. A <code class="literal">Supplier</code> translates to an HTTP GET, or a Stream <code class="literal">Source</code>.</p><p>Functions can be of <code class="literal">Flux&lt;String&gt;</code> or <code class="literal">Flux&lt;Pojo&gt;</code> and Spring Cloud
Function takes care of converting the data to and from the desired
types, as long as it comes in as plain text or (in the case of the
POJO) JSON. TBD: support for <code class="literal">Flux&lt;Message&lt;Pojo&gt;&gt;</code> and maybe plain
<code class="literal">Pojo</code> types (Fluxes implied and implemented by the framework).</p><p>Functions can be grouped together in a single application, or deployed
one-per-jar. It&#8217;s up to the developer to choose. An app with multiple
functions can be deployed multiple times in different "personalities",
exposing different functions over different physical transports.</p></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_deploying_a_packaged_function" href="#_deploying_a_packaged_function"></a>4.&nbsp;Deploying a Packaged Function</h1></div></div></div><p>TBD: describe the deployer app.</p></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_dynamic_compilation" href="#_dynamic_compilation"></a>5.&nbsp;Dynamic Compilation</h1></div></div></div><p>To run these examples, change into the <code class="literal">scripts</code> directory:</p><pre class="screen">cd scripts</pre><p>Also, start a RabbitMQ server locally (e.g. execute <code class="literal">rabbitmq-server</code>).</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_start_the_function_registry_service" href="#_start_the_function_registry_service"></a>5.1&nbsp;Start the Function Registry Service:</h2></div></div></div><pre class="screen">./function-registry.sh</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_register_a_function" href="#_register_a_function"></a>5.2&nbsp;Register a Function:</h2></div></div></div><pre class="screen">./registerFunction.sh -n uppercase -f "f-&gt;f.map(s-&gt;s.toString().toUpperCase())"</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_run_a_rest_microservice_using_that_function" href="#_run_a_rest_microservice_using_that_function"></a>5.3&nbsp;Run a REST Microservice using that Function:</h2></div></div></div><pre class="screen">./web.sh -f uppercase -p 9000
curl -H "Content-Type: text/plain" -H "Accept: text/plain" localhost:9000/uppercase -d foo</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_register_a_supplier" href="#_register_a_supplier"></a>5.4&nbsp;Register a Supplier:</h2></div></div></div><pre class="screen">./registerSupplier.sh -n words -f "()-&gt;Flux.just(\"foo\",\"bar\")"</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_run_a_rest_microservice_using_that_supplier" href="#_run_a_rest_microservice_using_that_supplier"></a>5.5&nbsp;Run a REST Microservice using that Supplier:</h2></div></div></div><pre class="screen">./web.sh -s words -p 9001
curl -H "Accept: application/json" localhost:9001/words</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_register_a_consumer" href="#_register_a_consumer"></a>5.6&nbsp;Register a Consumer:</h2></div></div></div><pre class="screen">./registerConsumer.sh -n print -t String -f "System.out::println"</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_run_a_rest_microservice_using_that_consumer" href="#_run_a_rest_microservice_using_that_consumer"></a>5.7&nbsp;Run a REST Microservice using that Consumer:</h2></div></div></div><pre class="screen">./web.sh -c print -p 9002
curl -X POST -H "Content-Type: text/plain" -d foo localhost:9002/print</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_run_stream_processing_microservices" href="#_run_stream_processing_microservices"></a>5.8&nbsp;Run Stream Processing Microservices:</h2></div></div></div><p>First register a streaming words supplier:</p><pre class="screen">./registerSupplier.sh -n wordstream -f "()-&gt;Flux.intervalMillis(1000).map(i-&gt;\"message-\"+i)"</pre><p>Then start the source (supplier), processor (function), and sink (consumer) apps
(in reverse order):</p><pre class="screen">./stream.sh -p 9103 -i uppercaseWords -c print
./stream.sh -p 9102 -i words -f uppercase -o uppercaseWords
./stream.sh -p 9101 -s wordstream -o words</pre><p>The output will appear in the console of the sink app (one message per second, converted to uppercase):</p><pre class="screen">MESSAGE-0
MESSAGE-1
MESSAGE-2
MESSAGE-3
MESSAGE-4
MESSAGE-5
MESSAGE-6
MESSAGE-7
MESSAGE-8
MESSAGE-9
...</pre></div></div></div></body></html>

View File

@@ -0,0 +1,184 @@
<?xml version="1.0" encoding="UTF-8"?>
<?asciidoc-toc?>
<?asciidoc-numbered?>
<book xmlns="http://docbook.org/ns/docbook" xmlns:xl="http://www.w3.org/1999/xlink" version="5.0" xml:lang="en">
<info>
<title>Spring Cloud Function</title>
<date>2017-07-21</date>
</info>
<preface>
<title></title>
<simpara>Mark Fisher, Dave Syer</simpara>
<simpara><?asciidoc-hr?></simpara>
</preface>
<chapter xml:id="_introduction">
<title>Introduction</title>
<simpara>Spring Cloud Function is a project with the following high-level goals:</simpara>
<itemizedlist>
<listitem>
<simpara><emphasis>Promote the implementation of business logic via functions.</emphasis></simpara>
</listitem>
<listitem>
<simpara><emphasis>Decouple the development lifecycle of business logic from any specific runtime target so that the same code can run as a web endpoint, a stream processor, or a task.</emphasis></simpara>
</listitem>
<listitem>
<simpara><emphasis>Support a uniform programming model across serverless providers, as well as the ability to run standalone (locally or in a PaaS).</emphasis></simpara>
</listitem>
<listitem>
<simpara><emphasis>Enable Spring Boot features (auto-configuration, dependency injection, metrics) on serverless providers.</emphasis></simpara>
</listitem>
</itemizedlist>
<simpara>It abstracts away all of the transport details and
infrastructure, allowing the developer to keep all the familiar tools
and processes, and focus firmly on business logic.</simpara>
<simpara>Here&#8217;s a complete, executable, testable Spring Boot application
(implementing a simple string manipulation):</simpara>
<programlisting language="java" linenumbering="unnumbered">@SpringBootApplication
public class Application {
@Bean
public Function&lt;Flux&lt;String&gt;, Flux&lt;String&gt;&gt; uppercase() {
return flux -&gt; flux.map(value -&gt; value.toUpperCase());
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}</programlisting>
<simpara>It&#8217;s just a Spring Boot application, so it can be built, run and
tested, locally and in a CI build, the same way as any other Spring
Boot application. The <literal>Function</literal> is from <literal>java.util</literal> and <literal>Flux</literal> is a
<link xl:href="http://www.reactive-streams.org/">Reactive Streams</link> <literal>Publisher</literal> from
<link xl:href="https://projectreactor.io/">Project Reactor</link>. The function can be
accessed over HTTP or messaging.</simpara>
<simpara>Spring Cloud Function has 4 main features:</simpara>
<orderedlist numeration="arabic">
<listitem>
<simpara>Wrappers for <literal>@Beans</literal> of type <literal>Function</literal>, <literal>Consumer</literal> and
<literal>Supplier</literal>, exposing them to the outside world as either HTTP
endpoints and/or message stream listeners/publishers with RabbitMQ, Kafka etc.</simpara>
</listitem>
<listitem>
<simpara>Compiling strings which are Java function bodies into bytecode, and
then turning them into <literal>@Beans</literal> that can be wrapped as above.</simpara>
</listitem>
<listitem>
<simpara>Deploying a JAR file containing such an application context with an
isolated classloader, so that you can pack them together in a single
JVM.</simpara>
</listitem>
<listitem>
<simpara>Adapters for <link xl:href="https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-aws">AWS Lambda</link>, <link xl:href="https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-openwhisk">Apache OpenWhisk</link> and possibly other "serverless" service providers.</simpara>
</listitem>
</orderedlist>
<note>
<simpara>Spring Cloud is released under the non-restrictive Apache 2.0 license. If you would like to contribute to this section of the documentation or if you find an error, please find the source code and issue trackers in the project at <link xl:href="https://github.com/spring-cloud/spring-cloud-function/tree/master/docs/src/main/asciidoc">github</link>.</simpara>
</note>
</chapter>
<chapter xml:id="_getting_started">
<title>Getting Started</title>
<simpara>Build from the command line (and "install" the samples):</simpara>
<screen>$ ./mvnw clean install</screen>
<simpara>(If you like to YOLO add <literal>-DskipTests</literal>.)</simpara>
<simpara>Run one of the samples, e.g.</simpara>
<screen>$ java -jar spring-cloud-function-samples/spring-cloud-function-sample/target/*.jar</screen>
<simpara>This runs the app and exposes its functions over HTTP, so you can
convert a string to uppercase, like this:</simpara>
<screen>$ curl -H "Content-Type: text/plain" localhost:8080/uppercase -d Hello
HELLO</screen>
<simpara>You can convert multiple strings (a <literal>Flux&lt;String&gt;</literal>) by separating them
with new lines</simpara>
<screen>$ curl -H "Content-Type: text/plain" localhost:8080/uppercase -d 'Hello
&gt; World'
HELLOWORLD</screen>
<simpara>(You can use <literal><superscript>Q</superscript>J</literal> in a terminal to insert a new line in a literal
string like that.)</simpara>
</chapter>
<chapter xml:id="_building_and_running_a_function">
<title>Building and Running a Function</title>
<simpara>The sample <literal>@SpringBootApplication</literal> above has a function that can be
decorated at runtime by Spring Cloud Function to be an HTTP endpoint,
or a Stream processor, for instance with RabbitMQ, Apache Kafka or
JMS.</simpara>
<simpara>The <literal>@Beans</literal> can be <literal>Function</literal>, <literal>Consumer</literal> or <literal>Supplier</literal> (all from
<literal>java.util</literal>), and their parametric types can be String or POJO. A
<literal>Function</literal> is exposed as an HTTP POST if <literal>spring-cloud-function-web</literal>
is on the classpath, and as a Spring Cloud Stream <literal>Processor</literal> if
<literal>spring-cloud-function-stream</literal> is on the classpath and a
<literal>spring.cloud.function.stream.endpoint</literal> property is configured in the Spring
environment. A <literal>Consumer</literal> is also exposed as an HTTP POST, or as a Stream
<literal>Sink</literal>. A <literal>Supplier</literal> translates to an HTTP GET, or a Stream <literal>Source</literal>.</simpara>
<simpara>Functions can be of <literal>Flux&lt;String&gt;</literal> or <literal>Flux&lt;Pojo&gt;</literal> and Spring Cloud
Function takes care of converting the data to and from the desired
types, as long as it comes in as plain text or (in the case of the
POJO) JSON. TBD: support for <literal>Flux&lt;Message&lt;Pojo&gt;&gt;</literal> and maybe plain
<literal>Pojo</literal> types (Fluxes implied and implemented by the framework).</simpara>
<simpara>Functions can be grouped together in a single application, or deployed
one-per-jar. It&#8217;s up to the developer to choose. An app with multiple
functions can be deployed multiple times in different "personalities",
exposing different functions over different physical transports.</simpara>
</chapter>
<chapter xml:id="_deploying_a_packaged_function">
<title>Deploying a Packaged Function</title>
<simpara>TBD: describe the deployer app.</simpara>
</chapter>
<chapter xml:id="_dynamic_compilation">
<title>Dynamic Compilation</title>
<simpara>To run these examples, change into the <literal>scripts</literal> directory:</simpara>
<screen>cd scripts</screen>
<simpara>Also, start a RabbitMQ server locally (e.g. execute <literal>rabbitmq-server</literal>).</simpara>
<section xml:id="_start_the_function_registry_service">
<title>Start the Function Registry Service:</title>
<screen>./function-registry.sh</screen>
</section>
<section xml:id="_register_a_function">
<title>Register a Function:</title>
<screen>./registerFunction.sh -n uppercase -f "f-&gt;f.map(s-&gt;s.toString().toUpperCase())"</screen>
</section>
<section xml:id="_run_a_rest_microservice_using_that_function">
<title>Run a REST Microservice using that Function:</title>
<screen>./web.sh -f uppercase -p 9000
curl -H "Content-Type: text/plain" -H "Accept: text/plain" localhost:9000/uppercase -d foo</screen>
</section>
<section xml:id="_register_a_supplier">
<title>Register a Supplier:</title>
<screen>./registerSupplier.sh -n words -f "()-&gt;Flux.just(\"foo\",\"bar\")"</screen>
</section>
<section xml:id="_run_a_rest_microservice_using_that_supplier">
<title>Run a REST Microservice using that Supplier:</title>
<screen>./web.sh -s words -p 9001
curl -H "Accept: application/json" localhost:9001/words</screen>
</section>
<section xml:id="_register_a_consumer">
<title>Register a Consumer:</title>
<screen>./registerConsumer.sh -n print -t String -f "System.out::println"</screen>
</section>
<section xml:id="_run_a_rest_microservice_using_that_consumer">
<title>Run a REST Microservice using that Consumer:</title>
<screen>./web.sh -c print -p 9002
curl -X POST -H "Content-Type: text/plain" -d foo localhost:9002/print</screen>
</section>
<section xml:id="_run_stream_processing_microservices">
<title>Run Stream Processing Microservices:</title>
<simpara>First register a streaming words supplier:</simpara>
<screen>./registerSupplier.sh -n wordstream -f "()-&gt;Flux.intervalMillis(1000).map(i-&gt;\"message-\"+i)"</screen>
<simpara>Then start the source (supplier), processor (function), and sink (consumer) apps
(in reverse order):</simpara>
<screen>./stream.sh -p 9103 -i uppercaseWords -c print
./stream.sh -p 9102 -i words -f uppercase -o uppercaseWords
./stream.sh -p 9101 -s wordstream -o words</screen>
<simpara>The output will appear in the console of the sink app (one message per second, converted to uppercase):</simpara>
<screen>MESSAGE-0
MESSAGE-1
MESSAGE-2
MESSAGE-3
MESSAGE-4
MESSAGE-5
MESSAGE-6
MESSAGE-7
MESSAGE-8
MESSAGE-9
...</screen>
</section>
</chapter>
</book>