Repository: dziadeusz/hexagonal-architecture-by-example
Branch: master
Commit: 66c733910127
Files: 43
Total size: 38.0 KB
Directory structure:
gitextract_5r_na3sw/
├── .gitignore
├── build.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src/
└── main/
├── java/
│ └── tech/
│ └── allegro/
│ └── hexagon/
│ ├── HexagonalArchitectureExampleApplication.java
│ └── articles/
│ ├── adapters/
│ │ ├── api/
│ │ │ ├── ArticleEndpoint.java
│ │ │ ├── ArticleFacade.java
│ │ │ ├── ArticleIdResponse.java
│ │ │ ├── ArticleRequest.java
│ │ │ └── ArticleResponse.java
│ │ ├── articledb/
│ │ │ ├── ArticleDatabaseModel.java
│ │ │ └── DbArticleRepository.java
│ │ ├── authorservice/
│ │ │ ├── AuthorExternalModel.java
│ │ │ └── ExternalServiceClientAuthorRepository.java
│ │ ├── messagebroker/
│ │ │ ├── ArticleCreatedMessage.java
│ │ │ ├── ArticleRetrievedMessage.java
│ │ │ └── MessageBrokerArticleMessageSender.java
│ │ ├── notifications/
│ │ │ ├── ArticleMailModel.java
│ │ │ ├── ArticleSmsModel.java
│ │ │ ├── AuthorMailNotifier.java
│ │ │ └── AuthorSmsNotifier.java
│ │ └── socialmedia/
│ │ ├── ArticleTwitterModel.java
│ │ ├── TwitterArticlePublisher.java
│ │ └── TwitterClient.java
│ ├── config/
│ │ └── ArticleConfig.java
│ └── domain/
│ ├── ArticlePublisher.java
│ ├── model/
│ │ ├── Article.java
│ │ ├── ArticleId.java
│ │ ├── Author.java
│ │ ├── AuthorId.java
│ │ ├── Content.java
│ │ ├── PersonName.java
│ │ └── Title.java
│ └── ports/
│ ├── ArticleMessageSender.java
│ ├── ArticleRepository.java
│ ├── ArticleService.java
│ ├── AuthorNotifier.java
│ ├── AuthorRepository.java
│ └── SocialMediaPublisher.java
└── resources/
└── application.properties
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
target/
================================================
FILE: build.gradle
================================================
plugins {
id 'org.springframework.boot' version '2.2.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
group = 'tech.allegro'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
================================================
FILE: gradlew
================================================
#!/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" "$@"
================================================
FILE: gradlew.bat
================================================
@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
================================================
FILE: settings.gradle
================================================
rootProject.name = 'hexagonal-architecture-by-example'
================================================
FILE: src/main/java/tech/allegro/hexagon/HexagonalArchitectureExampleApplication.java
================================================
package tech.allegro.hexagon;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HexagonalArchitectureExampleApplication {
public static void main(String[] args) {
SpringApplication.run(HexagonalArchitectureExampleApplication.class, args);
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/api/ArticleEndpoint.java
================================================
package tech.allegro.hexagon.articles.adapters.api;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("articles")
class ArticleEndpoint {
private final ArticleFacade articles;
ArticleEndpoint(ArticleFacade articles) {
this.articles = articles;
}
@GetMapping("{articleId}")
ArticleResponse get(@PathVariable("articleId") final String articleId) {
return articles.get(articleId);
}
@PostMapping
ArticleIdResponse create(@RequestBody final ArticleRequest articleRequest) {
return articles.create(articleRequest);
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/api/ArticleFacade.java
================================================
package tech.allegro.hexagon.articles.adapters.api;
import org.springframework.stereotype.Component;
import tech.allegro.hexagon.articles.domain.model.Article;
import tech.allegro.hexagon.articles.domain.model.ArticleId;
import tech.allegro.hexagon.articles.domain.ports.ArticleService;
@Component
class ArticleFacade {
private final ArticleService articleService;
ArticleFacade(final ArticleService articleService) {
this.articleService = articleService;
}
ArticleResponse get(final String articleId) {
final Article article = articleService.get(ArticleId.of(articleId));
return ArticleResponse.of(article);
}
ArticleIdResponse create(final ArticleRequest articleRequest) {
final ArticleId articleId = articleService.create(articleRequest.authorId(), articleRequest.title(), articleRequest.content());
return ArticleIdResponse.of(articleId);
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/api/ArticleIdResponse.java
================================================
package tech.allegro.hexagon.articles.adapters.api;
import com.fasterxml.jackson.annotation.JsonProperty;
import tech.allegro.hexagon.articles.domain.model.ArticleId;
class ArticleIdResponse {
private final String id;
private ArticleIdResponse(final String id) {
this.id = id;
}
static ArticleIdResponse of(final ArticleId articleId) {
return new ArticleIdResponse(articleId.value());
}
@JsonProperty("id")
String id() {
return id;
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/api/ArticleRequest.java
================================================
package tech.allegro.hexagon.articles.adapters.api;
import com.fasterxml.jackson.annotation.JsonProperty;
import tech.allegro.hexagon.articles.domain.model.AuthorId;
import tech.allegro.hexagon.articles.domain.model.Content;
import tech.allegro.hexagon.articles.domain.model.Title;
class ArticleRequest {
private final String title;
private final String content;
private final String authorId;
ArticleRequest(@JsonProperty("title") final String title, @JsonProperty("content") final String content, @JsonProperty("authorId") final String authorId) {
this.title = title;
this.content = content;
this.authorId = authorId;
}
Title title() {
return Title.of(title);
}
Content content() {
return Content.of(content);
}
AuthorId authorId() {
return AuthorId.of(authorId);
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/api/ArticleResponse.java
================================================
package tech.allegro.hexagon.articles.adapters.api;
import com.fasterxml.jackson.annotation.JsonProperty;
import tech.allegro.hexagon.articles.domain.model.Article;
class ArticleResponse {
private final String id;
private final String title;
private final String content;
private final String authorName;
private ArticleResponse(final String id, final String title, final String content, final String authorName) {
this.id = id;
this.title = title;
this.content = content;
this.authorName = authorName;
}
static ArticleResponse of(final Article article) {
return new ArticleResponse(article.id().value(),
article.title().value(),
article.content().value(),
article.author().name().value());
}
@JsonProperty("id")
String id() {
return id;
}
@JsonProperty("title")
String title() {
return title;
}
@JsonProperty("content")
String content() {
return content;
}
@JsonProperty("authorName")
String authorName() {
return authorName;
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/articledb/ArticleDatabaseModel.java
================================================
package tech.allegro.hexagon.articles.adapters.articledb;
import tech.allegro.hexagon.articles.domain.model.Article;
import tech.allegro.hexagon.articles.domain.model.ArticleId;
import tech.allegro.hexagon.articles.domain.model.Author;
import tech.allegro.hexagon.articles.domain.model.AuthorId;
import tech.allegro.hexagon.articles.domain.model.Content;
import tech.allegro.hexagon.articles.domain.model.PersonName;
import tech.allegro.hexagon.articles.domain.model.Title;
import java.time.ZonedDateTime;
import java.util.UUID;
class ArticleDatabaseModel {
private final UUID id;
private final String title;
private final String content;
private final long version;
private final ZonedDateTime createdAt;
private final String authorId;
private final String authorName;
private ArticleDatabaseModel(final UUID id,
final String title,
final String content,
final String authorId,
final long version,
final ZonedDateTime createdAt,
final String authorName) {
this.id = id;
this.title = title;
this.content = content;
this.authorId = authorId;
this.version = version;
this.createdAt = createdAt;
this.authorName = authorName;
}
@Override
public String toString() {
return title;
}
Article toDomain() {
return Article.article()
.withId(ArticleId.of(id.toString()))
.withAuthor(Author
.author()
.withId(AuthorId.of(authorId))
.withName(PersonName.of(authorName))
.build())
.withTitle(Title.of(title))
.withContent(Content.of(content))
.build();
}
static ArticleDatabaseModel of(final Author author, final Title title, final Content content) {
return articleDatabaseModel()
.withId(UUID.randomUUID())
.withVersion(0)
.withCreatedAt(ZonedDateTime.now())
.withAuthorId(author.id().value())
.withAuthorName(author.name().value())
.withTitle(title.value())
.withContent(content.value())
.build();
}
static ArticleDatabaseModelBuilder articleDatabaseModel() {
return new ArticleDatabaseModelBuilder();
}
static final class ArticleDatabaseModelBuilder {
private UUID id;
private String title;
private String content;
private long version;
private ZonedDateTime createdAt;
private String authorId;
private String authorName;
private ArticleDatabaseModelBuilder() {
}
ArticleDatabaseModelBuilder withId(UUID id) {
this.id = id;
return this;
}
ArticleDatabaseModelBuilder withTitle(String title) {
this.title = title;
return this;
}
ArticleDatabaseModelBuilder withContent(String content) {
this.content = content;
return this;
}
ArticleDatabaseModelBuilder withVersion(long version) {
this.version = version;
return this;
}
ArticleDatabaseModelBuilder withCreatedAt(ZonedDateTime createdAt) {
this.createdAt = createdAt;
return this;
}
ArticleDatabaseModelBuilder withAuthorId(String authorId) {
this.authorId = authorId;
return this;
}
ArticleDatabaseModelBuilder withAuthorName(String authorName) {
this.authorName = authorName;
return this;
}
ArticleDatabaseModel build() {
return new ArticleDatabaseModel(id, title, content, authorId, version, createdAt, authorName);
}
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/articledb/DbArticleRepository.java
================================================
package tech.allegro.hexagon.articles.adapters.articledb;
import org.springframework.stereotype.Component;
import tech.allegro.hexagon.articles.domain.model.Article;
import tech.allegro.hexagon.articles.domain.model.ArticleId;
import tech.allegro.hexagon.articles.domain.model.Author;
import tech.allegro.hexagon.articles.domain.model.Content;
import tech.allegro.hexagon.articles.domain.model.Title;
import tech.allegro.hexagon.articles.domain.ports.ArticleRepository;
import java.util.UUID;
import static tech.allegro.hexagon.articles.adapters.articledb.ArticleDatabaseModel.articleDatabaseModel;
import static tech.allegro.hexagon.articles.adapters.articledb.ArticleDatabaseModel.of;
@Component
class DbArticleRepository implements ArticleRepository {
@Override
public Article save(final Author author, final Title title, final Content content) {
/**
* Database integration implementation comes here
*/
final ArticleDatabaseModel entity = of(author, title, content);
return entity.toDomain();
}
@Override
public Article get(final ArticleId id) {
/**
* Database integration implementation comes here
*/
final ArticleDatabaseModel entity = articleDatabaseModel()
.withId(UUID.fromString(id.value()))
.withAuthorName("William Shakespeare")
.withAuthorId("928467")
.withTitle("Hexagonal Architecture")
.withContent("Lorem ipsum")
.build();
return entity.toDomain();
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/authorservice/AuthorExternalModel.java
================================================
package tech.allegro.hexagon.articles.adapters.authorservice;
import tech.allegro.hexagon.articles.domain.model.Author;
import tech.allegro.hexagon.articles.domain.model.AuthorId;
import tech.allegro.hexagon.articles.domain.model.PersonName;
class AuthorExternalModel {
private final long id;
private final String firstName;
private final String lastName;
private AuthorExternalModel(final long id, final String firstName, final String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
Author toDomain() {
return Author.author()
.withId(AuthorId.of(String.valueOf(id)))
.withName(PersonName.of(fullName()))
.build();
}
private String fullName() {
return String.format("%s %s", firstName, lastName);
}
@Override
public String toString() {
return fullName();
}
static AuthorExternalModelBuilder authorExternalModel() {
return new AuthorExternalModelBuilder();
}
static final class AuthorExternalModelBuilder {
private long id;
private String firstName;
private String lastName;
private AuthorExternalModelBuilder() {
}
AuthorExternalModelBuilder withId(long id) {
this.id = id;
return this;
}
AuthorExternalModelBuilder withFirstName(String firstName) {
this.firstName = firstName;
return this;
}
AuthorExternalModelBuilder withLastName(String lastName) {
this.lastName = lastName;
return this;
}
AuthorExternalModel build() {
return new AuthorExternalModel(id, firstName, lastName);
}
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/authorservice/ExternalServiceClientAuthorRepository.java
================================================
package tech.allegro.hexagon.articles.adapters.authorservice;
import org.springframework.stereotype.Component;
import tech.allegro.hexagon.articles.domain.model.Author;
import tech.allegro.hexagon.articles.domain.model.AuthorId;
import tech.allegro.hexagon.articles.domain.ports.AuthorRepository;
import static tech.allegro.hexagon.articles.adapters.authorservice.AuthorExternalModel.authorExternalModel;
@Component
class ExternalServiceClientAuthorRepository implements AuthorRepository {
@Override
public Author get(final AuthorId authorId) {
/**
* external author service integration implementation comes here
*/
final AuthorExternalModel author = authorExternalModel()
.withId(928467)
.withFirstName("William")
.withLastName("Shakespeare")
.build();
return author.toDomain();
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/messagebroker/ArticleCreatedMessage.java
================================================
package tech.allegro.hexagon.articles.adapters.messagebroker;
import tech.allegro.hexagon.articles.domain.model.Article;
import java.time.ZonedDateTime;
class ArticleCreatedMessage {
private final Article article;
private final ZonedDateTime sentAt;
private ArticleCreatedMessage(final Article article, final ZonedDateTime sentAt) {
this.article = article;
this.sentAt = sentAt;
}
static ArticleCreatedMessage of(Article article) {
return new ArticleCreatedMessage(article, ZonedDateTime.now());
}
@Override
public String toString() {
return String.format("\"Article >>%s<< created\"", article.title().value());
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/messagebroker/ArticleRetrievedMessage.java
================================================
package tech.allegro.hexagon.articles.adapters.messagebroker;
import tech.allegro.hexagon.articles.domain.model.Article;
import java.time.ZonedDateTime;
class ArticleRetrievedMessage {
private final Article article;
private final ZonedDateTime sentAt;
private ArticleRetrievedMessage(final Article article, final ZonedDateTime sentAt) {
this.article = article;
this.sentAt = sentAt;
}
static ArticleRetrievedMessage of(Article article) {
return new ArticleRetrievedMessage(article, ZonedDateTime.now());
}
@Override
public String toString() {
return String.format("\"Article >>%s<< retrieved\"", article.title().value());
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/messagebroker/MessageBrokerArticleMessageSender.java
================================================
package tech.allegro.hexagon.articles.adapters.messagebroker;
import org.springframework.stereotype.Component;
import tech.allegro.hexagon.articles.domain.model.Article;
import tech.allegro.hexagon.articles.domain.ports.ArticleMessageSender;
@Component
class MessageBrokerArticleMessageSender implements ArticleMessageSender {
@Override
public void sendMessageForCreated(final Article article) {
/**
* message broker integration implementation comes here
*/
ArticleCreatedMessage.of(article);
}
@Override
public void sendMessageForRetrieved(final Article article) {
/**
* message broker integration implementation comes here
*/
ArticleRetrievedMessage.of(article);
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/notifications/ArticleMailModel.java
================================================
package tech.allegro.hexagon.articles.adapters.notifications;
import tech.allegro.hexagon.articles.domain.model.Article;
class ArticleMailModel {
private static final String SUBJECT = "You have successfully published: >>%s<<";
private static final String CONTENT = "Check if everything is correct: >>%s<<";
private final String recipientId;
private final String subject;
private final String content;
private ArticleMailModel(final String recipientId,
final String subject,
final String content) {
this.recipientId = recipientId;
this.subject = subject;
this.content = content;
}
static ArticleMailModel of(final Article article) {
return new ArticleMailModel(article.author().name().value(),
String.format(SUBJECT, article.title().value()),
String.format(CONTENT, article.content().value()));
}
@Override
public String toString() {
return subject;
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/notifications/ArticleSmsModel.java
================================================
package tech.allegro.hexagon.articles.adapters.notifications;
import tech.allegro.hexagon.articles.domain.model.Article;
class ArticleSmsModel {
public static final String CONTENT = "Please check your email. We have sent you publication details of the article: >>%s<<";
private final String recipientId;
private final String text;
private ArticleSmsModel(final String recipientId, final String text) {
this.recipientId = recipientId;
this.text = text;
}
public static ArticleSmsModel of(Article article) {
return new ArticleSmsModel(
article.author().name().value(),
String.format(CONTENT, article.title().value()));
}
@Override
public String toString() {
return text;
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/notifications/AuthorMailNotifier.java
================================================
package tech.allegro.hexagon.articles.adapters.notifications;
import org.springframework.stereotype.Component;
import tech.allegro.hexagon.articles.domain.model.Article;
import tech.allegro.hexagon.articles.domain.ports.AuthorNotifier;
@Component
class AuthorMailNotifier implements AuthorNotifier {
@Override
public void notifyAboutCreationOf(final Article article) {
/**
* Mail system integration implementation comes here
*/
ArticleMailModel.of(article);
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/notifications/AuthorSmsNotifier.java
================================================
package tech.allegro.hexagon.articles.adapters.notifications;
import org.springframework.stereotype.Component;
import tech.allegro.hexagon.articles.domain.model.Article;
import tech.allegro.hexagon.articles.domain.ports.AuthorNotifier;
@Component
class AuthorSmsNotifier implements AuthorNotifier {
@Override
public void notifyAboutCreationOf(final Article article) {
/**
* SMS system integration implementation comes here
*/
ArticleSmsModel.of(article);
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/socialmedia/ArticleTwitterModel.java
================================================
package tech.allegro.hexagon.articles.adapters.socialmedia;
import tech.allegro.hexagon.articles.domain.model.Article;
class ArticleTwitterModel {
public static final String TWEET = "Check out the new article >>%s<< by %s";
private final String twitterAccountId;
private final String tweet;
private ArticleTwitterModel(final String twitterAccountId, final String tweet) {
this.twitterAccountId = twitterAccountId;
this.tweet = tweet;
}
static ArticleTwitterModel of(Article article) {
final String title = article
.title()
.value();
final String twitterId = article.author().name().value();
return new ArticleTwitterModel(twitterId, String.format(TWEET, title, twitterId));
}
@Override
public String toString() {
return tweet;
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/socialmedia/TwitterArticlePublisher.java
================================================
package tech.allegro.hexagon.articles.adapters.socialmedia;
import org.springframework.stereotype.Component;
import tech.allegro.hexagon.articles.domain.model.Article;
import tech.allegro.hexagon.articles.domain.ports.SocialMediaPublisher;
@Component
class TwitterArticlePublisher implements SocialMediaPublisher {
private final TwitterClient twitterClient;
TwitterArticlePublisher(final TwitterClient twitterClient) {
this.twitterClient = twitterClient;
}
@Override
public void publish(final Article article) {
final ArticleTwitterModel articleTweet = ArticleTwitterModel.of(article);
twitterClient.tweet(articleTweet);
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/socialmedia/TwitterClient.java
================================================
package tech.allegro.hexagon.articles.adapters.socialmedia;
import org.springframework.stereotype.Component;
@Component
class TwitterClient {
void tweet(final ArticleTwitterModel articleTweet) {
/**
* social media integration implementation comes here
*/
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/config/ArticleConfig.java
================================================
package tech.allegro.hexagon.articles.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import tech.allegro.hexagon.articles.domain.ArticlePublisher;
import tech.allegro.hexagon.articles.domain.ports.ArticleMessageSender;
import tech.allegro.hexagon.articles.domain.ports.ArticleRepository;
import tech.allegro.hexagon.articles.domain.ports.ArticleService;
import tech.allegro.hexagon.articles.domain.ports.AuthorNotifier;
import tech.allegro.hexagon.articles.domain.ports.AuthorRepository;
import tech.allegro.hexagon.articles.domain.ports.SocialMediaPublisher;
import java.util.List;
@Configuration
class ArticleConfig {
@Bean
ArticlePublisher articleEventPublisher(final ArticleMessageSender eventPublisher,
final List<SocialMediaPublisher> socialMediaPublishers,
final List<AuthorNotifier> articleAuthorNotifiers) {
return new ArticlePublisher(eventPublisher,
socialMediaPublishers,
articleAuthorNotifiers);
}
@Bean
ArticleService articleService(final ArticleRepository articleRepository,
final AuthorRepository authorRepository,
final ArticlePublisher articleEventPublisher
) {
return new ArticleService(
articleRepository,
authorRepository,
articleEventPublisher);
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/domain/ArticlePublisher.java
================================================
package tech.allegro.hexagon.articles.domain;
import tech.allegro.hexagon.articles.domain.model.Article;
import tech.allegro.hexagon.articles.domain.ports.ArticleMessageSender;
import tech.allegro.hexagon.articles.domain.ports.AuthorNotifier;
import tech.allegro.hexagon.articles.domain.ports.SocialMediaPublisher;
import java.util.List;
public class ArticlePublisher {
private final ArticleMessageSender messageSender;
private final List<SocialMediaPublisher> socialMediaPublishers;
private final List<AuthorNotifier> articleAuthorNotifiers;
public ArticlePublisher(final ArticleMessageSender messageSender,
final List<SocialMediaPublisher> socialMediaPublishers,
final List<AuthorNotifier> articleAuthorNotifiers) {
this.messageSender = messageSender;
this.socialMediaPublishers = socialMediaPublishers;
this.articleAuthorNotifiers = articleAuthorNotifiers;
}
public void publishCreationOf(final Article article) {
messageSender.sendMessageForCreated(article);
socialMediaPublishers.forEach(socialMediaPublisher -> socialMediaPublisher.publish(article));
articleAuthorNotifiers.forEach(articleAuthorNotifier -> articleAuthorNotifier.notifyAboutCreationOf(article));
}
public void publishRetrievalOf(final Article article) {
messageSender.sendMessageForRetrieved(article);
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/domain/model/Article.java
================================================
package tech.allegro.hexagon.articles.domain.model;
public class Article {
private final ArticleId id;
private final Title title;
private final Content content;
private final Author author;
private Article(final ArticleId id, final Title title, final Content content, final Author author) {
this.id = id;
this.title = title;
this.content = content;
this.author = author;
}
public void validateEligibilityForPublication() {
verifyForPlagiarism();
validateTitleLength();
validateContentLength();
checkPunctuation();
checkGrammar();
checkStyle();
//TODO: these methods are just placeholders with empty implementation
}
public ArticleId id() {
return id;
}
public Title title() {
return title;
}
public Content content() {
return content;
}
public Author author() {
return author;
}
private void checkGrammar() {
}
private void checkStyle() {
}
private void checkPunctuation() {
}
private void verifyForPlagiarism() {
}
private void validateContentLength() {
}
private void validateTitleLength() {
}
public static ArticleBuilder article() {
return new ArticleBuilder();
}
public static final class ArticleBuilder {
private ArticleId id;
private Title title;
private Content content;
private Author author;
private ArticleBuilder() {
}
public ArticleBuilder withId(ArticleId id) {
this.id = id;
return this;
}
public ArticleBuilder withTitle(Title title) {
this.title = title;
return this;
}
public ArticleBuilder withContent(Content content) {
this.content = content;
return this;
}
public ArticleBuilder withAuthor(Author author) {
this.author = author;
return this;
}
public Article build() {
return new Article(id, title, content, author);
}
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/domain/model/ArticleId.java
================================================
package tech.allegro.hexagon.articles.domain.model;
public class ArticleId {
private final String value;
private ArticleId(final String value) {
this.value = value;
}
public static ArticleId of(final String articleId) {
return new ArticleId(articleId);
}
public String value() {
return value;
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/domain/model/Author.java
================================================
package tech.allegro.hexagon.articles.domain.model;
public class Author {
private final AuthorId id;
private final PersonName name;
private Author(final AuthorId id, final PersonName name) {
this.id = id;
this.name = name;
}
public static AuthorBuilder author() {
return new AuthorBuilder();
}
public PersonName name() {
return name;
}
public AuthorId id() {
return id;
}
public static final class AuthorBuilder {
private AuthorId id;
private PersonName name;
private AuthorBuilder() {
}
public AuthorBuilder withId(AuthorId id) {
this.id = id;
return this;
}
public AuthorBuilder withName(PersonName name) {
this.name = name;
return this;
}
public Author build() {
return new Author(id, name);
}
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/domain/model/AuthorId.java
================================================
package tech.allegro.hexagon.articles.domain.model;
public class AuthorId {
private final String value;
private AuthorId(final String value) {
this.value = value;
}
public static AuthorId of(final String authorId) {
return new AuthorId(authorId);
}
public String value() {
return value;
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/domain/model/Content.java
================================================
package tech.allegro.hexagon.articles.domain.model;
public class Content {
private final String value;
private Content(final String value) {
this.value = value;
}
public static Content of(final String content) {
return new Content(content);
}
public String value() {
return value;
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/domain/model/PersonName.java
================================================
package tech.allegro.hexagon.articles.domain.model;
public class PersonName {
private final String value;
private PersonName(final String value) {
this.value = value;
}
public static PersonName of(final String content) {
return new PersonName(content);
}
public String value() {
return value;
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/domain/model/Title.java
================================================
package tech.allegro.hexagon.articles.domain.model;
public class Title {
private final String value;
private Title(final String value) {
this.value = value;
}
public static Title of(final String title) {
return new Title(title);
}
public String value() {
return value;
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/domain/ports/ArticleMessageSender.java
================================================
package tech.allegro.hexagon.articles.domain.ports;
import tech.allegro.hexagon.articles.domain.model.Article;
public interface ArticleMessageSender {
void sendMessageForCreated(Article article);
void sendMessageForRetrieved(Article article);
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/domain/ports/ArticleRepository.java
================================================
package tech.allegro.hexagon.articles.domain.ports;
import tech.allegro.hexagon.articles.domain.model.Article;
import tech.allegro.hexagon.articles.domain.model.ArticleId;
import tech.allegro.hexagon.articles.domain.model.Author;
import tech.allegro.hexagon.articles.domain.model.Content;
import tech.allegro.hexagon.articles.domain.model.Title;
public interface ArticleRepository {
Article save(Author author, Title title, Content content);
Article get(ArticleId id);
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/domain/ports/ArticleService.java
================================================
package tech.allegro.hexagon.articles.domain.ports;
import tech.allegro.hexagon.articles.domain.ArticlePublisher;
import tech.allegro.hexagon.articles.domain.model.Article;
import tech.allegro.hexagon.articles.domain.model.ArticleId;
import tech.allegro.hexagon.articles.domain.model.Author;
import tech.allegro.hexagon.articles.domain.model.AuthorId;
import tech.allegro.hexagon.articles.domain.model.Content;
import tech.allegro.hexagon.articles.domain.model.Title;
public final class ArticleService {
private final ArticleRepository articleRepository;
private final AuthorRepository authorRepository;
private final ArticlePublisher eventPublisher;
public ArticleService(final ArticleRepository articleRepository,
final AuthorRepository authorRepository,
final ArticlePublisher eventPublisher) {
this.articleRepository = articleRepository;
this.authorRepository = authorRepository;
this.eventPublisher = eventPublisher;
}
public ArticleId create(final AuthorId authorId, final Title title, final Content content) {
final Author author = authorRepository.get(authorId);
final Article article = articleRepository.save(author, title, content);
article.validateEligibilityForPublication();
eventPublisher.publishCreationOf(article);
return article.id();
}
public Article get(final ArticleId id) {
final Article article = articleRepository.get(id);
eventPublisher.publishRetrievalOf(article);
return article;
}
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/domain/ports/AuthorNotifier.java
================================================
package tech.allegro.hexagon.articles.domain.ports;
import tech.allegro.hexagon.articles.domain.model.Article;
public interface AuthorNotifier {
void notifyAboutCreationOf(Article article);
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/domain/ports/AuthorRepository.java
================================================
package tech.allegro.hexagon.articles.domain.ports;
import tech.allegro.hexagon.articles.domain.model.Author;
import tech.allegro.hexagon.articles.domain.model.AuthorId;
public interface AuthorRepository {
Author get(AuthorId authorId);
}
================================================
FILE: src/main/java/tech/allegro/hexagon/articles/domain/ports/SocialMediaPublisher.java
================================================
package tech.allegro.hexagon.articles.domain.ports;
import tech.allegro.hexagon.articles.domain.model.Article;
public interface SocialMediaPublisher {
void publish(Article article);
}
================================================
FILE: src/main/resources/application.properties
================================================
gitextract_5r_na3sw/
├── .gitignore
├── build.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src/
└── main/
├── java/
│ └── tech/
│ └── allegro/
│ └── hexagon/
│ ├── HexagonalArchitectureExampleApplication.java
│ └── articles/
│ ├── adapters/
│ │ ├── api/
│ │ │ ├── ArticleEndpoint.java
│ │ │ ├── ArticleFacade.java
│ │ │ ├── ArticleIdResponse.java
│ │ │ ├── ArticleRequest.java
│ │ │ └── ArticleResponse.java
│ │ ├── articledb/
│ │ │ ├── ArticleDatabaseModel.java
│ │ │ └── DbArticleRepository.java
│ │ ├── authorservice/
│ │ │ ├── AuthorExternalModel.java
│ │ │ └── ExternalServiceClientAuthorRepository.java
│ │ ├── messagebroker/
│ │ │ ├── ArticleCreatedMessage.java
│ │ │ ├── ArticleRetrievedMessage.java
│ │ │ └── MessageBrokerArticleMessageSender.java
│ │ ├── notifications/
│ │ │ ├── ArticleMailModel.java
│ │ │ ├── ArticleSmsModel.java
│ │ │ ├── AuthorMailNotifier.java
│ │ │ └── AuthorSmsNotifier.java
│ │ └── socialmedia/
│ │ ├── ArticleTwitterModel.java
│ │ ├── TwitterArticlePublisher.java
│ │ └── TwitterClient.java
│ ├── config/
│ │ └── ArticleConfig.java
│ └── domain/
│ ├── ArticlePublisher.java
│ ├── model/
│ │ ├── Article.java
│ │ ├── ArticleId.java
│ │ ├── Author.java
│ │ ├── AuthorId.java
│ │ ├── Content.java
│ │ ├── PersonName.java
│ │ └── Title.java
│ └── ports/
│ ├── ArticleMessageSender.java
│ ├── ArticleRepository.java
│ ├── ArticleService.java
│ ├── AuthorNotifier.java
│ ├── AuthorRepository.java
│ └── SocialMediaPublisher.java
└── resources/
└── application.properties
SYMBOL INDEX (165 symbols across 35 files)
FILE: src/main/java/tech/allegro/hexagon/HexagonalArchitectureExampleApplication.java
class HexagonalArchitectureExampleApplication (line 6) | @SpringBootApplication
method main (line 9) | public static void main(String[] args) {
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/api/ArticleEndpoint.java
class ArticleEndpoint (line 10) | @RestController
method ArticleEndpoint (line 16) | ArticleEndpoint(ArticleFacade articles) {
method get (line 20) | @GetMapping("{articleId}")
method create (line 25) | @PostMapping
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/api/ArticleFacade.java
class ArticleFacade (line 8) | @Component
method ArticleFacade (line 13) | ArticleFacade(final ArticleService articleService) {
method get (line 17) | ArticleResponse get(final String articleId) {
method create (line 22) | ArticleIdResponse create(final ArticleRequest articleRequest) {
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/api/ArticleIdResponse.java
class ArticleIdResponse (line 6) | class ArticleIdResponse {
method ArticleIdResponse (line 10) | private ArticleIdResponse(final String id) {
method of (line 14) | static ArticleIdResponse of(final ArticleId articleId) {
method id (line 18) | @JsonProperty("id")
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/api/ArticleRequest.java
class ArticleRequest (line 8) | class ArticleRequest {
method ArticleRequest (line 13) | ArticleRequest(@JsonProperty("title") final String title, @JsonPropert...
method title (line 20) | Title title() {
method content (line 24) | Content content() {
method authorId (line 28) | AuthorId authorId() {
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/api/ArticleResponse.java
class ArticleResponse (line 6) | class ArticleResponse {
method ArticleResponse (line 12) | private ArticleResponse(final String id, final String title, final Str...
method of (line 19) | static ArticleResponse of(final Article article) {
method id (line 26) | @JsonProperty("id")
method title (line 31) | @JsonProperty("title")
method content (line 36) | @JsonProperty("content")
method authorName (line 41) | @JsonProperty("authorName")
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/articledb/ArticleDatabaseModel.java
class ArticleDatabaseModel (line 14) | class ArticleDatabaseModel {
method ArticleDatabaseModel (line 24) | private ArticleDatabaseModel(final UUID id,
method toString (line 40) | @Override
method toDomain (line 45) | Article toDomain() {
method of (line 58) | static ArticleDatabaseModel of(final Author author, final Title title,...
method articleDatabaseModel (line 70) | static ArticleDatabaseModelBuilder articleDatabaseModel() {
class ArticleDatabaseModelBuilder (line 74) | static final class ArticleDatabaseModelBuilder {
method ArticleDatabaseModelBuilder (line 83) | private ArticleDatabaseModelBuilder() {
method withId (line 86) | ArticleDatabaseModelBuilder withId(UUID id) {
method withTitle (line 91) | ArticleDatabaseModelBuilder withTitle(String title) {
method withContent (line 96) | ArticleDatabaseModelBuilder withContent(String content) {
method withVersion (line 101) | ArticleDatabaseModelBuilder withVersion(long version) {
method withCreatedAt (line 106) | ArticleDatabaseModelBuilder withCreatedAt(ZonedDateTime createdAt) {
method withAuthorId (line 111) | ArticleDatabaseModelBuilder withAuthorId(String authorId) {
method withAuthorName (line 116) | ArticleDatabaseModelBuilder withAuthorName(String authorName) {
method build (line 121) | ArticleDatabaseModel build() {
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/articledb/DbArticleRepository.java
class DbArticleRepository (line 16) | @Component
method save (line 19) | @Override
method get (line 28) | @Override
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/authorservice/AuthorExternalModel.java
class AuthorExternalModel (line 7) | class AuthorExternalModel {
method AuthorExternalModel (line 12) | private AuthorExternalModel(final long id, final String firstName, fin...
method toDomain (line 18) | Author toDomain() {
method fullName (line 25) | private String fullName() {
method toString (line 29) | @Override
method authorExternalModel (line 34) | static AuthorExternalModelBuilder authorExternalModel() {
class AuthorExternalModelBuilder (line 38) | static final class AuthorExternalModelBuilder {
method AuthorExternalModelBuilder (line 43) | private AuthorExternalModelBuilder() {
method withId (line 46) | AuthorExternalModelBuilder withId(long id) {
method withFirstName (line 51) | AuthorExternalModelBuilder withFirstName(String firstName) {
method withLastName (line 56) | AuthorExternalModelBuilder withLastName(String lastName) {
method build (line 61) | AuthorExternalModel build() {
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/authorservice/ExternalServiceClientAuthorRepository.java
class ExternalServiceClientAuthorRepository (line 10) | @Component
method get (line 14) | @Override
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/messagebroker/ArticleCreatedMessage.java
class ArticleCreatedMessage (line 7) | class ArticleCreatedMessage {
method ArticleCreatedMessage (line 12) | private ArticleCreatedMessage(final Article article, final ZonedDateTi...
method of (line 17) | static ArticleCreatedMessage of(Article article) {
method toString (line 21) | @Override
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/messagebroker/ArticleRetrievedMessage.java
class ArticleRetrievedMessage (line 7) | class ArticleRetrievedMessage {
method ArticleRetrievedMessage (line 13) | private ArticleRetrievedMessage(final Article article, final ZonedDate...
method of (line 18) | static ArticleRetrievedMessage of(Article article) {
method toString (line 22) | @Override
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/messagebroker/MessageBrokerArticleMessageSender.java
class MessageBrokerArticleMessageSender (line 7) | @Component
method sendMessageForCreated (line 10) | @Override
method sendMessageForRetrieved (line 18) | @Override
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/notifications/ArticleMailModel.java
class ArticleMailModel (line 5) | class ArticleMailModel {
method ArticleMailModel (line 14) | private ArticleMailModel(final String recipientId,
method of (line 22) | static ArticleMailModel of(final Article article) {
method toString (line 28) | @Override
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/notifications/ArticleSmsModel.java
class ArticleSmsModel (line 5) | class ArticleSmsModel {
method ArticleSmsModel (line 11) | private ArticleSmsModel(final String recipientId, final String text) {
method of (line 16) | public static ArticleSmsModel of(Article article) {
method toString (line 23) | @Override
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/notifications/AuthorMailNotifier.java
class AuthorMailNotifier (line 7) | @Component
method notifyAboutCreationOf (line 10) | @Override
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/notifications/AuthorSmsNotifier.java
class AuthorSmsNotifier (line 7) | @Component
method notifyAboutCreationOf (line 10) | @Override
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/socialmedia/ArticleTwitterModel.java
class ArticleTwitterModel (line 5) | class ArticleTwitterModel {
method ArticleTwitterModel (line 11) | private ArticleTwitterModel(final String twitterAccountId, final Strin...
method of (line 16) | static ArticleTwitterModel of(Article article) {
method toString (line 24) | @Override
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/socialmedia/TwitterArticlePublisher.java
class TwitterArticlePublisher (line 7) | @Component
method TwitterArticlePublisher (line 12) | TwitterArticlePublisher(final TwitterClient twitterClient) {
method publish (line 16) | @Override
FILE: src/main/java/tech/allegro/hexagon/articles/adapters/socialmedia/TwitterClient.java
class TwitterClient (line 5) | @Component
method tweet (line 7) | void tweet(final ArticleTwitterModel articleTweet) {
FILE: src/main/java/tech/allegro/hexagon/articles/config/ArticleConfig.java
class ArticleConfig (line 15) | @Configuration
method articleEventPublisher (line 18) | @Bean
method articleService (line 27) | @Bean
FILE: src/main/java/tech/allegro/hexagon/articles/domain/ArticlePublisher.java
class ArticlePublisher (line 10) | public class ArticlePublisher {
method ArticlePublisher (line 15) | public ArticlePublisher(final ArticleMessageSender messageSender,
method publishCreationOf (line 23) | public void publishCreationOf(final Article article) {
method publishRetrievalOf (line 29) | public void publishRetrievalOf(final Article article) {
FILE: src/main/java/tech/allegro/hexagon/articles/domain/model/Article.java
class Article (line 3) | public class Article {
method Article (line 10) | private Article(final ArticleId id, final Title title, final Content c...
method validateEligibilityForPublication (line 17) | public void validateEligibilityForPublication() {
method id (line 27) | public ArticleId id() {
method title (line 31) | public Title title() {
method content (line 35) | public Content content() {
method author (line 39) | public Author author() {
method checkGrammar (line 43) | private void checkGrammar() {
method checkStyle (line 46) | private void checkStyle() {
method checkPunctuation (line 49) | private void checkPunctuation() {
method verifyForPlagiarism (line 52) | private void verifyForPlagiarism() {
method validateContentLength (line 55) | private void validateContentLength() {
method validateTitleLength (line 58) | private void validateTitleLength() {
method article (line 61) | public static ArticleBuilder article() {
class ArticleBuilder (line 66) | public static final class ArticleBuilder {
method ArticleBuilder (line 72) | private ArticleBuilder() {
method withId (line 75) | public ArticleBuilder withId(ArticleId id) {
method withTitle (line 80) | public ArticleBuilder withTitle(Title title) {
method withContent (line 85) | public ArticleBuilder withContent(Content content) {
method withAuthor (line 90) | public ArticleBuilder withAuthor(Author author) {
method build (line 95) | public Article build() {
FILE: src/main/java/tech/allegro/hexagon/articles/domain/model/ArticleId.java
class ArticleId (line 3) | public class ArticleId {
method ArticleId (line 6) | private ArticleId(final String value) {
method of (line 10) | public static ArticleId of(final String articleId) {
method value (line 14) | public String value() {
FILE: src/main/java/tech/allegro/hexagon/articles/domain/model/Author.java
class Author (line 3) | public class Author {
method Author (line 8) | private Author(final AuthorId id, final PersonName name) {
method author (line 13) | public static AuthorBuilder author() {
method name (line 17) | public PersonName name() {
method id (line 21) | public AuthorId id() {
class AuthorBuilder (line 25) | public static final class AuthorBuilder {
method AuthorBuilder (line 29) | private AuthorBuilder() {
method withId (line 32) | public AuthorBuilder withId(AuthorId id) {
method withName (line 37) | public AuthorBuilder withName(PersonName name) {
method build (line 42) | public Author build() {
FILE: src/main/java/tech/allegro/hexagon/articles/domain/model/AuthorId.java
class AuthorId (line 3) | public class AuthorId {
method AuthorId (line 6) | private AuthorId(final String value) {
method of (line 10) | public static AuthorId of(final String authorId) {
method value (line 14) | public String value() {
FILE: src/main/java/tech/allegro/hexagon/articles/domain/model/Content.java
class Content (line 3) | public class Content {
method Content (line 6) | private Content(final String value) {
method of (line 10) | public static Content of(final String content) {
method value (line 14) | public String value() {
FILE: src/main/java/tech/allegro/hexagon/articles/domain/model/PersonName.java
class PersonName (line 3) | public class PersonName {
method PersonName (line 6) | private PersonName(final String value) {
method of (line 10) | public static PersonName of(final String content) {
method value (line 14) | public String value() {
FILE: src/main/java/tech/allegro/hexagon/articles/domain/model/Title.java
class Title (line 3) | public class Title {
method Title (line 6) | private Title(final String value) {
method of (line 10) | public static Title of(final String title) {
method value (line 14) | public String value() {
FILE: src/main/java/tech/allegro/hexagon/articles/domain/ports/ArticleMessageSender.java
type ArticleMessageSender (line 5) | public interface ArticleMessageSender {
method sendMessageForCreated (line 7) | void sendMessageForCreated(Article article);
method sendMessageForRetrieved (line 9) | void sendMessageForRetrieved(Article article);
FILE: src/main/java/tech/allegro/hexagon/articles/domain/ports/ArticleRepository.java
type ArticleRepository (line 9) | public interface ArticleRepository {
method save (line 11) | Article save(Author author, Title title, Content content);
method get (line 13) | Article get(ArticleId id);
FILE: src/main/java/tech/allegro/hexagon/articles/domain/ports/ArticleService.java
class ArticleService (line 11) | public final class ArticleService {
method ArticleService (line 18) | public ArticleService(final ArticleRepository articleRepository,
method create (line 26) | public ArticleId create(final AuthorId authorId, final Title title, fi...
method get (line 36) | public Article get(final ArticleId id) {
FILE: src/main/java/tech/allegro/hexagon/articles/domain/ports/AuthorNotifier.java
type AuthorNotifier (line 5) | public interface AuthorNotifier {
method notifyAboutCreationOf (line 7) | void notifyAboutCreationOf(Article article);
FILE: src/main/java/tech/allegro/hexagon/articles/domain/ports/AuthorRepository.java
type AuthorRepository (line 6) | public interface AuthorRepository {
method get (line 8) | Author get(AuthorId authorId);
FILE: src/main/java/tech/allegro/hexagon/articles/domain/ports/SocialMediaPublisher.java
type SocialMediaPublisher (line 5) | public interface SocialMediaPublisher {
method publish (line 7) | void publish(Article article);
Condensed preview — 43 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (45K chars).
[
{
"path": ".gitignore",
"chars": 53,
"preview": "### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\ntarget/"
},
{
"path": "build.gradle",
"chars": 544,
"preview": "plugins {\n id 'org.springframework.boot' version '2.2.2.RELEASE'\n id 'io.spring.dependency-management' version '1."
},
{
"path": "gradle/wrapper/gradle-wrapper.properties",
"chars": 202,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "gradlew",
"chars": 5296,
"preview": "#!/usr/bin/env sh\n\n##############################################################################\n##\n## Gradle start up"
},
{
"path": "gradlew.bat",
"chars": 2176,
"preview": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem "
},
{
"path": "settings.gradle",
"chars": 55,
"preview": "rootProject.name = 'hexagonal-architecture-by-example'\n"
},
{
"path": "src/main/java/tech/allegro/hexagon/HexagonalArchitectureExampleApplication.java",
"chars": 369,
"preview": "package tech.allegro.hexagon;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoco"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/adapters/api/ArticleEndpoint.java",
"chars": 929,
"preview": "package tech.allegro.hexagon.articles.adapters.api;\n\nimport org.springframework.web.bind.annotation.GetMapping;\nimport o"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/adapters/api/ArticleFacade.java",
"chars": 921,
"preview": "package tech.allegro.hexagon.articles.adapters.api;\n\nimport org.springframework.stereotype.Component;\nimport tech.allegr"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/adapters/api/ArticleIdResponse.java",
"chars": 499,
"preview": "package tech.allegro.hexagon.articles.adapters.api;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport tech.a"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/adapters/api/ArticleRequest.java",
"chars": 870,
"preview": "package tech.allegro.hexagon.articles.adapters.api;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport tech.a"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/adapters/api/ArticleResponse.java",
"chars": 1139,
"preview": "package tech.allegro.hexagon.articles.adapters.api;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport tech.a"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/adapters/articledb/ArticleDatabaseModel.java",
"chars": 4033,
"preview": "package tech.allegro.hexagon.articles.adapters.articledb;\n\nimport tech.allegro.hexagon.articles.domain.model.Article;\nim"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/adapters/articledb/DbArticleRepository.java",
"chars": 1579,
"preview": "package tech.allegro.hexagon.articles.adapters.articledb;\n\nimport org.springframework.stereotype.Component;\nimport tech."
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/adapters/authorservice/AuthorExternalModel.java",
"chars": 1789,
"preview": "package tech.allegro.hexagon.articles.adapters.authorservice;\n\nimport tech.allegro.hexagon.articles.domain.model.Author;"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/adapters/authorservice/ExternalServiceClientAuthorRepository.java",
"chars": 907,
"preview": "package tech.allegro.hexagon.articles.adapters.authorservice;\n\nimport org.springframework.stereotype.Component;\nimport t"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/adapters/messagebroker/ArticleCreatedMessage.java",
"chars": 691,
"preview": "package tech.allegro.hexagon.articles.adapters.messagebroker;\n\nimport tech.allegro.hexagon.articles.domain.model.Article"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/adapters/messagebroker/ArticleRetrievedMessage.java",
"chars": 702,
"preview": "package tech.allegro.hexagon.articles.adapters.messagebroker;\n\nimport tech.allegro.hexagon.articles.domain.model.Article"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/adapters/messagebroker/MessageBrokerArticleMessageSender.java",
"chars": 765,
"preview": "package tech.allegro.hexagon.articles.adapters.messagebroker;\n\nimport org.springframework.stereotype.Component;\nimport t"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/adapters/notifications/ArticleMailModel.java",
"chars": 1038,
"preview": "package tech.allegro.hexagon.articles.adapters.notifications;\n\nimport tech.allegro.hexagon.articles.domain.model.Article"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/adapters/notifications/ArticleSmsModel.java",
"chars": 784,
"preview": "package tech.allegro.hexagon.articles.adapters.notifications;\n\nimport tech.allegro.hexagon.articles.domain.model.Article"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/adapters/notifications/AuthorMailNotifier.java",
"chars": 511,
"preview": "package tech.allegro.hexagon.articles.adapters.notifications;\n\nimport org.springframework.stereotype.Component;\nimport t"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/adapters/notifications/AuthorSmsNotifier.java",
"chars": 508,
"preview": "package tech.allegro.hexagon.articles.adapters.notifications;\n\nimport org.springframework.stereotype.Component;\nimport t"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/adapters/socialmedia/ArticleTwitterModel.java",
"chars": 857,
"preview": "package tech.allegro.hexagon.articles.adapters.socialmedia;\n\nimport tech.allegro.hexagon.articles.domain.model.Article;\n"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/adapters/socialmedia/TwitterArticlePublisher.java",
"chars": 678,
"preview": "package tech.allegro.hexagon.articles.adapters.socialmedia;\n\nimport org.springframework.stereotype.Component;\nimport tec"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/adapters/socialmedia/TwitterClient.java",
"chars": 295,
"preview": "package tech.allegro.hexagon.articles.adapters.socialmedia;\n\nimport org.springframework.stereotype.Component;\n\n@Componen"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/config/ArticleConfig.java",
"chars": 1530,
"preview": "package tech.allegro.hexagon.articles.config;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springfram"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/domain/ArticlePublisher.java",
"chars": 1432,
"preview": "package tech.allegro.hexagon.articles.domain;\n\nimport tech.allegro.hexagon.articles.domain.model.Article;\nimport tech.al"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/domain/model/Article.java",
"chars": 2160,
"preview": "package tech.allegro.hexagon.articles.domain.model;\n\npublic class Article {\n\n private final ArticleId id;\n private"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/domain/model/ArticleId.java",
"chars": 353,
"preview": "package tech.allegro.hexagon.articles.domain.model;\n\npublic class ArticleId {\n private final String value;\n\n priva"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/domain/model/Author.java",
"chars": 940,
"preview": "package tech.allegro.hexagon.articles.domain.model;\n\npublic class Author {\n private final AuthorId id;\n private fi"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/domain/model/AuthorId.java",
"chars": 347,
"preview": "package tech.allegro.hexagon.articles.domain.model;\n\npublic class AuthorId {\n private final String value;\n\n privat"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/domain/model/Content.java",
"chars": 341,
"preview": "package tech.allegro.hexagon.articles.domain.model;\n\npublic class Content {\n private final String value;\n\n private"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/domain/model/PersonName.java",
"chars": 353,
"preview": "package tech.allegro.hexagon.articles.domain.model;\n\npublic class PersonName {\n private final String value;\n\n priv"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/domain/model/Title.java",
"chars": 329,
"preview": "package tech.allegro.hexagon.articles.domain.model;\n\npublic class Title {\n private final String value;\n\n private T"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/domain/ports/ArticleMessageSender.java",
"chars": 258,
"preview": "package tech.allegro.hexagon.articles.domain.ports;\n\nimport tech.allegro.hexagon.articles.domain.model.Article;\n\npublic "
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/domain/ports/ArticleRepository.java",
"chars": 483,
"preview": "package tech.allegro.hexagon.articles.domain.ports;\n\nimport tech.allegro.hexagon.articles.domain.model.Article;\nimport t"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/domain/ports/ArticleService.java",
"chars": 1595,
"preview": "package tech.allegro.hexagon.articles.domain.ports;\n\nimport tech.allegro.hexagon.articles.domain.ArticlePublisher;\nimpor"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/domain/ports/AuthorNotifier.java",
"chars": 200,
"preview": "package tech.allegro.hexagon.articles.domain.ports;\n\nimport tech.allegro.hexagon.articles.domain.model.Article;\n\npublic "
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/domain/ports/AuthorRepository.java",
"chars": 246,
"preview": "package tech.allegro.hexagon.articles.domain.ports;\n\nimport tech.allegro.hexagon.articles.domain.model.Author;\nimport te"
},
{
"path": "src/main/java/tech/allegro/hexagon/articles/domain/ports/SocialMediaPublisher.java",
"chars": 192,
"preview": "package tech.allegro.hexagon.articles.domain.ports;\n\nimport tech.allegro.hexagon.articles.domain.model.Article;\n\npublic "
},
{
"path": "src/main/resources/application.properties",
"chars": 1,
"preview": "\n"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the dziadeusz/hexagonal-architecture-by-example GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 43 files (38.0 KB), approximately 10.2k tokens, and a symbol index with 165 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.