From 2223ea98b89501ea32f5c4d485b447ce499601c8 Mon Sep 17 00:00:00 2001 From: Raisel Melian Date: Wed, 31 Oct 2018 11:41:59 -0400 Subject: [PATCH 01/14] initial java skeleton --- templates/java-spring/__.gitignore | 26 +++ templates/java-spring/build.gradle | 44 +++++ templates/java-spring/gradlew | 172 ++++++++++++++++++ templates/java-spring/gradlew.bat | 84 +++++++++ templates/java-spring/settings.gradle | 1 + .../streetlights/StreetlightsApplication.java | 16 ++ .../streetlights/domain/LightMeasured.java | 32 ++++ .../streetlights/infrastructure/Bindings.java | 18 ++ .../streetlights/service/Handlers.java | 15 ++ .../src/main/resources/application.yml | 3 + .../StreetlightsApplicationTests.java | 16 ++ 11 files changed, 427 insertions(+) create mode 100644 templates/java-spring/__.gitignore create mode 100644 templates/java-spring/build.gradle create mode 100644 templates/java-spring/gradlew create mode 100644 templates/java-spring/gradlew.bat create mode 100644 templates/java-spring/settings.gradle create mode 100644 templates/java-spring/src/main/java/com/asyncapi/streetlights/StreetlightsApplication.java create mode 100644 templates/java-spring/src/main/java/com/asyncapi/streetlights/domain/LightMeasured.java create mode 100644 templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java create mode 100644 templates/java-spring/src/main/java/com/asyncapi/streetlights/service/Handlers.java create mode 100644 templates/java-spring/src/main/resources/application.yml create mode 100644 templates/java-spring/src/test/java/com/asyncapi/streetlights/StreetlightsApplicationTests.java diff --git a/templates/java-spring/__.gitignore b/templates/java-spring/__.gitignore new file mode 100644 index 000000000..9243c63d7 --- /dev/null +++ b/templates/java-spring/__.gitignore @@ -0,0 +1,26 @@ +.gradle +/build/ +!gradle/wrapper/gradle-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ \ No newline at end of file diff --git a/templates/java-spring/build.gradle b/templates/java-spring/build.gradle new file mode 100644 index 000000000..8f404c877 --- /dev/null +++ b/templates/java-spring/build.gradle @@ -0,0 +1,44 @@ +buildscript { + ext { + springBootVersion = '2.1.0.RELEASE' + } + repositories { + mavenCentral() + } + dependencies { + classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") + } +} + +apply plugin: 'java' +apply plugin: 'eclipse' +apply plugin: 'org.springframework.boot' +apply plugin: 'io.spring.dependency-management' + +group = 'com.asyncapi' +version = '0.0.1-SNAPSHOT' +sourceCompatibility = 1.8 + +repositories { + mavenCentral() + maven { url "https://repo.spring.io/milestone" } +} + + +ext { + springCloudVersion = 'Greenwich.M1' +} + +dependencies { + implementation('org.springframework.boot:spring-boot-starter-amqp') + implementation('org.springframework.cloud:spring-cloud-stream') + implementation('org.springframework.cloud:spring-cloud-stream-binder-rabbit') + testImplementation('org.springframework.boot:spring-boot-starter-test') + testImplementation('org.springframework.cloud:spring-cloud-stream-test-support') +} + +dependencyManagement { + imports { + mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" + } +} diff --git a/templates/java-spring/gradlew b/templates/java-spring/gradlew new file mode 100644 index 000000000..4453ccea3 --- /dev/null +++ b/templates/java-spring/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save ( ) { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/templates/java-spring/gradlew.bat b/templates/java-spring/gradlew.bat new file mode 100644 index 000000000..e95643d6a --- /dev/null +++ b/templates/java-spring/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/templates/java-spring/settings.gradle b/templates/java-spring/settings.gradle new file mode 100644 index 000000000..eee01af9f --- /dev/null +++ b/templates/java-spring/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'streetlights' diff --git a/templates/java-spring/src/main/java/com/asyncapi/streetlights/StreetlightsApplication.java b/templates/java-spring/src/main/java/com/asyncapi/streetlights/StreetlightsApplication.java new file mode 100644 index 000000000..f38359df2 --- /dev/null +++ b/templates/java-spring/src/main/java/com/asyncapi/streetlights/StreetlightsApplication.java @@ -0,0 +1,16 @@ +package com.asyncapi.streetlights; + +import com.asyncapi.streetlights.infrastructure.Bindings; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.stream.annotation.EnableBinding; + +@SpringBootApplication +@EnableBinding(Bindings.class) +public class StreetlightsApplication { + + public static void main(String[] args) { + SpringApplication.run(StreetlightsApplication.class, args); + } + +} diff --git a/templates/java-spring/src/main/java/com/asyncapi/streetlights/domain/LightMeasured.java b/templates/java-spring/src/main/java/com/asyncapi/streetlights/domain/LightMeasured.java new file mode 100644 index 000000000..03d1e8813 --- /dev/null +++ b/templates/java-spring/src/main/java/com/asyncapi/streetlights/domain/LightMeasured.java @@ -0,0 +1,32 @@ +package com.asyncapi.streetlights.domain; + +public class LightMeasured { + + private Integer lumens; + + private String sentAt; + + public Integer getLumens() { + return lumens; + } + + public void setLumens(Integer lumens) { + this.lumens = lumens; + } + + public String getSentAt() { + return sentAt; + } + + public void setSentAt(String sentAt) { + this.sentAt = sentAt; + } + + @Override + public String toString() { + return "LightMeasured{" + + "lumens=" + lumens + + ", sentAt='" + sentAt + '\'' + + '}'; + } +} diff --git a/templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java b/templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java new file mode 100644 index 000000000..c86ab6411 --- /dev/null +++ b/templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java @@ -0,0 +1,18 @@ +package com.asyncapi.streetlights.infrastructure; + +import org.springframework.cloud.stream.annotation.Input; +import org.springframework.messaging.SubscribableChannel; + +public interface Bindings { + {{#each asyncapi.topics}} + + @Input("{{@key}}") + SubscribableChannel input(); + {{/each}} + + {{#each asyncapi.topics as |topic |}} + {{topic.serviceName}}.{{topic.publish.summary}} + {{/each}} + // @Input(Bindings.INPUT) + // SubscribableChannel input(); +} diff --git a/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/Handlers.java b/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/Handlers.java new file mode 100644 index 000000000..5711c4647 --- /dev/null +++ b/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/Handlers.java @@ -0,0 +1,15 @@ +package com.asyncapi.streetlights.service; + +import com.asyncapi.streetlights.infrastructure.Bindings; +import org.springframework.cloud.stream.annotation.StreamListener; +import org.springframework.stereotype.Component; + +@Component +public class Handlers { + + @StreamListener(Bindings.INPUT) + public void handle(String lightMeasured) { + System.out.println("Received: " + lightMeasured); + } + +} diff --git a/templates/java-spring/src/main/resources/application.yml b/templates/java-spring/src/main/resources/application.yml new file mode 100644 index 000000000..796b34850 --- /dev/null +++ b/templates/java-spring/src/main/resources/application.yml @@ -0,0 +1,3 @@ +spring: + rabbitmq: + port: 32771 diff --git a/templates/java-spring/src/test/java/com/asyncapi/streetlights/StreetlightsApplicationTests.java b/templates/java-spring/src/test/java/com/asyncapi/streetlights/StreetlightsApplicationTests.java new file mode 100644 index 000000000..300fb5401 --- /dev/null +++ b/templates/java-spring/src/test/java/com/asyncapi/streetlights/StreetlightsApplicationTests.java @@ -0,0 +1,16 @@ +package com.asyncapi.streetlights; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class StreetlightsApplicationTests { + + @Test + public void contextLoads() { + } + +} From 5af37c6e04a6d3e1bb6838edac9522378bc2ec13 Mon Sep 17 00:00:00 2001 From: Raisel Melian Date: Wed, 31 Oct 2018 16:52:33 -0400 Subject: [PATCH 02/14] add support to generate SubscribableChannel from publish --- templates/java-spring/settings.gradle | 2 +- .../streetlights/infrastructure/Bindings.java | 28 +++++++++++++------ .../streetlights/service/Handlers.java | 9 +++--- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/templates/java-spring/settings.gradle b/templates/java-spring/settings.gradle index eee01af9f..80a6e73f5 100644 --- a/templates/java-spring/settings.gradle +++ b/templates/java-spring/settings.gradle @@ -1 +1 @@ -rootProject.name = 'streetlights' +rootProject.name = '{{asyncapi.info.x-project-name}}' diff --git a/templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java b/templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java index c86ab6411..a71c45fe2 100644 --- a/templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java +++ b/templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java @@ -1,18 +1,30 @@ package com.asyncapi.streetlights.infrastructure; import org.springframework.cloud.stream.annotation.Input; +import org.springframework.cloud.stream.annotation.Output; +import org.springframework.messaging.MessageChannel; import org.springframework.messaging.SubscribableChannel; public interface Bindings { - {{#each asyncapi.topics}} + {{#each asyncapi.topics as |topic |}} + {{#if topic.publish}} + String {{topic.publish.x-operation-id}} = "input{{topic.publish.x-operation-id}}"; + {{/if}} + {{#if topic.subscribe}} + String {{topic.subscribe.x-operation-id}} = "output{{topic.subscribe.x-operation-id}}"; + {{/if}} + {{/each}} - @Input("{{@key}}") + {{#each asyncapi.topics as |topic |}} + {{#if topic.publish}} + @Input(Bindings.{{topic.publish.x-operation-id}}) SubscribableChannel input(); - {{/each}} + {{/if}} + + {{#if topic.subscribe}} + @Output(Bindings.{{topic.subscribe.x-operation-id}}) + MessageChannel hotDrinks(); + {{/if}} + {{/each}} - {{#each asyncapi.topics as |topic |}} - {{topic.serviceName}}.{{topic.publish.summary}} - {{/each}} - // @Input(Bindings.INPUT) - // SubscribableChannel input(); } diff --git a/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/Handlers.java b/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/Handlers.java index 5711c4647..713a37afe 100644 --- a/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/Handlers.java +++ b/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/Handlers.java @@ -6,10 +6,11 @@ @Component public class Handlers { - - @StreamListener(Bindings.INPUT) - public void handle(String lightMeasured) { - System.out.println("Received: " + lightMeasured); +{{#each asyncapi.topics as |topic |}} + @StreamListener(Bindings.{{topic.publish.x-operation-id}}) + public void handle_{{topic.publish.x-operation-id}}(String message) { + System.out.println("Received: " + message); } +{{/each}} } From 66272ac45df0baa181186e5df336a121b197ed31 Mon Sep 17 00:00:00 2001 From: Raisel Melian Date: Wed, 31 Oct 2018 18:34:06 -0400 Subject: [PATCH 03/14] add support for creating sender (subscribe) --- .../streetlights/infrastructure/Bindings.java | 4 ++-- .../streetlights/service/Handlers.java | 3 +++ .../service/MessagePublisher.java | 23 +++++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 templates/java-spring/src/main/java/com/asyncapi/streetlights/service/MessagePublisher.java diff --git a/templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java b/templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java index a71c45fe2..91df0ad6c 100644 --- a/templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java +++ b/templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java @@ -18,12 +18,12 @@ public interface Bindings { {{#each asyncapi.topics as |topic |}} {{#if topic.publish}} @Input(Bindings.{{topic.publish.x-operation-id}}) - SubscribableChannel input(); + SubscribableChannel input{{topic.publish.x-operation-id}}(); {{/if}} {{#if topic.subscribe}} @Output(Bindings.{{topic.subscribe.x-operation-id}}) - MessageChannel hotDrinks(); + MessageChannel output{{topic.subscribe.x-operation-id}}(); {{/if}} {{/each}} diff --git a/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/Handlers.java b/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/Handlers.java index 713a37afe..34d489c37 100644 --- a/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/Handlers.java +++ b/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/Handlers.java @@ -6,11 +6,14 @@ @Component public class Handlers { + {{#each asyncapi.topics as |topic |}} + {{#if topic.publish}} @StreamListener(Bindings.{{topic.publish.x-operation-id}}) public void handle_{{topic.publish.x-operation-id}}(String message) { System.out.println("Received: " + message); } +{{/if}} {{/each}} } diff --git a/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/MessagePublisher.java b/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/MessagePublisher.java new file mode 100644 index 000000000..dbf76bab3 --- /dev/null +++ b/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/MessagePublisher.java @@ -0,0 +1,23 @@ +package com.asyncapi.streetlights.service; + +import com.asyncapi.streetlights.infrastructure.Bindings; +import org.springframework.messaging.support.MessageBuilder; + +public class MessagePublisher { + + private final Bindings bindings; + + + public MessagePublisher(Bindings bindings) { + this.bindings = bindings; + } + + {{#each asyncapi.topics as |topic |}} + {{#if topic.subscribe}} + public void send{{topic.subscribe.x-operation-id}}(String message) { + bindings.output{{topic.subscribe.x-operation-id}}().send(MessageBuilder.withPayload(message).build()); + } + {{/if}} + {{/each}} + +} From d5da9e30416c83e7906526d970f68a9558e013ce Mon Sep 17 00:00:00 2001 From: Raisel Melian Date: Wed, 31 Oct 2018 22:36:20 -0400 Subject: [PATCH 04/14] format Bindings variables to uppercase, capitalize java method names --- templates/java-spring/.helpers/handlebars.js | 13 +++++++++++++ .../streetlights/infrastructure/Bindings.java | 17 ++++++++--------- .../asyncapi/streetlights/service/Handlers.java | 4 ++-- .../streetlights/service/MessagePublisher.java | 4 ++-- 4 files changed, 25 insertions(+), 13 deletions(-) create mode 100644 templates/java-spring/.helpers/handlebars.js diff --git a/templates/java-spring/.helpers/handlebars.js b/templates/java-spring/.helpers/handlebars.js new file mode 100644 index 000000000..1098f1d08 --- /dev/null +++ b/templates/java-spring/.helpers/handlebars.js @@ -0,0 +1,13 @@ +module.exports = (Handlebars, _) => { + +//capitalizeFirstLetter + Handlebars.registerHelper('capFirst', (str) => { + return str.charAt(0).toUpperCase() + str.slice(1); + }); + +//convert string to java constant format: lightMeasuredPublish -> LIGHT_MEASURED_PUBLISH + Handlebars.registerHelper('javaConst', (str) => { + var tokenList = str.split(/(?=[A-Z])/); + return tokenList.map(function(x){ return x.toUpperCase() }).join("_"); + }); +}; diff --git a/templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java b/templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java index 91df0ad6c..c3e33d2e7 100644 --- a/templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java +++ b/templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java @@ -8,23 +8,22 @@ public interface Bindings { {{#each asyncapi.topics as |topic |}} {{#if topic.publish}} - String {{topic.publish.x-operation-id}} = "input{{topic.publish.x-operation-id}}"; + String {{javaConst topic.publish.x-operation-id}} = "input{{capFirst topic.publish.x-operation-id}}"; {{/if}} {{#if topic.subscribe}} - String {{topic.subscribe.x-operation-id}} = "output{{topic.subscribe.x-operation-id}}"; + String {{javaConst topic.subscribe.x-operation-id}} = "output{{capFirst topic.subscribe.x-operation-id}}"; {{/if}} {{/each}} - {{#each asyncapi.topics as |topic |}} {{#if topic.publish}} - @Input(Bindings.{{topic.publish.x-operation-id}}) - SubscribableChannel input{{topic.publish.x-operation-id}}(); - {{/if}} + @Input(Bindings.{{javaConst topic.publish.x-operation-id}}) + SubscribableChannel input{{capFirst topic.publish.x-operation-id}}(); + {{/if}} {{#if topic.subscribe}} - @Output(Bindings.{{topic.subscribe.x-operation-id}}) - MessageChannel output{{topic.subscribe.x-operation-id}}(); + + @Output(Bindings.{{javaConst topic.subscribe.x-operation-id}}) + MessageChannel output{{capFirst topic.subscribe.x-operation-id}}(); {{/if}} {{/each}} - } diff --git a/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/Handlers.java b/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/Handlers.java index 34d489c37..bfce9935b 100644 --- a/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/Handlers.java +++ b/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/Handlers.java @@ -9,8 +9,8 @@ public class Handlers { {{#each asyncapi.topics as |topic |}} {{#if topic.publish}} - @StreamListener(Bindings.{{topic.publish.x-operation-id}}) - public void handle_{{topic.publish.x-operation-id}}(String message) { + @StreamListener(Bindings.{{javaConst topic.publish.x-operation-id}}) + public void handle{{capFirst topic.publish.x-operation-id}}(String message) { System.out.println("Received: " + message); } {{/if}} diff --git a/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/MessagePublisher.java b/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/MessagePublisher.java index dbf76bab3..b30164d4d 100644 --- a/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/MessagePublisher.java +++ b/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/MessagePublisher.java @@ -14,8 +14,8 @@ public MessagePublisher(Bindings bindings) { {{#each asyncapi.topics as |topic |}} {{#if topic.subscribe}} - public void send{{topic.subscribe.x-operation-id}}(String message) { - bindings.output{{topic.subscribe.x-operation-id}}().send(MessageBuilder.withPayload(message).build()); + public void send{{capFirst topic.subscribe.x-operation-id}}(String message) { + bindings.output{{capFirst topic.subscribe.x-operation-id}}().send(MessageBuilder.withPayload(message).build()); } {{/if}} {{/each}} From f870a7ee3a99133ac24b18277c3506a6bd5f7ba0 Mon Sep 17 00:00:00 2001 From: Raisel Melian Date: Wed, 31 Oct 2018 22:44:08 -0400 Subject: [PATCH 05/14] remove non used class LightMeasured --- .../streetlights/domain/LightMeasured.java | 32 ------------------- 1 file changed, 32 deletions(-) delete mode 100644 templates/java-spring/src/main/java/com/asyncapi/streetlights/domain/LightMeasured.java diff --git a/templates/java-spring/src/main/java/com/asyncapi/streetlights/domain/LightMeasured.java b/templates/java-spring/src/main/java/com/asyncapi/streetlights/domain/LightMeasured.java deleted file mode 100644 index 03d1e8813..000000000 --- a/templates/java-spring/src/main/java/com/asyncapi/streetlights/domain/LightMeasured.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.asyncapi.streetlights.domain; - -public class LightMeasured { - - private Integer lumens; - - private String sentAt; - - public Integer getLumens() { - return lumens; - } - - public void setLumens(Integer lumens) { - this.lumens = lumens; - } - - public String getSentAt() { - return sentAt; - } - - public void setSentAt(String sentAt) { - this.sentAt = sentAt; - } - - @Override - public String toString() { - return "LightMeasured{" + - "lumens=" + lumens + - ", sentAt='" + sentAt + '\'' + - '}'; - } -} From 39045441f7e03f70dbb8e44ba63a24cb2f29561b Mon Sep 17 00:00:00 2001 From: Raisel Melian Date: Thu, 15 Nov 2018 09:06:25 -0500 Subject: [PATCH 06/14] migrate spring cloud streams to spring integration, support for MQTT --- lib/generator.js | 5 +- .../java-spring/{__.gitignore => .gitignore} | 0 templates/java-spring/.helpers/handlebars.js | 42 ++++++- .../java-spring/.partials/AmqpConfig.java | 112 ++++++++++++++++++ .../service => .partials}/Handlers.java | 6 +- .../MessagePublisher.java | 8 +- .../java-spring/.partials/MqttConfig.java | 107 +++++++++++++++++ templates/java-spring/build.gradle | 19 +-- templates/java-spring/settings.gradle | 2 +- .../main/java/com/asyncapi/Application.java | 13 ++ .../com/asyncapi/infrastructure/Config.java | 8 ++ .../com/asyncapi/service/MqttCommandLine.java | 25 ++++ .../asyncapi/service/MqttMessageHandler.java | 19 +++ .../com/asyncapi/service/MqttMyGateway.java | 16 +++ .../streetlights/StreetlightsApplication.java | 16 --- .../streetlights/infrastructure/Bindings.java | 29 ----- .../src/main/resources/application.yml | 28 ++++- ...cationTests.java => ApplicationTests.java} | 4 +- 18 files changed, 382 insertions(+), 77 deletions(-) rename templates/java-spring/{__.gitignore => .gitignore} (100%) create mode 100644 templates/java-spring/.partials/AmqpConfig.java rename templates/java-spring/{src/main/java/com/asyncapi/streetlights/service => .partials}/Handlers.java (66%) rename templates/java-spring/{src/main/java/com/asyncapi/streetlights/service => .partials}/MessagePublisher.java (51%) create mode 100644 templates/java-spring/.partials/MqttConfig.java create mode 100644 templates/java-spring/src/main/java/com/asyncapi/Application.java create mode 100644 templates/java-spring/src/main/java/com/asyncapi/infrastructure/Config.java create mode 100644 templates/java-spring/src/main/java/com/asyncapi/service/MqttCommandLine.java create mode 100644 templates/java-spring/src/main/java/com/asyncapi/service/MqttMessageHandler.java create mode 100644 templates/java-spring/src/main/java/com/asyncapi/service/MqttMyGateway.java delete mode 100644 templates/java-spring/src/main/java/com/asyncapi/streetlights/StreetlightsApplication.java delete mode 100644 templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java rename templates/java-spring/src/test/java/com/asyncapi/{streetlights/StreetlightsApplicationTests.java => ApplicationTests.java} (77%) diff --git a/lib/generator.js b/lib/generator.js index 833de764f..0921c7f42 100644 --- a/lib/generator.js +++ b/lib/generator.js @@ -8,6 +8,7 @@ const xfs = require('fs.extra'); const beautifier = require('./beautifier'); const registerPartial = require('./register-partial'); const parse = require('./parser'); +const util = require('util'); const generator = module.exports; @@ -236,7 +237,9 @@ const registerHelpers = config => new Promise((resolve, reject) => { */ const registerPartials = config => new Promise((resolve, reject) => { const partials_dir = path.resolve(config.templates, PARTIALS_DIRNAME); - + console.log("===================") + console.log(util.inspect(config, {showHidden: false, depth: null})) + console.log("===================") if (!fs.existsSync(partials_dir)) return resolve(); const walker = xfs.walk(partials_dir, { diff --git a/templates/java-spring/__.gitignore b/templates/java-spring/.gitignore similarity index 100% rename from templates/java-spring/__.gitignore rename to templates/java-spring/.gitignore diff --git a/templates/java-spring/.helpers/handlebars.js b/templates/java-spring/.helpers/handlebars.js index 1098f1d08..4a9facf0e 100644 --- a/templates/java-spring/.helpers/handlebars.js +++ b/templates/java-spring/.helpers/handlebars.js @@ -1,13 +1,47 @@ module.exports = (Handlebars, _) => { //capitalizeFirstLetter - Handlebars.registerHelper('capFirst', (str) => { - return str.charAt(0).toUpperCase() + str.slice(1); + Handlebars.registerHelper('capitalize', (str) => { + return _.capitalize(str); + }); + + Handlebars.registerHelper('camelCase', (str) => { + return _.camelCase(str); + }); + + Handlebars.registerHelper('upperFirst', (str) => { + return _.upperFirst(str); }); //convert string to java constant format: lightMeasuredPublish -> LIGHT_MEASURED_PUBLISH Handlebars.registerHelper('javaConst', (str) => { - var tokenList = str.split(/(?=[A-Z])/); - return tokenList.map(function(x){ return x.toUpperCase() }).join("_"); + return _.snakeCase(str).toUpperCase(); + }); + + Handlebars.registerHelper('compare', (lvalue, operator, rvalue, options) => { + if (arguments.length < 4) throw new Error('Handlerbars Helper "compare" needs 3 parameters'); + + const operators = { + '==': (l,r) => { return l == r; }, + '===': (l,r) => { return l === r; }, + '!=': (l,r) => { return l != r; }, + '<': (l,r) => { return l < r; }, + '>': (l,r) => { return l > r; }, + '<=': (l,r) => { return l <= r; }, + '>=': (l,r) => { return l >= r; }, + typeof: (l,r) => { return typeof l === r; } + }; + + if (!operators[operator]) throw new Error(`Handlerbars Helper 'compare' doesn't know the operator ${operator}`); + const result = operators[operator](lvalue,rvalue); + + if (result) return options.fn(this); + + return options.inverse(this); }); + + // Handlebars.registerHelper('json', function(context) { + // return JSON.stringify(context); + // }); + }; diff --git a/templates/java-spring/.partials/AmqpConfig.java b/templates/java-spring/.partials/AmqpConfig.java new file mode 100644 index 000000000..0e93a64de --- /dev/null +++ b/templates/java-spring/.partials/AmqpConfig.java @@ -0,0 +1,112 @@ +package com.asyncapi.streetlights.infrastructure; + +import com.asyncapi.streetlights.service.AmqpMessageHandler; +import org.springframework.amqp.core.*; +import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.core.RabbitAdmin; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.integration.amqp.dsl.Amqp; +import org.springframework.integration.amqp.outbound.AmqpOutboundEndpoint; +import org.springframework.integration.annotation.ServiceActivator; +import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.dsl.IntegrationFlow; +import org.springframework.integration.dsl.IntegrationFlows; +import org.springframework.messaging.MessageChannel; + +@Configuration +public class Config { + + @Value("${amqp.broker.host}") + private String host; + + @Value("${amqp.broker.port}") + private int port; + + @Value("${amqp.broker.username}") + private String username; + + @Value("${amqp.broker.password}") + private String password; + + @Value("${amqp.exchange.exchange1}") + private String exchange1; + + @Value("${amqp.queue.somequeue}") + private String someQueue; + + @Value("${amqp.queue.somequeue2}") + private String someQueue2; + + @Bean + public ConnectionFactory connectionFactory() { + CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host); + connectionFactory.setUsername(username); + connectionFactory.setPassword(password); + connectionFactory.setPort(port); + return connectionFactory; + } + + @Bean + public AmqpAdmin amqpAdmin() { + return new RabbitAdmin(connectionFactory()); + } + + @Bean + public Declarables qs() { + return new Declarables( + new TopicExchange(exchange1, true, false), + new Queue(someQueue, true, false, false), + new Binding(someQueue, Binding.DestinationType.QUEUE, exchange1, "#", null), + new Queue(someQueue2, true, false, false)); + } + + // consumer + + @Autowired + AmqpMessageHandler amqpMessageHandler; + + @Bean + public IntegrationFlow amqpInFlow1() { + return IntegrationFlows.from(Amqp.inboundGateway(connectionFactory(), someQueue)) + .transform(p -> p + ", received from AMQP") + .handle(amqpMessageHandler::handleMessage1) + .get(); + } + + @Bean + public IntegrationFlow amqpInFlow2() { + return IntegrationFlows.from(Amqp.inboundGateway(connectionFactory(), someQueue2)) + .transform(p -> p + ", received from AMQP") + .handle(amqpMessageHandler::handleMessage2) + .get(); + } + + // publisher + + @Bean + public MessageChannel amqpOutboundChannel() { + return new DirectChannel(); + } + + @Bean + public RabbitTemplate rabbitTemplate() { + RabbitTemplate template = new RabbitTemplate(connectionFactory()); +// template.setMessageConverter(jsonMessageConverter()); + return template; + } + + @Bean + @ServiceActivator(inputChannel = "amqpOutboundChannel") + public AmqpOutboundEndpoint amqpOutbound(AmqpTemplate amqpTemplate) { + AmqpOutboundEndpoint outbound = new AmqpOutboundEndpoint(amqpTemplate); + outbound.setExchangeName(exchange1); + outbound.setRoutingKey("foo"); // default exchange - route to queue 'foo' + return outbound; + } + +} diff --git a/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/Handlers.java b/templates/java-spring/.partials/Handlers.java similarity index 66% rename from templates/java-spring/src/main/java/com/asyncapi/streetlights/service/Handlers.java rename to templates/java-spring/.partials/Handlers.java index bfce9935b..7a1fca6e7 100644 --- a/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/Handlers.java +++ b/templates/java-spring/.partials/Handlers.java @@ -1,6 +1,6 @@ -package com.asyncapi.streetlights.service; +package com.asyncapi.service; -import com.asyncapi.streetlights.infrastructure.Bindings; +import com.asyncapi.infrastructure.Bindings; import org.springframework.cloud.stream.annotation.StreamListener; import org.springframework.stereotype.Component; @@ -10,7 +10,7 @@ public class Handlers { {{#each asyncapi.topics as |topic |}} {{#if topic.publish}} @StreamListener(Bindings.{{javaConst topic.publish.x-operation-id}}) - public void handle{{capFirst topic.publish.x-operation-id}}(String message) { + public void handle{{capitalize topic.publish.x-operation-id}}(String message) { System.out.println("Received: " + message); } {{/if}} diff --git a/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/MessagePublisher.java b/templates/java-spring/.partials/MessagePublisher.java similarity index 51% rename from templates/java-spring/src/main/java/com/asyncapi/streetlights/service/MessagePublisher.java rename to templates/java-spring/.partials/MessagePublisher.java index b30164d4d..e14da94aa 100644 --- a/templates/java-spring/src/main/java/com/asyncapi/streetlights/service/MessagePublisher.java +++ b/templates/java-spring/.partials/MessagePublisher.java @@ -1,6 +1,6 @@ -package com.asyncapi.streetlights.service; +package com.asyncapi.service; -import com.asyncapi.streetlights.infrastructure.Bindings; +import com.asyncapi.infrastructure.Bindings; import org.springframework.messaging.support.MessageBuilder; public class MessagePublisher { @@ -14,8 +14,8 @@ public MessagePublisher(Bindings bindings) { {{#each asyncapi.topics as |topic |}} {{#if topic.subscribe}} - public void send{{capFirst topic.subscribe.x-operation-id}}(String message) { - bindings.output{{capFirst topic.subscribe.x-operation-id}}().send(MessageBuilder.withPayload(message).build()); + public void send{{capitalize topic.subscribe.x-operation-id}}(String message) { + bindings.output{{capitalize topic.subscribe.x-operation-id}}().send(MessageBuilder.withPayload(message).build()); } {{/if}} {{/each}} diff --git a/templates/java-spring/.partials/MqttConfig.java b/templates/java-spring/.partials/MqttConfig.java new file mode 100644 index 000000000..76e9aeda2 --- /dev/null +++ b/templates/java-spring/.partials/MqttConfig.java @@ -0,0 +1,107 @@ +package com.asyncapi.infrastructure; + +import com.asyncapi.service.MqttMessageHandler; +import org.eclipse.paho.client.mqttv3.MqttConnectOptions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.integration.annotation.ServiceActivator; +import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.dsl.IntegrationFlow; +import org.springframework.integration.dsl.IntegrationFlows; +import org.springframework.integration.endpoint.MessageProducerSupport; +import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory; +import org.springframework.integration.mqtt.core.MqttPahoClientFactory; +import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter; +import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler; +import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.MessageHandler; +import org.springframework.util.StringUtils; + +@Configuration +public class Config { + + @Value("${mqtt.broker.host}") + private String host; + + @Value("${mqtt.broker.port}") + private int port; + + @Value("${mqtt.broker.username}") + private String username; + + @Value("${mqtt.broker.password}") + private String password; + + {{#each asyncapi.topics as |topic key|}} + {{#if topic.subscribe}} + @Value("${mqtt.topic.{{~topic.x-service-name~}}Topic}") + private String {{topic.x-service-name}}Topic; + + {{/if}} + {{/each}} + + @Bean + public MqttPahoClientFactory mqttClientFactory() { + DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory(); + MqttConnectOptions options = new MqttConnectOptions(); + options.setServerURIs(new String[] { host + ":" + port }); + if (!StringUtils.isEmpty(username)) { + options.setUserName(username); + } + if (!StringUtils.isEmpty(password)) { + options.setPassword(password.toCharArray()); + } + factory.setConnectionOptions(options); + return factory; + } + + // consumer + + @Autowired + MqttMessageHandler mqttMessageHandler; + {{#each asyncapi.topics as |topic key|}} + + {{#if topic.subscribe}} + @Bean + public IntegrationFlow {{camelCase topic.x-service-name}}Flow() { + return IntegrationFlows.from({{camelCase topic.x-service-name}}Inbound()) + .transform(p -> p + ", received from MQTT") + .handle(mqttMessageHandler::handle{{upperFirst topic.x-service-name}}) + .get(); + } + + @Bean + public MessageProducerSupport {{camelCase topic.x-service-name}}Inbound() { + MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter("{{camelCase topic.x-service-name}}Subscriber", + mqttClientFactory(), {{topic.x-service-name}}Topic); + adapter.setCompletionTimeout(5000); + adapter.setConverter(new DefaultPahoMessageConverter()); + return adapter; + } + {{/if}} + {{/each}} + + // publisher + {{#each asyncapi.topics as |topic key|}} + + {{#if topic.publish}} + @Bean + public MessageChannel {{camelCase topic.x-service-name}}OutboundChannel() { + return new DirectChannel(); + } + + @Bean + @ServiceActivator(inputChannel = "{{camelCase topic.x-service-name}}OutboundChannel") + public MessageHandler {{camelCase topic.x-service-name}}Outbound() { + MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler("{{camelCase topic.x-service-name}}Publisher", mqttClientFactory()); + messageHandler.setAsync(true); + messageHandler.setDefaultTopic({{topic.x-service-name}}Topic); + return messageHandler; + } + {{/if}} + {{/each}} + +} diff --git a/templates/java-spring/build.gradle b/templates/java-spring/build.gradle index 8f404c877..10854b5c1 100644 --- a/templates/java-spring/build.gradle +++ b/templates/java-spring/build.gradle @@ -21,24 +21,13 @@ sourceCompatibility = 1.8 repositories { mavenCentral() - maven { url "https://repo.spring.io/milestone" } } -ext { - springCloudVersion = 'Greenwich.M1' -} - dependencies { - implementation('org.springframework.boot:spring-boot-starter-amqp') - implementation('org.springframework.cloud:spring-cloud-stream') - implementation('org.springframework.cloud:spring-cloud-stream-binder-rabbit') - testImplementation('org.springframework.boot:spring-boot-starter-test') - testImplementation('org.springframework.cloud:spring-cloud-stream-test-support') -} -dependencyManagement { - imports { - mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" - } + implementation('org.springframework.boot:spring-boot-starter-integration') + implementation('org.springframework.integration:spring-integration-mqtt') + implementation('org.springframework.integration:spring-integration-amqp') + testImplementation('org.springframework.boot:spring-boot-starter-test') } diff --git a/templates/java-spring/settings.gradle b/templates/java-spring/settings.gradle index 80a6e73f5..a218266d5 100644 --- a/templates/java-spring/settings.gradle +++ b/templates/java-spring/settings.gradle @@ -1 +1 @@ -rootProject.name = '{{asyncapi.info.x-project-name}}' +rootProject.name = '{{asyncapi.info.title}}' diff --git a/templates/java-spring/src/main/java/com/asyncapi/Application.java b/templates/java-spring/src/main/java/com/asyncapi/Application.java new file mode 100644 index 000000000..0512d3de1 --- /dev/null +++ b/templates/java-spring/src/main/java/com/asyncapi/Application.java @@ -0,0 +1,13 @@ +package com.asyncapi; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/templates/java-spring/src/main/java/com/asyncapi/infrastructure/Config.java b/templates/java-spring/src/main/java/com/asyncapi/infrastructure/Config.java new file mode 100644 index 000000000..78ed37f82 --- /dev/null +++ b/templates/java-spring/src/main/java/com/asyncapi/infrastructure/Config.java @@ -0,0 +1,8 @@ +{{#each asyncapi.servers}} + {{#compare this.scheme '===' 'amqp'}} +{{> amqpConfig asyncapi=../../asyncapi}} + {{/compare}} + {{#compare this.scheme '===' 'mqtt'}} +{{> mqttConfig asyncapi=../../asyncapi }} + {{/compare}} +{{/each}} diff --git a/templates/java-spring/src/main/java/com/asyncapi/service/MqttCommandLine.java b/templates/java-spring/src/main/java/com/asyncapi/service/MqttCommandLine.java new file mode 100644 index 000000000..ebb088aee --- /dev/null +++ b/templates/java-spring/src/main/java/com/asyncapi/service/MqttCommandLine.java @@ -0,0 +1,25 @@ +package com.asyncapi.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +@Component +public class MqttCommandLine implements CommandLineRunner { + + @Autowired + MqttMyGateway myGateway; + + @Override + public void run(String... args) { + System.out.println("******* MQTT Sending message: *******"); + + {{#each asyncapi.topics as |topic key|}} + {{#if topic.publish}} + myGateway.{{camelCase topic.publish.x-operation-id}}("Hello World from {{topic.publish.x-operation-id}}"); + + {{/if}} + {{/each}} + System.out.println("MQTT Sent: Hello World"); + } +} diff --git a/templates/java-spring/src/main/java/com/asyncapi/service/MqttMessageHandler.java b/templates/java-spring/src/main/java/com/asyncapi/service/MqttMessageHandler.java new file mode 100644 index 000000000..e02098540 --- /dev/null +++ b/templates/java-spring/src/main/java/com/asyncapi/service/MqttMessageHandler.java @@ -0,0 +1,19 @@ +package com.asyncapi.service; + +import org.springframework.messaging.Message; +import org.springframework.stereotype.Service; + +@Service +public class MqttMessageHandler { + +{{#each asyncapi.topics as |topic |}} + {{#if topic.subscribe}} + public void handle{{upperFirst topic.x-service-name}}(Message message) { + System.out.println("MQTT handler {{topic.x-service-name}}"); + System.out.println(message.getPayload()); + } + {{/if}} + +{{/each}} + +} diff --git a/templates/java-spring/src/main/java/com/asyncapi/service/MqttMyGateway.java b/templates/java-spring/src/main/java/com/asyncapi/service/MqttMyGateway.java new file mode 100644 index 000000000..3a5e65c72 --- /dev/null +++ b/templates/java-spring/src/main/java/com/asyncapi/service/MqttMyGateway.java @@ -0,0 +1,16 @@ +package com.asyncapi.service; + +import org.springframework.integration.annotation.Gateway; +import org.springframework.integration.annotation.MessagingGateway; + +@MessagingGateway +public interface MqttMyGateway { + + {{#each asyncapi.topics as |topic key|}} + {{#if topic.publish}} + + @Gateway(requestChannel = "{{camelCase topic.x-service-name}}OutboundChannel") + void {{camelCase topic.publish.x-operation-id}}(String data); + {{/if}} + {{/each}} +} diff --git a/templates/java-spring/src/main/java/com/asyncapi/streetlights/StreetlightsApplication.java b/templates/java-spring/src/main/java/com/asyncapi/streetlights/StreetlightsApplication.java deleted file mode 100644 index f38359df2..000000000 --- a/templates/java-spring/src/main/java/com/asyncapi/streetlights/StreetlightsApplication.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.asyncapi.streetlights; - -import com.asyncapi.streetlights.infrastructure.Bindings; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.stream.annotation.EnableBinding; - -@SpringBootApplication -@EnableBinding(Bindings.class) -public class StreetlightsApplication { - - public static void main(String[] args) { - SpringApplication.run(StreetlightsApplication.class, args); - } - -} diff --git a/templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java b/templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java deleted file mode 100644 index c3e33d2e7..000000000 --- a/templates/java-spring/src/main/java/com/asyncapi/streetlights/infrastructure/Bindings.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.asyncapi.streetlights.infrastructure; - -import org.springframework.cloud.stream.annotation.Input; -import org.springframework.cloud.stream.annotation.Output; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.SubscribableChannel; - -public interface Bindings { - {{#each asyncapi.topics as |topic |}} - {{#if topic.publish}} - String {{javaConst topic.publish.x-operation-id}} = "input{{capFirst topic.publish.x-operation-id}}"; - {{/if}} - {{#if topic.subscribe}} - String {{javaConst topic.subscribe.x-operation-id}} = "output{{capFirst topic.subscribe.x-operation-id}}"; - {{/if}} - {{/each}} - {{#each asyncapi.topics as |topic |}} - {{#if topic.publish}} - - @Input(Bindings.{{javaConst topic.publish.x-operation-id}}) - SubscribableChannel input{{capFirst topic.publish.x-operation-id}}(); - {{/if}} - {{#if topic.subscribe}} - - @Output(Bindings.{{javaConst topic.subscribe.x-operation-id}}) - MessageChannel output{{capFirst topic.subscribe.x-operation-id}}(); - {{/if}} - {{/each}} -} diff --git a/templates/java-spring/src/main/resources/application.yml b/templates/java-spring/src/main/resources/application.yml index 796b34850..b884b638e 100644 --- a/templates/java-spring/src/main/resources/application.yml +++ b/templates/java-spring/src/main/resources/application.yml @@ -1,3 +1,27 @@ -spring: - rabbitmq: +{{#each asyncapi.servers as |server|}} + {{#compare server.scheme '===' 'amqp'}} +amqp: + broker: + host: localhost port: 32771 + username: guest + password: guest + exchange: + exchange1: exchange-1 + queue: + somequeue: some.queue + somequeue2: some.queue2 + {{/compare}} + {{#compare server.scheme '===' 'mqtt'}} +mqtt: + broker: + host: tcp://{{server.url}} + port: {{server.variables.port.default}} + username: + password: + topic: +{{#each ../../asyncapi.topics as |topic key|}} + {{topic.x-service-name}}Topic: {{key}} +{{/each}} + {{/compare}} +{{/each}} diff --git a/templates/java-spring/src/test/java/com/asyncapi/streetlights/StreetlightsApplicationTests.java b/templates/java-spring/src/test/java/com/asyncapi/ApplicationTests.java similarity index 77% rename from templates/java-spring/src/test/java/com/asyncapi/streetlights/StreetlightsApplicationTests.java rename to templates/java-spring/src/test/java/com/asyncapi/ApplicationTests.java index 300fb5401..a98fe4fe1 100644 --- a/templates/java-spring/src/test/java/com/asyncapi/streetlights/StreetlightsApplicationTests.java +++ b/templates/java-spring/src/test/java/com/asyncapi/ApplicationTests.java @@ -1,4 +1,4 @@ -package com.asyncapi.streetlights; +package com.asyncapi; import org.junit.Test; import org.junit.runner.RunWith; @@ -7,7 +7,7 @@ @RunWith(SpringRunner.class) @SpringBootTest -public class StreetlightsApplicationTests { +public class ApplicationTests { @Test public void contextLoads() { From e01f7418d7b7945d31de648b08724b58fba56c70 Mon Sep 17 00:00:00 2001 From: Raisel Melian Date: Thu, 15 Nov 2018 10:03:50 -0500 Subject: [PATCH 07/14] refactor services names --- templates/java-spring/.partials/Handlers.java | 19 --------------- .../.partials/MessagePublisher.java | 23 ------------------- .../MqttCommandLinePublisher.java} | 6 ++--- .../java-spring/.partials/MqttConfig.java | 14 +++++------ .../MqttMessageHandlerService.java} | 2 +- .../MqttPublisherService.java} | 4 ++-- .../service/CommandLinePublisher.java | 8 +++++++ .../service/MessageHandlerService.java | 8 +++++++ .../asyncapi/service/PublisherService.java | 8 +++++++ 9 files changed, 37 insertions(+), 55 deletions(-) delete mode 100644 templates/java-spring/.partials/Handlers.java delete mode 100644 templates/java-spring/.partials/MessagePublisher.java rename templates/java-spring/{src/main/java/com/asyncapi/service/MqttCommandLine.java => .partials/MqttCommandLinePublisher.java} (69%) rename templates/java-spring/{src/main/java/com/asyncapi/service/MqttMessageHandler.java => .partials/MqttMessageHandlerService.java} (92%) rename templates/java-spring/{src/main/java/com/asyncapi/service/MqttMyGateway.java => .partials/MqttPublisherService.java} (91%) create mode 100644 templates/java-spring/src/main/java/com/asyncapi/service/CommandLinePublisher.java create mode 100644 templates/java-spring/src/main/java/com/asyncapi/service/MessageHandlerService.java create mode 100644 templates/java-spring/src/main/java/com/asyncapi/service/PublisherService.java diff --git a/templates/java-spring/.partials/Handlers.java b/templates/java-spring/.partials/Handlers.java deleted file mode 100644 index 7a1fca6e7..000000000 --- a/templates/java-spring/.partials/Handlers.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.asyncapi.service; - -import com.asyncapi.infrastructure.Bindings; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.stereotype.Component; - -@Component -public class Handlers { - -{{#each asyncapi.topics as |topic |}} - {{#if topic.publish}} - @StreamListener(Bindings.{{javaConst topic.publish.x-operation-id}}) - public void handle{{capitalize topic.publish.x-operation-id}}(String message) { - System.out.println("Received: " + message); - } -{{/if}} -{{/each}} - -} diff --git a/templates/java-spring/.partials/MessagePublisher.java b/templates/java-spring/.partials/MessagePublisher.java deleted file mode 100644 index e14da94aa..000000000 --- a/templates/java-spring/.partials/MessagePublisher.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.asyncapi.service; - -import com.asyncapi.infrastructure.Bindings; -import org.springframework.messaging.support.MessageBuilder; - -public class MessagePublisher { - - private final Bindings bindings; - - - public MessagePublisher(Bindings bindings) { - this.bindings = bindings; - } - - {{#each asyncapi.topics as |topic |}} - {{#if topic.subscribe}} - public void send{{capitalize topic.subscribe.x-operation-id}}(String message) { - bindings.output{{capitalize topic.subscribe.x-operation-id}}().send(MessageBuilder.withPayload(message).build()); - } - {{/if}} - {{/each}} - -} diff --git a/templates/java-spring/src/main/java/com/asyncapi/service/MqttCommandLine.java b/templates/java-spring/.partials/MqttCommandLinePublisher.java similarity index 69% rename from templates/java-spring/src/main/java/com/asyncapi/service/MqttCommandLine.java rename to templates/java-spring/.partials/MqttCommandLinePublisher.java index ebb088aee..a7e82f8c2 100644 --- a/templates/java-spring/src/main/java/com/asyncapi/service/MqttCommandLine.java +++ b/templates/java-spring/.partials/MqttCommandLinePublisher.java @@ -5,10 +5,10 @@ import org.springframework.stereotype.Component; @Component -public class MqttCommandLine implements CommandLineRunner { +public class CommandLinePublisher implements CommandLineRunner { @Autowired - MqttMyGateway myGateway; + PublisherService publisherService; @Override public void run(String... args) { @@ -16,7 +16,7 @@ public void run(String... args) { {{#each asyncapi.topics as |topic key|}} {{#if topic.publish}} - myGateway.{{camelCase topic.publish.x-operation-id}}("Hello World from {{topic.publish.x-operation-id}}"); + publisherService.{{camelCase topic.publish.x-operation-id}}("Hello World from {{topic.publish.x-operation-id}}"); {{/if}} {{/each}} diff --git a/templates/java-spring/.partials/MqttConfig.java b/templates/java-spring/.partials/MqttConfig.java index 76e9aeda2..a8c917917 100644 --- a/templates/java-spring/.partials/MqttConfig.java +++ b/templates/java-spring/.partials/MqttConfig.java @@ -1,6 +1,6 @@ package com.asyncapi.infrastructure; -import com.asyncapi.service.MqttMessageHandler; +import com.asyncapi.service.MessageHandlerService; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -61,7 +61,7 @@ public MqttPahoClientFactory mqttClientFactory() { // consumer @Autowired - MqttMessageHandler mqttMessageHandler; + MessageHandlerService messageHandlerService; {{#each asyncapi.topics as |topic key|}} {{#if topic.subscribe}} @@ -69,7 +69,7 @@ public MqttPahoClientFactory mqttClientFactory() { public IntegrationFlow {{camelCase topic.x-service-name}}Flow() { return IntegrationFlows.from({{camelCase topic.x-service-name}}Inbound()) .transform(p -> p + ", received from MQTT") - .handle(mqttMessageHandler::handle{{upperFirst topic.x-service-name}}) + .handle(messageHandlerService::handle{{upperFirst topic.x-service-name}}) .get(); } @@ -96,10 +96,10 @@ public MqttPahoClientFactory mqttClientFactory() { @Bean @ServiceActivator(inputChannel = "{{camelCase topic.x-service-name}}OutboundChannel") public MessageHandler {{camelCase topic.x-service-name}}Outbound() { - MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler("{{camelCase topic.x-service-name}}Publisher", mqttClientFactory()); - messageHandler.setAsync(true); - messageHandler.setDefaultTopic({{topic.x-service-name}}Topic); - return messageHandler; + MqttPahoMessageHandler pahoMessageHandler = new MqttPahoMessageHandler("{{camelCase topic.x-service-name}}Publisher", mqttClientFactory()); + pahoMessageHandler.setAsync(true); + pahoMessageHandler.setDefaultTopic({{topic.x-service-name}}Topic); + return pahoMessageHandler; } {{/if}} {{/each}} diff --git a/templates/java-spring/src/main/java/com/asyncapi/service/MqttMessageHandler.java b/templates/java-spring/.partials/MqttMessageHandlerService.java similarity index 92% rename from templates/java-spring/src/main/java/com/asyncapi/service/MqttMessageHandler.java rename to templates/java-spring/.partials/MqttMessageHandlerService.java index e02098540..58bdd9ce9 100644 --- a/templates/java-spring/src/main/java/com/asyncapi/service/MqttMessageHandler.java +++ b/templates/java-spring/.partials/MqttMessageHandlerService.java @@ -4,7 +4,7 @@ import org.springframework.stereotype.Service; @Service -public class MqttMessageHandler { +public class MessageHandlerService { {{#each asyncapi.topics as |topic |}} {{#if topic.subscribe}} diff --git a/templates/java-spring/src/main/java/com/asyncapi/service/MqttMyGateway.java b/templates/java-spring/.partials/MqttPublisherService.java similarity index 91% rename from templates/java-spring/src/main/java/com/asyncapi/service/MqttMyGateway.java rename to templates/java-spring/.partials/MqttPublisherService.java index 3a5e65c72..6341bf6ce 100644 --- a/templates/java-spring/src/main/java/com/asyncapi/service/MqttMyGateway.java +++ b/templates/java-spring/.partials/MqttPublisherService.java @@ -4,11 +4,11 @@ import org.springframework.integration.annotation.MessagingGateway; @MessagingGateway -public interface MqttMyGateway { +public interface PublisherService { {{#each asyncapi.topics as |topic key|}} {{#if topic.publish}} - + @Gateway(requestChannel = "{{camelCase topic.x-service-name}}OutboundChannel") void {{camelCase topic.publish.x-operation-id}}(String data); {{/if}} diff --git a/templates/java-spring/src/main/java/com/asyncapi/service/CommandLinePublisher.java b/templates/java-spring/src/main/java/com/asyncapi/service/CommandLinePublisher.java new file mode 100644 index 000000000..d44978cb2 --- /dev/null +++ b/templates/java-spring/src/main/java/com/asyncapi/service/CommandLinePublisher.java @@ -0,0 +1,8 @@ +{{#each asyncapi.servers}} + {{#compare this.scheme '===' 'amqp'}} +{{> amqpCommandLinePublisher asyncapi=../../asyncapi}} + {{/compare}} + {{#compare this.scheme '===' 'mqtt'}} +{{> mqttCommandLinePublisher asyncapi=../../asyncapi }} + {{/compare}} +{{/each}} diff --git a/templates/java-spring/src/main/java/com/asyncapi/service/MessageHandlerService.java b/templates/java-spring/src/main/java/com/asyncapi/service/MessageHandlerService.java new file mode 100644 index 000000000..35eb7cd01 --- /dev/null +++ b/templates/java-spring/src/main/java/com/asyncapi/service/MessageHandlerService.java @@ -0,0 +1,8 @@ +{{#each asyncapi.servers}} + {{#compare this.scheme '===' 'amqp'}} +{{> amqpMessageHandlerService asyncapi=../../asyncapi}} + {{/compare}} + {{#compare this.scheme '===' 'mqtt'}} +{{> mqttMessageHandlerService asyncapi=../../asyncapi }} + {{/compare}} +{{/each}} diff --git a/templates/java-spring/src/main/java/com/asyncapi/service/PublisherService.java b/templates/java-spring/src/main/java/com/asyncapi/service/PublisherService.java new file mode 100644 index 000000000..48b831711 --- /dev/null +++ b/templates/java-spring/src/main/java/com/asyncapi/service/PublisherService.java @@ -0,0 +1,8 @@ +{{#each asyncapi.servers}} + {{#compare this.scheme '===' 'amqp'}} +{{> amqpPublisherService asyncapi=../../asyncapi}} + {{/compare}} + {{#compare this.scheme '===' 'mqtt'}} +{{> mqttPublisherService asyncapi=../../asyncapi }} + {{/compare}} +{{/each}} From c590e273a78224c5ae8d9c08087f00384690b33b Mon Sep 17 00:00:00 2001 From: Raisel Melian Date: Thu, 15 Nov 2018 10:07:19 -0500 Subject: [PATCH 08/14] remove logs --- lib/generator.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/generator.js b/lib/generator.js index 0921c7f42..6bdea16dc 100644 --- a/lib/generator.js +++ b/lib/generator.js @@ -8,7 +8,6 @@ const xfs = require('fs.extra'); const beautifier = require('./beautifier'); const registerPartial = require('./register-partial'); const parse = require('./parser'); -const util = require('util'); const generator = module.exports; @@ -237,9 +236,6 @@ const registerHelpers = config => new Promise((resolve, reject) => { */ const registerPartials = config => new Promise((resolve, reject) => { const partials_dir = path.resolve(config.templates, PARTIALS_DIRNAME); - console.log("===================") - console.log(util.inspect(config, {showHidden: false, depth: null})) - console.log("===================") if (!fs.existsSync(partials_dir)) return resolve(); const walker = xfs.walk(partials_dir, { From 29deba576f049e06f6711e1e7455ebf645133c1b Mon Sep 17 00:00:00 2001 From: Raisel Melian Date: Thu, 15 Nov 2018 10:07:53 -0500 Subject: [PATCH 09/14] put line space back --- lib/generator.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/generator.js b/lib/generator.js index 6bdea16dc..fdbc48813 100644 --- a/lib/generator.js +++ b/lib/generator.js @@ -236,6 +236,7 @@ const registerHelpers = config => new Promise((resolve, reject) => { */ const registerPartials = config => new Promise((resolve, reject) => { const partials_dir = path.resolve(config.templates, PARTIALS_DIRNAME); + if (!fs.existsSync(partials_dir)) return resolve(); const walker = xfs.walk(partials_dir, { From d00566897b17a76d783068255908ea84e8a10f62 Mon Sep 17 00:00:00 2001 From: Raisel Melian Date: Thu, 15 Nov 2018 12:52:50 -0500 Subject: [PATCH 10/14] add support for AMQP --- .../java-spring/.partials/AmqpConfig.java | 90 +++++++++++-------- .../.partials/MqttCommandLinePublisher.java | 25 ------ .../java-spring/.partials/MqttConfig.java | 1 - .../.partials/MqttMessageHandlerService.java | 19 ---- .../service/CommandLinePublisher.java | 33 +++++-- .../service/MessageHandlerService.java | 25 ++++-- .../asyncapi/service/PublisherService.java | 24 +++-- .../src/main/resources/application.yml | 13 ++- 8 files changed, 122 insertions(+), 108 deletions(-) delete mode 100644 templates/java-spring/.partials/MqttCommandLinePublisher.java delete mode 100644 templates/java-spring/.partials/MqttMessageHandlerService.java diff --git a/templates/java-spring/.partials/AmqpConfig.java b/templates/java-spring/.partials/AmqpConfig.java index 0e93a64de..b96f03270 100644 --- a/templates/java-spring/.partials/AmqpConfig.java +++ b/templates/java-spring/.partials/AmqpConfig.java @@ -1,6 +1,6 @@ -package com.asyncapi.streetlights.infrastructure; +package com.asyncapi.infrastructure; -import com.asyncapi.streetlights.service.AmqpMessageHandler; +import com.asyncapi.service.MessageHandlerService; import org.springframework.amqp.core.*; import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; import org.springframework.amqp.rabbit.connection.ConnectionFactory; @@ -33,14 +33,20 @@ public class Config { @Value("${amqp.broker.password}") private String password; - @Value("${amqp.exchange.exchange1}") - private String exchange1; + {{#each asyncapi.topics as |topic key|}} + {{#if topic.subscribe}} + @Value("${amqp.exchange.{{~topic.x-service-name~}}}") + private String {{topic.x-service-name}}Exchange; - @Value("${amqp.queue.somequeue}") - private String someQueue; + {{/if}} + {{/each}} + {{#each asyncapi.topics as |topic key|}} + {{#if topic.subscribe}} + @Value("${amqp.queue.{{~topic.x-service-name~}}}") + private String {{topic.x-service-name}}Queue; - @Value("${amqp.queue.somequeue2}") - private String someQueue2; + {{/if}} + {{/each}} @Bean public ConnectionFactory connectionFactory() { @@ -57,56 +63,66 @@ public AmqpAdmin amqpAdmin() { } @Bean - public Declarables qs() { + public Declarables exchanges() { return new Declarables( - new TopicExchange(exchange1, true, false), - new Queue(someQueue, true, false, false), - new Binding(someQueue, Binding.DestinationType.QUEUE, exchange1, "#", null), - new Queue(someQueue2, true, false, false)); + {{#each asyncapi.topics as |topic key|}} + {{#if topic.publish}} + new TopicExchange({{topic.x-service-name}}Exchange, true, false){{#unless @last}},{{/unless}} + {{/if}} + {{/each}} + ); + } + + @Bean + public Declarables queues() { + return new Declarables( + {{#each asyncapi.topics as |topic key|}} + {{#if topic.subscribe}} + new Queue({{topic.x-service-name}}Queue, true, false, false){{#unless @last}},{{/unless}} + {{/if}} + {{/each}} + ); } // consumer @Autowired - AmqpMessageHandler amqpMessageHandler; + MessageHandlerService messageHandlerService; + {{#each asyncapi.topics as |topic key|}} + {{#if topic.subscribe}} @Bean - public IntegrationFlow amqpInFlow1() { - return IntegrationFlows.from(Amqp.inboundGateway(connectionFactory(), someQueue)) - .transform(p -> p + ", received from AMQP") - .handle(amqpMessageHandler::handleMessage1) - .get(); - } - - @Bean - public IntegrationFlow amqpInFlow2() { - return IntegrationFlows.from(Amqp.inboundGateway(connectionFactory(), someQueue2)) - .transform(p -> p + ", received from AMQP") - .handle(amqpMessageHandler::handleMessage2) + public IntegrationFlow {{camelCase topic.x-service-name}}Flow() { + return IntegrationFlows.from(Amqp.inboundGateway(connectionFactory(), {{topic.x-service-name}}Queue)) + .handle(messageHandlerService::handle{{upperFirst topic.x-service-name}}) .get(); } + {{/if}} + {{/each}} // publisher - @Bean - public MessageChannel amqpOutboundChannel() { - return new DirectChannel(); - } - @Bean public RabbitTemplate rabbitTemplate() { RabbitTemplate template = new RabbitTemplate(connectionFactory()); -// template.setMessageConverter(jsonMessageConverter()); return template; } + {{#each asyncapi.topics as |topic key|}} + + {{#if topic.publish}} + @Bean + public MessageChannel {{camelCase topic.x-service-name}}OutboundChannel() { + return new DirectChannel(); + } @Bean - @ServiceActivator(inputChannel = "amqpOutboundChannel") - public AmqpOutboundEndpoint amqpOutbound(AmqpTemplate amqpTemplate) { + @ServiceActivator(inputChannel = "{{camelCase topic.x-service-name}}OutboundChannel") + public AmqpOutboundEndpoint {{camelCase topic.x-service-name}}Outbound(AmqpTemplate amqpTemplate) { AmqpOutboundEndpoint outbound = new AmqpOutboundEndpoint(amqpTemplate); - outbound.setExchangeName(exchange1); - outbound.setRoutingKey("foo"); // default exchange - route to queue 'foo' + outbound.setExchangeName({{topic.x-service-name}}Exchange); + outbound.setRoutingKey("#"); return outbound; } - + {{/if}} + {{/each}} } diff --git a/templates/java-spring/.partials/MqttCommandLinePublisher.java b/templates/java-spring/.partials/MqttCommandLinePublisher.java deleted file mode 100644 index a7e82f8c2..000000000 --- a/templates/java-spring/.partials/MqttCommandLinePublisher.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.asyncapi.service; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.CommandLineRunner; -import org.springframework.stereotype.Component; - -@Component -public class CommandLinePublisher implements CommandLineRunner { - - @Autowired - PublisherService publisherService; - - @Override - public void run(String... args) { - System.out.println("******* MQTT Sending message: *******"); - - {{#each asyncapi.topics as |topic key|}} - {{#if topic.publish}} - publisherService.{{camelCase topic.publish.x-operation-id}}("Hello World from {{topic.publish.x-operation-id}}"); - - {{/if}} - {{/each}} - System.out.println("MQTT Sent: Hello World"); - } -} diff --git a/templates/java-spring/.partials/MqttConfig.java b/templates/java-spring/.partials/MqttConfig.java index a8c917917..a7cd58496 100644 --- a/templates/java-spring/.partials/MqttConfig.java +++ b/templates/java-spring/.partials/MqttConfig.java @@ -68,7 +68,6 @@ public MqttPahoClientFactory mqttClientFactory() { @Bean public IntegrationFlow {{camelCase topic.x-service-name}}Flow() { return IntegrationFlows.from({{camelCase topic.x-service-name}}Inbound()) - .transform(p -> p + ", received from MQTT") .handle(messageHandlerService::handle{{upperFirst topic.x-service-name}}) .get(); } diff --git a/templates/java-spring/.partials/MqttMessageHandlerService.java b/templates/java-spring/.partials/MqttMessageHandlerService.java deleted file mode 100644 index 58bdd9ce9..000000000 --- a/templates/java-spring/.partials/MqttMessageHandlerService.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.asyncapi.service; - -import org.springframework.messaging.Message; -import org.springframework.stereotype.Service; - -@Service -public class MessageHandlerService { - -{{#each asyncapi.topics as |topic |}} - {{#if topic.subscribe}} - public void handle{{upperFirst topic.x-service-name}}(Message message) { - System.out.println("MQTT handler {{topic.x-service-name}}"); - System.out.println(message.getPayload()); - } - {{/if}} - -{{/each}} - -} diff --git a/templates/java-spring/src/main/java/com/asyncapi/service/CommandLinePublisher.java b/templates/java-spring/src/main/java/com/asyncapi/service/CommandLinePublisher.java index d44978cb2..f3083db95 100644 --- a/templates/java-spring/src/main/java/com/asyncapi/service/CommandLinePublisher.java +++ b/templates/java-spring/src/main/java/com/asyncapi/service/CommandLinePublisher.java @@ -1,8 +1,25 @@ -{{#each asyncapi.servers}} - {{#compare this.scheme '===' 'amqp'}} -{{> amqpCommandLinePublisher asyncapi=../../asyncapi}} - {{/compare}} - {{#compare this.scheme '===' 'mqtt'}} -{{> mqttCommandLinePublisher asyncapi=../../asyncapi }} - {{/compare}} -{{/each}} +package com.asyncapi.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +@Component +public class CommandLinePublisher implements CommandLineRunner { + + @Autowired + PublisherService publisherService; + + @Override + public void run(String... args) { + System.out.println("******* Sending message: *******"); + + {{#each asyncapi.topics as |topic key|}} + {{#if topic.publish}} + publisherService.{{camelCase topic.publish.x-operation-id}}("Hello World from {{topic.publish.x-operation-id}}"); + + {{/if}} + {{/each}} + System.out.println("Message sent"); + } +} diff --git a/templates/java-spring/src/main/java/com/asyncapi/service/MessageHandlerService.java b/templates/java-spring/src/main/java/com/asyncapi/service/MessageHandlerService.java index 35eb7cd01..2d84210ee 100644 --- a/templates/java-spring/src/main/java/com/asyncapi/service/MessageHandlerService.java +++ b/templates/java-spring/src/main/java/com/asyncapi/service/MessageHandlerService.java @@ -1,8 +1,19 @@ -{{#each asyncapi.servers}} - {{#compare this.scheme '===' 'amqp'}} -{{> amqpMessageHandlerService asyncapi=../../asyncapi}} - {{/compare}} - {{#compare this.scheme '===' 'mqtt'}} -{{> mqttMessageHandlerService asyncapi=../../asyncapi }} - {{/compare}} +package com.asyncapi.service; + +import org.springframework.messaging.Message; +import org.springframework.stereotype.Service; + +@Service +public class MessageHandlerService { + +{{#each asyncapi.topics as |topic |}} + {{#if topic.subscribe}} + public void handle{{upperFirst topic.x-service-name}}(Message message) { + System.out.println("handler {{topic.x-service-name}}"); + System.out.println(message.getPayload()); + } + {{/if}} + {{/each}} + +} diff --git a/templates/java-spring/src/main/java/com/asyncapi/service/PublisherService.java b/templates/java-spring/src/main/java/com/asyncapi/service/PublisherService.java index 48b831711..6341bf6ce 100644 --- a/templates/java-spring/src/main/java/com/asyncapi/service/PublisherService.java +++ b/templates/java-spring/src/main/java/com/asyncapi/service/PublisherService.java @@ -1,8 +1,16 @@ -{{#each asyncapi.servers}} - {{#compare this.scheme '===' 'amqp'}} -{{> amqpPublisherService asyncapi=../../asyncapi}} - {{/compare}} - {{#compare this.scheme '===' 'mqtt'}} -{{> mqttPublisherService asyncapi=../../asyncapi }} - {{/compare}} -{{/each}} +package com.asyncapi.service; + +import org.springframework.integration.annotation.Gateway; +import org.springframework.integration.annotation.MessagingGateway; + +@MessagingGateway +public interface PublisherService { + + {{#each asyncapi.topics as |topic key|}} + {{#if topic.publish}} + + @Gateway(requestChannel = "{{camelCase topic.x-service-name}}OutboundChannel") + void {{camelCase topic.publish.x-operation-id}}(String data); + {{/if}} + {{/each}} +} diff --git a/templates/java-spring/src/main/resources/application.yml b/templates/java-spring/src/main/resources/application.yml index b884b638e..1f733a55d 100644 --- a/templates/java-spring/src/main/resources/application.yml +++ b/templates/java-spring/src/main/resources/application.yml @@ -7,10 +7,17 @@ amqp: username: guest password: guest exchange: - exchange1: exchange-1 +{{#each ../../asyncapi.topics as |topic key|}} + {{#if topic.publish}} + {{topic.x-service-name}}: {{key}} + {{/if}} +{{/each}} queue: - somequeue: some.queue - somequeue2: some.queue2 +{{#each ../../asyncapi.topics as |topic key|}} + {{#if topic.subscribe}} + {{topic.x-service-name}}: {{key}} + {{/if}} +{{/each}} {{/compare}} {{#compare server.scheme '===' 'mqtt'}} mqtt: From 74e6781d06ee3987f6e2ac659d74649ad2dbcb84 Mon Sep 17 00:00:00 2001 From: Raisel Melian Date: Thu, 15 Nov 2018 15:49:42 -0500 Subject: [PATCH 11/14] remove unused partial --- .../.partials/MqttPublisherService.java | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 templates/java-spring/.partials/MqttPublisherService.java diff --git a/templates/java-spring/.partials/MqttPublisherService.java b/templates/java-spring/.partials/MqttPublisherService.java deleted file mode 100644 index 6341bf6ce..000000000 --- a/templates/java-spring/.partials/MqttPublisherService.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.asyncapi.service; - -import org.springframework.integration.annotation.Gateway; -import org.springframework.integration.annotation.MessagingGateway; - -@MessagingGateway -public interface PublisherService { - - {{#each asyncapi.topics as |topic key|}} - {{#if topic.publish}} - - @Gateway(requestChannel = "{{camelCase topic.x-service-name}}OutboundChannel") - void {{camelCase topic.publish.x-operation-id}}(String data); - {{/if}} - {{/each}} -} From 6330cb03bef98ec3f01201d88454cebd9870bf68 Mon Sep 17 00:00:00 2001 From: Raisel Melian Date: Sun, 18 Nov 2018 16:59:26 -0500 Subject: [PATCH 12/14] #18 readme, removing x-operation-id usage --- templates/java-spring/README.md | 96 +++++++++++++++++++ .../service/CommandLinePublisher.java | 2 +- .../asyncapi/service/PublisherService.java | 2 +- 3 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 templates/java-spring/README.md diff --git a/templates/java-spring/README.md b/templates/java-spring/README.md new file mode 100644 index 000000000..40bd872c8 --- /dev/null +++ b/templates/java-spring/README.md @@ -0,0 +1,96 @@ +

Java Spring generator

+

+ Use your AsyncAPI definition to generate java code to subscribe and publish messages +

+

+ +## Usage + +### AsyncAPI extensions +In order for the generator to know what names to use for some methods it's necessary to make use of [AsyncAPI specification extensions](https://www.asyncapi.com/v1/spec.html#Specification-Extensions). The extension to use is **x-service-name** and must be applied to all topics. + +here is an example of how to use it: +```yml +topics: + event.lighting.measured: + x-service-name: measures + publish: + $ref: '#/components/messages/lightMeasured' + subscribe: + $ref: '#/components/messages/lightMeasured' +``` +here is a complete example +```yml +asyncapi: '1.0.0' +info: + title: Streetlights API + version: '1.0.0' + description: | + The Smartylighting Streetlights API allows you + to remotely manage the city lights. + license: + name: Apache 2.0 + url: 'https://www.apache.org/licenses/LICENSE-2.0' +baseTopic: smartylighting.streetlights.1.0 +servers: + - url: test.mosquitto.org + scheme: mqtt + description: Test broker + variables: + port: + description: Secure connection (TLS) is available through port 8883. + default: '1883' + enum: + - '1883' + - '8883' +topics: + event.lighting.measured: + x-service-name: measures + publish: + $ref: '#/components/messages/lightMeasured' + subscribe: + $ref: '#/components/messages/lightMeasured' +components: + messages: + lightMeasured: + summary: Inform about environmental lighting conditions for a particular streetlight. + payload: + $ref: "#/components/schemas/lightMeasuredPayload" + schemas: + lightMeasuredPayload: + type: object + properties: + lumens: + type: integer + minimum: 0 + description: Light intensity measured in lumens. + sentAt: + $ref: "#/components/schemas/sentAt" + sentAt: + type: string + format: date-time + description: Date and time when the message was sent. +``` +### From the command-line interface (CLI) + +```bash + Usage: ag [options] java-spring + + Options: + + -V, --version output the version number + -t, --templates directory where templates are located (defaults to internal templates directory) + -h, --help output usage information +``` + +#### Examples + +The shortest possible syntax: +```bash +ag asyncapi.yaml java-spring +``` + +Specify where to put the result: +```bash +ag -o ./src asyncapi.yaml java-spring +``` diff --git a/templates/java-spring/src/main/java/com/asyncapi/service/CommandLinePublisher.java b/templates/java-spring/src/main/java/com/asyncapi/service/CommandLinePublisher.java index f3083db95..2bc579824 100644 --- a/templates/java-spring/src/main/java/com/asyncapi/service/CommandLinePublisher.java +++ b/templates/java-spring/src/main/java/com/asyncapi/service/CommandLinePublisher.java @@ -16,7 +16,7 @@ public void run(String... args) { {{#each asyncapi.topics as |topic key|}} {{#if topic.publish}} - publisherService.{{camelCase topic.publish.x-operation-id}}("Hello World from {{topic.publish.x-operation-id}}"); + publisherService.publish{{capitalize topic.x-service-name}}("Hello World from {{topic.x-service-name}}"); {{/if}} {{/each}} diff --git a/templates/java-spring/src/main/java/com/asyncapi/service/PublisherService.java b/templates/java-spring/src/main/java/com/asyncapi/service/PublisherService.java index 6341bf6ce..27852fa29 100644 --- a/templates/java-spring/src/main/java/com/asyncapi/service/PublisherService.java +++ b/templates/java-spring/src/main/java/com/asyncapi/service/PublisherService.java @@ -10,7 +10,7 @@ public interface PublisherService { {{#if topic.publish}} @Gateway(requestChannel = "{{camelCase topic.x-service-name}}OutboundChannel") - void {{camelCase topic.publish.x-operation-id}}(String data); + void publish{{capitalize topic.x-service-name}}(String data); {{/if}} {{/each}} } From 015366a97b2822df71f3ed452e653402ae44dad9 Mon Sep 17 00:00:00 2001 From: Raisel Melian Date: Mon, 19 Nov 2018 11:52:05 -0500 Subject: [PATCH 13/14] add how to run the java aplication --- templates/java-spring/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/templates/java-spring/README.md b/templates/java-spring/README.md index 40bd872c8..4a04610f1 100644 --- a/templates/java-spring/README.md +++ b/templates/java-spring/README.md @@ -94,3 +94,9 @@ Specify where to put the result: ```bash ag -o ./src asyncapi.yaml java-spring ``` + +### Run it +To run the generated application you need the java virtual machine and gradle installed. After thats done go to the root folder of the generated code and run this command: +```bash +gradle bootRun +``` From 8332d50b570b743dbeb256d9e42202c6e94a11ba Mon Sep 17 00:00:00 2001 From: fmvilas Date: Tue, 20 Nov 2018 19:12:11 +0100 Subject: [PATCH 14/14] Bump version to 0.4.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index e4ef0adf9..f1d5186ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "asyncapi-generator", - "version": "0.3.3", + "version": "0.4.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 92deb2a75..3794b94e8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "asyncapi-generator", - "version": "0.3.3", + "version": "0.4.0", "description": "The AsyncAPI generator. It can generate documentation, code, anything!", "main": "./lib/generator.js", "bin": {