23 Commits

Author SHA1 Message Date
Michael Schnell
eeca95221f Moved license file 2021-10-23 14:54:34 +02:00
Michael Schnell
e0aca86722 Added license information 2021-10-23 14:52:43 +02:00
Michael Schnell
2b9a8da5ae Update README.md 2021-09-19 18:34:02 +02:00
Michael Schnell
cefabe2603 Fixed doc 2021-09-19 11:57:58 +02:00
Michael Schnell
01605ec586 Enhanced title for search engines 2021-09-18 13:51:10 +02:00
Michael Schnell
35e852475c Added build link 2021-09-17 17:35:56 +02:00
Michael Schnell
628669e2dd Added build badge 2021-09-17 17:34:11 +02:00
Michael Schnell
6bab4790af Cleanup Sonar issues, added Github build and formatted source 2021-09-17 17:22:05 +02:00
Michael Schnell
a3fe604856 Fixed wrong level 2021-09-17 16:43:41 +02:00
Michael Schnell
73f10da831 Shortend howto 2021-09-17 16:41:56 +02:00
Michael Schnell
773e23c859 Removed Developer VM as it is outdated and shortened howto 2021-09-17 16:31:11 +02:00
Michael Schnell
e33e149023 Do not use "report-unupported-elements-at-runtime".
See https://github.com/oracle/graal/issues/1725#issuecomment-547570158
2021-09-17 16:09:38 +02:00
Michael Schnell
c05fbf3068 Fixed too old eventstore version 2021-09-17 16:07:43 +02:00
Michael Schnell
52810588c3 Fixed doc 2021-09-05 09:29:49 +02:00
Michael Schnell
95602b8715 Added missing version 2021-09-05 09:29:36 +02:00
Michael Schnell
7a1210abb3 Updated Maven Wrapper 2021-09-05 09:29:24 +02:00
Michael Schnell
5a614a7d72 Fixed problems with native image creation 2021-09-04 17:33:45 +02:00
Michael Schnell
eb394c118f Updated to latest Quarkus version 2021-09-04 17:33:23 +02:00
Michael Schnell
d2e03295a2 Added missing engine 2021-09-04 15:57:29 +02:00
Michael Schnell
0689587fcd Added framwork hints 2021-09-04 15:56:28 +02:00
Michael Schnell
ca526e872e Updated current Quarkus / Spring Boot versions 2021-09-04 15:53:45 +02:00
Michael Schnell
0bd7433cc8 spring.http.converters changed to spring.mvc.converters
See https://docs.across.dev/across-site/production/migration/platform-5-0-to-5-1.html#_deprecated_spring_boot_properties
2021-09-04 15:52:59 +02:00
Michael Schnell
05705386de Fixed naming 2021-09-04 15:49:32 +02:00
136 changed files with 1987 additions and 1276 deletions

37
.github/workflows/maven.yml vendored Normal file
View File

@@ -0,0 +1,37 @@
name: Java Maven Build
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v2
- name: Show versions
run: ./mvnw -version
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
java-version: '11'
distribution: 'zulu'
cache: maven
- name: Cache Maven packages
uses: actions/cache@v1
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Build with Maven
run: ./mvnw clean verify -U -B --file pom.xml

1
.gitignore vendored
View File

@@ -2,5 +2,6 @@
!.gitignore
!.gitkeep
!.mvn
!.github
target
*.log

View File

@@ -1,38 +1,31 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
* Copyright 2007-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL =
"https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
@@ -80,13 +73,13 @@ public class MavenWrapperDownloader {
}
}
}
System.out.println("- Downloading from: : " + url);
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
@@ -102,6 +95,16 @@ public class MavenWrapperDownloader {
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());

Binary file not shown.

View File

@@ -1 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

201
LICENSE.txt Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

130
README.md
View File

@@ -1,7 +1,9 @@
# ddd-cqrs-4-java-example
Example microservices that use [ddd-4-java](https://github.com/fuinorg/ddd-4-java) and [cqrs-4-java](https://github.com/fuinorg/cqrs-4-java) libraries and an [EventStore](https://eventstore.org/) to store the events (Event Sourcing).
Example Java DDD/CQRS/Event Sourcing microservices with [Quarkus](https://quarkus.io/), [Spring Boot](https://spring.io/projects/spring-boot/) and the [EventStore](https://eventstore.org/) from Greg Young. The code uses the lightweight [ddd-4-java](https://github.com/fuinorg/ddd-4-java) and [cqrs-4-java](https://github.com/fuinorg/cqrs-4-java) libaries. No special framework is used except the well known JEE/Spring standards.
[![Java Development Kit 11](https://img.shields.io/badge/JDK-11-green.svg)](https://openjdk.java.net/projects/jdk/11/)
[![Apache](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Build Status](https://github.com/fuinorg/ddd-cqrs-4-java-example/actions/workflows/maven.yml/badge.svg)](https://github.com/fuinorg/ddd-cqrs-4-java-example/actions/workflows/maven.yml)
## Background
This application shows how to implement [DDD](https://en.wikipedia.org/wiki/Domain-driven_design), [CQRS](https://en.wikipedia.org/wiki/Command%E2%80%93query_separation) and [Event Sourcing](https://martinfowler.com/eaaDev/EventSourcing.html) without a DDD/CQRS framework. It uses just a few small libraries in addition to standard web application frameworks like [Quarkus](https://quarkus.io/) and [Spring Boot](https://spring.io/projects/spring-boot/).
@@ -24,7 +26,6 @@ Here is an overview of how such an application looks like:
## Getting started
### Prerequisites
#### Option 1: Install everything yourself
Make sure you have the following tools installed/configured:
* [git](https://git-scm.com/) (VCS)
* [Docker CE](https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/)
@@ -32,85 +33,102 @@ Make sure you have the following tools installed/configured:
* *OPTIONAL* [GraalVM](https://www.graalvm.org/)
* Hostname should be set in /etc/hosts (See [Find and Change Your Hostname in Ubuntu](https://helpdeskgeek.com/linux-tips/find-and-change-your-hostname-in-ubuntu/) for more information)
#### :star: Option 2: Use lubuntu-developer-vm :star:
The **[lubuntu-developer-vm](https://github.com/fuinorg/lubuntu-developer-vm)** has already (almost) everything installed. You only need to execute the following steps:
1. Download and install the [lubuntu-developer-vm](https://github.com/fuinorg/lubuntu-developer-vm) as described
2. OPTIONAL: Change memory of VM to 6 GB (instead of 4 GB default) if you want to create a native image with GraalVM
3. Start the VM and login (developer / developer)
4. Open a console (Shortcut = ctrl alt t)
5. Run a script that finalizes the setup of the developer virtual machine
```
bash <(curl \
-s https://raw.githubusercontent.com/fuinorg/ddd-cqrs-4-java-example/master/setup-lubuntu-developer-vm.sh)
```
6. Reboot
```
reboot
```
### Clone and install project
1. Open a console (Ubuntu shortcut = ctrl alt t)
2. Clone the git repository
1. Clone the git repository
```
git clone https://github.com/fuinorg/ddd-cqrs-4-java-example.git
```
3. Change into the project's directory and run a Maven build
2. Change into the project's directory and run a Maven build
```
cd ddd-cqrs-4-java-example
./mvnw install
```
Be patient - This may take a while (~5 minutes) as all dependencies and some Docker images must be downloaded and also some integration tests will be executed.
### Start Event Store and Maria DB
1. Open a console (Ubuntu shortcut = ctrl alt t)
2. Change into the project's directory and run Docker Compose
```
cd ddd-cqrs-4-java-example
docker-compose up
```
### Start Event Store and Maria DB (Console window 1)
Change into the project's directory and run Docker Compose
```
cd ddd-cqrs-4-java-example
docker-compose up
```
### Start command / query implementations
Start one command microservice and one query microservice - You can mix Quarkus & Spring Boot!
Start one query service and then one command service.
You can mix Quarkus & Spring Boot if you want to!
#### Quarkus Microservices
| Module | |
| :------------ | :---- |
| **[Command](quarkus/command)** | [![Overview](https://raw.github.com/fuinorg/ddd-cqrs-4-java-example/master/quarkus/command/doc/cdi-command-small.png)](quarkus/command) |
| **[Query](quarkus/query)** | [![Overview](https://raw.github.com/fuinorg/ddd-cqrs-4-java-example/master/quarkus/query/doc/cdi-view-small.png)](quarkus/query) |
##### Quarkus Query Service (Console window 2)
1. Start the Quarkus query service:
```
cd ddd-cqrs-4-java-example/quarkus/query
./mvnw quarkus:dev
```
2. Opening [http://localhost:8080/](http://localhost:8080/) should show the query welcome page
For more details see [quarkus/query](quarkus/query).
##### Quarkus Command Service (Console window 3)
1. Start the Quarkus command service:
```
cd ddd-cqrs-4-java-example/quarkus/command
./mvnw quarkus:dev
```
2. Opening [http://localhost:8081/](http://localhost:8081/) should show the command welcome page
For more details see [quarkus/command](quarkus/command).
#### Spring Boot Microservices
| Module | |
| :------------ | :---- |
| **[Command](spring-boot/command)** | [![Overview](https://raw.github.com/fuinorg/ddd-cqrs-4-java-example/master/spring-boot/command/doc/spring-command-small.png)](spring-boot/command) |
| **[Query](spring-boot/query)** | [![Overview](https://raw.github.com/fuinorg/ddd-cqrs-4-java-example/master/spring-boot/query/doc/spring-view-small.png)](spring-boot/query) |
##### Spring Boot Query Service (Console window 2)
1. Start the Spring Boot query service:
```
cd ddd-cqrs-4-java-example/spring-boot/query
./mvnw spring-boot:run
```
2. Opening [http://localhost:8080/](http://localhost:8080/) should show the query welcome page
### Test
For more details see [spring-boot/query](spring-boot/query).
##### Spring Boot Command Service (Console window 3)
1. Start the Spring Boot command service:
```
cd ddd-cqrs-4-java-example/spring-boot/command
./mvnw spring-boot:run
```
2. Opening [http://localhost:8081/](http://localhost:8081/) should show the command welcome page
For more details see [spring-boot/command](spring-boot/command).
### Verify projection and query data
1. Open [http://localhost:2113/](http://localhost:2113/) to access the event store UI (User: admin / Password: changeit)
You should see a projection named "qry-person-stream" when you click on "Projections" in the top menu.
2. Opening [http://localhost:8080/persons](http://localhost:8080/persons) should show an empty JSON array
3. Open a console (Ubuntu shortcut = ctrl alt t)
4. Change into the demo directory and execute a command using cURL (See [shell script](demo/create-person-command.sh) and [command](demo/create-person-command.json))
```
cd ddd-cqrs-4-java-example/demo
./create-person-command.sh
```
Command console should show something like
```
Update aggregate: id=PERSON 84565d62-115e-4502-b7c9-38ad69c64b05, version=-1, nextVersion=0
```
Query console should show something like
```
PersonCreatedEventHandler ... Handle PersonCreatedEvent: Person 'Peter Parker' was created
```
4. Refreshing [http://localhost:8080/persons](http://localhost:8080/persons) should show
### Execute a test command (Console window 4)
Change into the demo directory and execute a command using cURL (See [shell script](demo/create-person-command.sh) and [command](demo/create-person-command.json))
```
cd ddd-cqrs-4-java-example/demo
./create-person-command.sh
```
Command service (Console window 3) should show something like
```
Update aggregate: id=PERSON 84565d62-115e-4502-b7c9-38ad69c64b05, version=-1, nextVersion=0
```
Query service (Console window 2) should show something like
```
PersonCreatedEventHandler ... Handle PersonCreatedEvent: Person 'Peter Parker' was created
```
### Verify the query data was updated
1. Refreshing [http://localhost:8080/persons](http://localhost:8080/persons) should show
```json
[{"id":"84565d62-115e-4502-b7c9-38ad69c64b05","name":"Peter Parker"}]
```
5. Opening [http://localhost:8080/persons/84565d62-115e-4502-b7c9-38ad69c64b05](http://localhost:8080/persons/84565d62-115e-4502-b7c9-38ad69c64b05) should show
2. Opening [http://localhost:8080/persons/84565d62-115e-4502-b7c9-38ad69c64b05](http://localhost:8080/persons/84565d62-115e-4502-b7c9-38ad69c64b05) should show
```json
{"id":"84565d62-115e-4502-b7c9-38ad69c64b05","name":"Peter Parker"}
6. The event sourced data of the person aggregate could be found in a stream named [PERSON-84565d62-115e-4502-b7c9-38ad69c64b05](http://localhost:2113/web/index.html#/streams/PERSON-84565d62-115e-4502-b7c9-38ad69c64b05)
3. The event sourced data of the person aggregate could be found in a stream named [PERSON-84565d62-115e-4502-b7c9-38ad69c64b05](http://localhost:2113/web/index.html#/streams/PERSON-84565d62-115e-4502-b7c9-38ad69c64b05)
### Stop Event Store and Maria DB and clean up

View File

@@ -12,13 +12,12 @@
*/
package org.fuin.cqrs4j.example.aggregates;
import jakarta.validation.constraints.NotNull;
import javax.validation.constraints.NotNull;
import org.fuin.cqrs4j.example.shared.PersonId;
import org.fuin.cqrs4j.example.shared.PersonName;
import org.fuin.objects4j.common.ExceptionShortIdentifable;
/**
* A name that should be unique does already exist.
*/
@@ -26,11 +25,11 @@ public final class DuplicatePersonNameException extends Exception implements Exc
private static final long serialVersionUID = 1000L;
private static final String SHORT_ID = "DUPLICATE_PERSON_NAME";
private PersonId personId;
private static final String SHORT_ID = "DUPLICATE_PERSON_NAME";
private PersonName name;
private final PersonId personId;
private final PersonName name;
/**
* Constructor with mandatory data.
@@ -64,9 +63,9 @@ public final class DuplicatePersonNameException extends Exception implements Exc
return name;
}
@Override
public final String getShortId() {
return SHORT_ID;
}
@Override
public final String getShortId() {
return SHORT_ID;
}
}

View File

@@ -15,7 +15,7 @@ package org.fuin.cqrs4j.example.aggregates;
import java.io.Serializable;
import java.util.Optional;
import jakarta.validation.constraints.NotNull;
import javax.validation.constraints.NotNull;
import org.fuin.cqrs4j.example.shared.PersonCreatedEvent;
import org.fuin.cqrs4j.example.shared.PersonId;

View File

@@ -12,13 +12,13 @@
*/
package org.fuin.cqrs4j.example.aggregates;
import org.fuin.objects4j.common.NotThreadSafe;
import jakarta.validation.constraints.NotNull;
import javax.validation.constraints.NotNull;
import org.fuin.cqrs4j.example.shared.PersonId;
import org.fuin.ddd4j.ddd.EntityType;
import org.fuin.ddd4j.esrepo.EventStoreRepository;
import org.fuin.esc.api.EventStore;
import org.fuin.objects4j.common.NotThreadSafe;
/**
* Event sourced repository for storing a {@link Person} aggregate.

View File

@@ -12,7 +12,7 @@ import org.fuin.cqrs4j.example.shared.PersonName;
import org.junit.Test;
/**
* Test for the {@link Person} class.
* Test for the {@link Person} class.
*/
public class PersonTest {
@@ -24,7 +24,9 @@ public class PersonTest {
final PersonName personName = new PersonName("Peter Parker");
// TEST
final Person testee = new Person(personId, personName, pid -> { return Optional.empty(); }) ;
final Person testee = new Person(personId, personName, pid -> {
return Optional.empty();
});
// VERIFY
assertThat(testee.getUncommittedChanges()).hasSize(1);
@@ -34,8 +36,7 @@ public class PersonTest {
assertThat(event.getName()).isEqualTo(personName);
}
@Test
public final void testCreateDuplicateName() {
@@ -46,12 +47,14 @@ public class PersonTest {
// TEST & VERIFY
try {
new Person(personId, personName, pid -> { return Optional.of(otherId); }) ;
new Person(personId, personName, pid -> {
return Optional.of(otherId);
});
fail("Excpected duplicate name exception");
} catch (final DuplicatePersonNameException ex) {
assertThat(ex.getMessage()).isEqualTo("The name 'Peter Parker' already exists: " + otherId);
}
}
}

View File

@@ -3,7 +3,7 @@ version: '2.4'
services:
eventstore:
image: eventstore/eventstore:release-4.1.3
image: eventstore/eventstore:release-5.0.9
container_name: "cqrs4j-quarkus-example-eventstore"
ports:
- "1113:1113"

View File

@@ -120,24 +120,26 @@
<dependency>
<groupId>jakarta.enterprise</groupId>
<artifactId>jakarta.enterprise.cdi-api</artifactId>
<version>3.0.0</version>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se-core</artifactId>
<version>4.0.2.Final</version>
<version>3.1.5.SP1</version>
</dependency>
<dependency>
<groupId>org.eclipse.microprofile.config</groupId>
<artifactId>microprofile-config-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>io.smallrye.config</groupId>
<artifactId>smallrye-config</artifactId>
</dependency>
<dependency>
<groupId>io.smallrye.config</groupId>
<artifactId>smallrye-config</artifactId>
<version>2.4.2</version>
</dependency>
<dependency>
<groupId>jakarta.json</groupId>

View File

@@ -14,11 +14,11 @@ package org.fuin.cqrs4j.example.javasecdi.cmd.app;
import java.util.UUID;
import jakarta.enterprise.context.control.ActivateRequestContext;
import jakarta.enterprise.inject.Instance;
import jakarta.enterprise.inject.se.SeContainer;
import jakarta.enterprise.inject.se.SeContainerInitializer;
import jakarta.inject.Inject;
import javax.enterprise.context.control.ActivateRequestContext;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;
import javax.inject.Inject;
import org.fuin.cqrs4j.example.javasecdi.cmd.domain.Person;
import org.fuin.cqrs4j.example.javasecdi.cmd.domain.PersonRepository;
@@ -37,7 +37,7 @@ import org.slf4j.LoggerFactory;
public class CmdExampleApp {
private static final Logger LOG = LoggerFactory.getLogger(CmdExampleApp.class);
@Inject
private Instance<EventStore> eventStoreInstance;
@@ -48,7 +48,7 @@ public class CmdExampleApp {
public void execute() {
LOG.info("Executing...");
try (final EventStore eventStore = eventStoreInstance.get()) {
final PersonId id = new PersonId(UUID.fromString("f645969a-402d-41a9-882b-d2d8000d0f43"));
@@ -61,7 +61,7 @@ public class CmdExampleApp {
repo.update(person);
LOG.info("Updated event store...");
} catch (final Exception ex) {
throw new RuntimeException("Error saving person aggregate into event store", ex);
}
@@ -81,16 +81,16 @@ public class CmdExampleApp {
new LogbackStandalone().init(args, new NewLogConfigFileParams("org.fuin.cqrs4j.example.javasecdi", "logback"));
LOG.info("Start example");
try (final SeContainer container = SeContainerInitializer.newInstance().initialize()) {
final CmdExampleApp app = container.select(CmdExampleApp.class).get();
app.execute();
}
LOG.info("Finished example");
System.exit(0);
} catch (final RuntimeException ex) {
ex.printStackTrace(System.err);
System.exit(1);

View File

@@ -1,6 +1,6 @@
package org.fuin.cqrs4j.example.javasecdi.cmd.domain;
import jakarta.validation.constraints.NotNull;
import javax.validation.constraints.NotNull;
import org.fuin.cqrs4j.example.shared.PersonId;
import org.fuin.cqrs4j.example.shared.PersonName;

View File

@@ -2,7 +2,7 @@ package org.fuin.cqrs4j.example.javasecdi.cmd.domain;
import java.io.Serializable;
import jakarta.validation.constraints.NotNull;
import javax.validation.constraints.NotNull;
import org.fuin.cqrs4j.example.shared.PersonCreatedEvent;
import org.fuin.cqrs4j.example.shared.PersonId;
@@ -45,7 +45,8 @@ public class Person extends AbstractAggregateRoot<PersonId> implements Serializa
* @throws DuplicatePersonNameException
* The name already exists for another person.
*/
public Person(@NotNull final PersonId id, @NotNull final PersonName name, final PersonService service) throws DuplicatePersonNameException {
public Person(@NotNull final PersonId id, @NotNull final PersonName name, final PersonService service)
throws DuplicatePersonNameException {
super();
// VERIFY PRECONDITIONS

View File

@@ -1,7 +1,7 @@
package org.fuin.cqrs4j.example.javasecdi.cmd.domain;
import org.fuin.objects4j.common.NotThreadSafe;
import jakarta.validation.constraints.NotNull;
import javax.validation.constraints.NotNull;
import org.fuin.cqrs4j.example.shared.PersonId;
import org.fuin.ddd4j.ddd.EntityType;

View File

@@ -1,8 +1,8 @@
package org.fuin.cqrs4j.example.javasecdi.cmd.domain;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.inject.Produces;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Produces;
import org.fuin.esc.api.EventStore;

View File

@@ -1,20 +1,20 @@
package org.fuin.cqrs4j.example.javasecdi.qry.app;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Disposes;
import jakarta.enterprise.inject.Produces;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Disposes;
import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.apache.deltaspike.jpa.api.transaction.TransactionScoped;
@ApplicationScoped
public class QryEntityManagerProducer {
private EntityManagerFactory emf;
@Produces
@Produces
@TransactionScoped
public EntityManager create() {
if (emf == null) {

View File

@@ -17,8 +17,8 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import jakarta.enterprise.inject.se.SeContainer;
import jakarta.enterprise.inject.se.SeContainerInitializer;
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;
import javax.inject.Inject;
import org.fuin.ext4logback.LogbackStandalone;

View File

@@ -4,10 +4,10 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.ThreadFactory;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.inject.Disposes;
import jakarta.enterprise.inject.Produces;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Disposes;
import javax.enterprise.inject.Produces;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;

View File

@@ -4,8 +4,8 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
/**
* CDI producer that creates an {@link ScheduledExecutorService}.
@@ -16,7 +16,9 @@ public class QryScheduledExecutorService {
@Produces
@ApplicationScoped
public ScheduledExecutorService create(ThreadFactory threadFactory) {
return new ScheduledThreadPoolExecutor(1, threadFactory, (runnable, executor) -> { System.out.println("Execution blocked"); });
return new ScheduledThreadPoolExecutor(1, threadFactory, (runnable, executor) -> {
System.out.println("Execution blocked");
});
}
}

View File

@@ -3,8 +3,8 @@ package org.fuin.cqrs4j.example.javasecdi.qry.app;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
/**
* Creates an thread factory.

View File

@@ -1,7 +1,7 @@
package org.fuin.cqrs4j.example.javasecdi.qry.app;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Event;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Event;
import javax.inject.Inject;
@ApplicationScoped

View File

@@ -1,10 +1,10 @@
package org.fuin.cqrs4j.example.javasecdi.qry.domain;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;

View File

@@ -1,6 +1,6 @@
package org.fuin.cqrs4j.example.javasecdi.qry.handler;
import jakarta.enterprise.context.ApplicationScoped;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import org.apache.deltaspike.jpa.api.transaction.Transactional;
@@ -18,7 +18,7 @@ import org.slf4j.LoggerFactory;
*/
@ApplicationScoped
public class PersonCreatedEventHandler implements EventHandler<PersonCreatedEvent> {
private static final Logger LOG = LoggerFactory.getLogger(PersonCreatedEventHandler.class);
@Inject

View File

@@ -1,6 +1,6 @@
package org.fuin.cqrs4j.example.javasecdi.qry.handler;
import jakarta.enterprise.context.ApplicationScoped;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import org.apache.deltaspike.jpa.api.transaction.Transactional;
@@ -16,7 +16,7 @@ import org.slf4j.LoggerFactory;
public class QryEventChunkHandler {
private static final Logger LOG = LoggerFactory.getLogger(QryEventChunkHandler.class);
/** Unique name of the event store projection that is used. */
public static final ProjectionStreamId PROJECTION_STREAM_ID = new ProjectionStreamId("qry-person-stream");

View File

@@ -1,7 +1,7 @@
package org.fuin.cqrs4j.example.javasecdi.qry.handler;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import org.fuin.cqrs4j.EventDispatcher;
import org.fuin.cqrs4j.SimpleEventDispatcher;

View File

@@ -1,10 +1,10 @@
package org.fuin.cqrs4j.example.javasecdi.qry.handler;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import org.fuin.esc.api.SimpleStreamId;
import org.fuin.esc.api.StreamId;

View File

@@ -1,6 +1,6 @@
package org.fuin.cqrs4j.example.javasecdi.qry.handler;
import jakarta.validation.constraints.NotNull;
import javax.validation.constraints.NotNull;
import org.apache.deltaspike.data.api.AbstractEntityRepository;
import org.apache.deltaspike.data.api.Repository;

View File

@@ -8,7 +8,7 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.Semaphore;
import jakarta.enterprise.event.ObservesAsync;
import javax.enterprise.event.ObservesAsync;
import javax.inject.Inject;
import org.fuin.cqrs4j.EventDispatcher;

View File

@@ -12,7 +12,7 @@
*/
package org.fuin.cqrs4j.example.javasecdi.shared.app;
import jakarta.enterprise.context.ApplicationScoped;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import org.eclipse.microprofile.config.inject.ConfigProperty;
@@ -68,14 +68,19 @@ public class SharedConfig {
/**
* Constructor with all data.
*
* @param eventStoreHost Host.
* @param eventStoreHttpPort HTTP port
* @param eventStoreTcpPort TCP port.
* @param eventStoreUser User.
* @param eventStorePassword Password.
* @param eventStoreHost
* Host.
* @param eventStoreHttpPort
* HTTP port
* @param eventStoreTcpPort
* TCP port.
* @param eventStoreUser
* User.
* @param eventStorePassword
* Password.
*/
public SharedConfig(final String eventStoreHost, final int eventStoreHttpPort, final int eventStoreTcpPort,
final String eventStoreUser, final String eventStorePassword) {
public SharedConfig(final String eventStoreHost, final int eventStoreHttpPort, final int eventStoreTcpPort, final String eventStoreUser,
final String eventStorePassword) {
super();
this.eventStoreHost = eventStoreHost;
this.eventStoreHttpPort = eventStoreHttpPort;

View File

@@ -14,8 +14,8 @@ package org.fuin.cqrs4j.example.javasecdi.shared.app;
import java.util.concurrent.Executors;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import com.github.msemys.esjc.EventStore;
import com.github.msemys.esjc.EventStoreBuilder;

View File

@@ -2,10 +2,10 @@ package org.fuin.cqrs4j.example.javasecdi.shared.app;
import java.nio.charset.Charset;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.context.RequestScoped;
import jakarta.enterprise.inject.Disposes;
import jakarta.enterprise.inject.Produces;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Disposes;
import javax.enterprise.inject.Produces;
import org.fuin.esc.api.EventStore;
import org.fuin.esc.esjc.ESJCEventStore;

View File

@@ -15,8 +15,8 @@ package org.fuin.cqrs4j.example.javasecdi.shared.app;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
/**
* Creates an executor service.

View File

@@ -1,7 +1,7 @@
package org.fuin.cqrs4j.example.javasecdi.shared.app;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import org.fuin.esc.spi.JsonbDeSerializer;
import org.fuin.esc.spi.SerDeserializerRegistry;
@@ -24,8 +24,7 @@ public class SharedSerDeserializerRegistryFactory {
final JsonbDeSerializer jsonbDeSer = SharedUtils.createJsonbDeSerializer();
// Registry connects the type with the appropriate serializer and de-serializer
final SerDeserializerRegistry serDeserRegistry = SharedUtils.createSerDeserializerRegistry(typeRegistry,
jsonbDeSer);
final SerDeserializerRegistry serDeserRegistry = SharedUtils.createSerDeserializerRegistry(typeRegistry, jsonbDeSer);
return serDeserRegistry;

View File

@@ -19,6 +19,8 @@ package org.fuin.cqrs4j.example.javasecdi.shared.app;
import java.nio.charset.Charset;
import javax.json.bind.adapter.JsonbAdapter;
import org.eclipse.yasson.FieldAccessStrategy;
import org.fuin.cqrs4j.example.shared.PersonCreatedEvent;
import org.fuin.cqrs4j.example.shared.PersonId;
@@ -37,9 +39,6 @@ import org.fuin.esc.spi.SerializedDataTypeRegistry;
import org.fuin.esc.spi.SimpleSerializedDataTypeRegistry;
import org.fuin.esc.spi.SimpleSerializerDeserializerRegistry;
import jakarta.json.bind.adapter.JsonbAdapter;
/**
* Utility code shared between command (write) and query (read) module.
*/
@@ -51,16 +50,14 @@ public final class SharedUtils {
/** All JSON-B adapters from this module. */
public static JsonbAdapter<?, ?>[] JSONB_ADAPTERS = new JsonbAdapter<?, ?>[] { new EventIdConverter(),
new EntityIdPathConverter(new SharedEntityIdFactory()), new PersonId.Converter(),
new PersonName.Converter() };
new EntityIdPathConverter(new SharedEntityIdFactory()), new PersonId.Converter(), new PersonName.Converter() };
private SharedUtils() {
throw new UnsupportedOperationException("It is not allowed to create an instance of a utiliy class");
}
/**
* Create a registry that allows finding types (classes) based on their unique
* type name.
* Create a registry that allows finding types (classes) based on their unique type name.
*
* @return New instance.
*/
@@ -84,11 +81,12 @@ public final class SharedUtils {
}
/**
* Creates a registry that connects the type with the appropriate serializer and
* de-serializer.
* Creates a registry that connects the type with the appropriate serializer and de-serializer.
*
* @param typeRegistry Type registry (Mapping from type name to class).
* @param jsonbDeSer JSON-B serializer/deserializer to use.
* @param typeRegistry
* Type registry (Mapping from type name to class).
* @param jsonbDeSer
* JSON-B serializer/deserializer to use.
*
* @return New instance.
*/
@@ -120,9 +118,8 @@ public final class SharedUtils {
public static JsonbDeSerializer createJsonbDeSerializer() {
return JsonbDeSerializer.builder().withSerializers(EscSpiUtils.createEscJsonbSerializers())
.withDeserializers(EscSpiUtils.createEscJsonbDeserializers())
.withAdapters(JSONB_ADAPTERS).withPropertyVisibilityStrategy(new FieldAccessStrategy())
.withEncoding(Charset.forName("utf-8")).build();
.withDeserializers(EscSpiUtils.createEscJsonbDeserializers()).withAdapters(JSONB_ADAPTERS)
.withPropertyVisibilityStrategy(new FieldAccessStrategy()).withEncoding(Charset.forName("utf-8")).build();
}
@@ -138,8 +135,10 @@ public final class SharedUtils {
/**
* Constructor with all data.
*
* @param type Type.
* @param clasz Class.
* @param type
* Type.
* @param clasz
* Class.
*/
public TypeClass(final SerializedDataType type, final Class<?> clasz) {
super();

36
mvnw vendored
View File

@@ -8,7 +8,7 @@
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
@@ -19,7 +19,7 @@
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven2 Start Up Batch script
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
@@ -114,7 +114,6 @@ if $mingw ; then
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
# TODO classpath?
fi
if [ -z "$JAVA_HOME" ]; then
@@ -212,7 +211,11 @@ else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
@@ -221,22 +224,38 @@ else
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
wget "$jarUrl" -O "$wrapperJarPath"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
curl -o "$wrapperJarPath" "$jarUrl"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
@@ -277,6 +296,11 @@ if $cygwin; then
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \

45
mvnw.cmd vendored
View File

@@ -7,7 +7,7 @@
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@@ -18,7 +18,7 @@
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven2 Start Up Batch script
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@@ -26,7 +26,7 @@
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@@ -37,7 +37,7 @@
@echo off
@REM set title of command window
title %0
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
@@ -120,23 +120,44 @@ SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
echo Found %WRAPPER_JAR%
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
echo Finished downloading %WRAPPER_JAR%
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end

47
pom.xml
View File

@@ -3,6 +3,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.fuin.cqrs4j.example</groupId>
<artifactId>cqrs4j-example-root</artifactId>
<version>0.2.0-SNAPSHOT</version>
@@ -14,7 +15,7 @@
<maven.compiler.parameters>true</maven.compiler.parameters>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<esc.version>0.5.0-SNAPSHOT</esc.version>
<esc.version>0.4.2</esc.version>
</properties>
<modules>
@@ -32,19 +33,19 @@
<dependency>
<groupId>org.fuin</groupId>
<artifactId>ddd-4-java</artifactId>
<version>0.4.0-SNAPSHOT</version>
<version>0.4.0</version>
</dependency>
<dependency>
<groupId>org.fuin</groupId>
<artifactId>cqrs-4-java</artifactId>
<version>0.4.0-SNAPSHOT</version>
<version>0.4.0</version>
</dependency>
<dependency>
<groupId>org.fuin</groupId>
<artifactId>objects4j</artifactId>
<version>0.8.0-SNAPSHOT</version>
<version>0.7.1</version>
</dependency>
<dependency>
@@ -98,7 +99,7 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<version>1.2.5</version>
</dependency>
<dependency>
@@ -110,49 +111,37 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
<version>1.7.32</version>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.0.0</version>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>jakarta.json.bind</groupId>
<artifactId>jakarta.json.bind-api</artifactId>
<version>2.0.0</version>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>3.0.0</version>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.eclipse.microprofile.config</groupId>
<artifactId>microprofile-config-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>io.smallrye.config</groupId>
<artifactId>smallrye-config</artifactId>
<version>2.4.4</version>
</dependency>
<dependency>
<groupId>jakarta.json</groupId>
<artifactId>jakarta.json-api</artifactId>
<version>2.0.1</version>
<version>1.1.6</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.4.26.Final</version>
<version>5.5.7.Final</version>
</dependency>
<dependency>
@@ -176,7 +165,7 @@
<dependency>
<groupId>org.fuin</groupId>
<artifactId>units4j</artifactId>
<version>0.10.0-SNAPSHOT</version>
<version>0.9.1</version>
</dependency>
<dependency>
@@ -194,7 +183,7 @@
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>7.0.1.Final</version>
<version>6.2.0.Final</version>
</dependency>
<dependency>
@@ -206,19 +195,19 @@
<dependency>
<groupId>org.eclipse</groupId>
<artifactId>yasson</artifactId>
<version>2.0.2</version>
<version>1.0.8</version>
</dependency>
<dependency>
<groupId>jakarta.mail</groupId>
<artifactId>jakarta.mail-api</artifactId>
<version>2.0.1</version>
<version>1.6.7</version>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>jakarta.mail</artifactId>
<version>1.6.4</version>
<version>1.6.7</version>
</dependency>
</dependencies>
@@ -310,7 +299,7 @@
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.34.1</version>
<version>0.37.0</version>
</plugin>
</plugins>

View File

@@ -0,0 +1,117 @@
/*
* Copyright 2007-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}

Binary file not shown.

View File

@@ -0,0 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

View File

@@ -21,7 +21,7 @@ Make sure you installed everything as described [here](../../../../).
## *OPTIONAL* Build and run the command microservice in native mode
1. Make sure you have enough memory (~6-8 GB) on your PC or VM
2. Open a console (Ubuntu shortcut = <ctrl><alt><t>)
2. Open a console (Ubuntu shortcut = ctrl alt t)
3. Build the native executable
```
cd command

View File

@@ -19,7 +19,7 @@
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven2 Start Up Batch script
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
@@ -212,9 +212,9 @@ else
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
@@ -246,7 +246,7 @@ else
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"

View File

@@ -18,7 +18,7 @@
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven2 Start Up Batch script
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@@ -26,7 +26,7 @@
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@@ -120,7 +120,7 @@ SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
@@ -134,7 +134,7 @@ if exist %WRAPPER_JAR% (
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...

View File

@@ -44,6 +44,12 @@
<artifactId>jakarta.security.jacc-api</artifactId>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.9.0</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-context-propagation</artifactId>
@@ -81,6 +87,11 @@
<artifactId>jakarta.mail-api</artifactId>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>jakarta.mail</artifactId>
</dependency>
<!-- test -->
<dependency>
@@ -104,6 +115,7 @@
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.version}</version>
<executions>
<execution>
<goals>

View File

@@ -40,8 +40,8 @@ public class AggregateAlreadyExistsExceptionMapper implements ExceptionMapper<Ag
LOG.info("{} {}", ex.getShortId(), ex.getMessage());
return Response.status(Status.CONFLICT).entity(SimpleResult.error(ex.getShortId(), ex.getMessage()))
.type(headers.getMediaType()).build();
return Response.status(Status.CONFLICT).entity(SimpleResult.error(ex.getShortId(), ex.getMessage())).type(headers.getMediaType())
.build();
}
}

View File

@@ -40,8 +40,8 @@ public class AggregateDeletedExceptionMapper implements ExceptionMapper<Aggregat
LOG.info("{} {}", ex.getShortId(), ex.getMessage());
return Response.status(Status.GONE).entity(SimpleResult.error(ex.getShortId(), ex.getMessage()))
.type(headers.getMediaType()).build();
return Response.status(Status.GONE).entity(SimpleResult.error(ex.getShortId(), ex.getMessage())).type(headers.getMediaType())
.build();
}
}

View File

@@ -40,8 +40,8 @@ public class AggregateNotFoundExceptionMapper implements ExceptionMapper<Aggrega
LOG.info("{} {}", ex.getShortId(), ex.getMessage());
return Response.status(Status.NOT_FOUND).entity(SimpleResult.error(ex.getShortId(), ex.getMessage()))
.type(headers.getMediaType()).build();
return Response.status(Status.NOT_FOUND).entity(SimpleResult.error(ex.getShortId(), ex.getMessage())).type(headers.getMediaType())
.build();
}
}

View File

@@ -40,8 +40,8 @@ public class AggregateVersionConflictExceptionMapper implements ExceptionMapper<
LOG.info("{} {}", ex.getShortId(), ex.getMessage());
return Response.status(Status.CONFLICT).entity(SimpleResult.error(ex.getShortId(), ex.getMessage()))
.type(headers.getMediaType()).build();
return Response.status(Status.CONFLICT).entity(SimpleResult.error(ex.getShortId(), ex.getMessage())).type(headers.getMediaType())
.build();
}
}

View File

@@ -35,13 +35,13 @@ public class AggregateVersionNotFoundExceptionMapper implements ExceptionMapper<
@Context
private HttpHeaders headers;
@Override
@Override
public Response toResponse(final AggregateVersionNotFoundException ex) {
LOG.error("{} {}", ex.getShortId(), ex.getMessage());
return Response.status(Status.NOT_FOUND).entity(SimpleResult.error(ex.getShortId(), ex.getMessage()))
.type(headers.getMediaType()).build();
return Response.status(Status.NOT_FOUND).entity(SimpleResult.error(ex.getShortId(), ex.getMessage())).type(headers.getMediaType())
.build();
}
}

View File

@@ -17,8 +17,8 @@ import java.util.List;
import java.util.Set;
import org.fuin.objects4j.common.Nullable;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
@@ -55,7 +55,7 @@ public class ConstraintViolationExceptionMapper implements ExceptionMapper<Const
}
private static String asString(@Nullable final Set<ConstraintViolation<?>> constraintViolations) {
if (constraintViolations == null || constraintViolations.size() == 0) {
if (constraintViolations == null || constraintViolations.isEmpty()) {
return "";
}
final List<String> list = new ArrayList<>();

View File

@@ -16,9 +16,9 @@ import java.util.Optional;
import java.util.Set;
import javax.inject.Inject;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.Validator;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
@@ -48,7 +48,7 @@ public class PersonResource {
@Context
UriInfo uriInfo;
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@@ -64,18 +64,18 @@ public class PersonResource {
try {
// Create aggregate
final Person person = new Person(cmd.getAggregateRootId(), cmd.getName(), (name) -> {
final Person person = new Person(cmd.getAggregateRootId(), cmd.getName(), name -> {
// TODO Execute a call to the query side to verify if the name already exists
return Optional.empty();
});
repo.add(person);
// Send OK response
return Response.ok(SimpleResult.ok()).build();
return Response.ok(SimpleResult.ok()).build();
} catch (final DuplicatePersonNameException ex) {
throw new CommandExecutionFailedException(ex);
}
}
}

View File

@@ -12,9 +12,9 @@
*/
package org.fuin.cqrs4j.example.quarkus.command.domain;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.inject.Produces;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Produces;
import org.fuin.cqrs4j.example.aggregates.PersonRepository;
import org.fuin.esc.esjc.IESJCEventStore;

View File

@@ -3,7 +3,8 @@
quarkus.http.port=8081
quarkus.native.additional-build-args=-H:ReflectionConfigurationFiles=reflection-config.json,--report-unsupported-elements-at-runtime
quarkus.native.additional-build-args=-H:ReflectionConfigurationFiles=reflection-config.json,--initialize-at-run-time=org.apache.http.impl.auth.NTLMEngineImpl
quarkus.native.native-image-xmx=8192m
quarkus.index-dependency.ddd4j.group-id=org.fuin
quarkus.index-dependency.ddd4j.artifact-id=ddd-4-java

View File

@@ -12,7 +12,7 @@ import java.util.List;
import java.util.UUID;
import javax.inject.Inject;
import jakarta.json.bind.Jsonb;
import javax.json.bind.Jsonb;
import org.fuin.cqrs4j.ResultType;
import org.fuin.cqrs4j.SimpleResult;
@@ -31,37 +31,28 @@ import io.quarkus.test.junit.QuarkusTest;
import io.restassured.http.ContentType;
@QuarkusTest
public class PersonResourceIT {
class PersonResourceIT {
@Inject
IESJCEventStore eventStore;
@Inject
Jsonb jsonb;
@Test
public void testCreate() {
void testCreate() {
// PREPARE
final PersonId personId = new PersonId(UUID.randomUUID());
final PersonName personName = new PersonName("Peter Parker");
final CreatePersonCommand cmd = new CreatePersonCommand(personId, personName);
final String json = jsonb.toJson(cmd);
// TEST & VERIFY
final SimpleResult result =
given()
.accept(ContentType.JSON)
.contentType(ContentType.JSON)
.body(json)
.when()
.post("/persons/create")
.then()
.statusCode(200)
.extract()
.as(SimpleResult.class);
final SimpleResult result = given().accept(ContentType.JSON).contentType(ContentType.JSON).body(json).when().post("/persons/create")
.then().statusCode(200).extract().as(SimpleResult.class);
assertThat(result.getType(), is(equalTo(ResultType.OK)));
final SimpleStreamId personStreamId = new SimpleStreamId(PersonId.TYPE + "-" + personId);
final StreamEventsSlice slice = eventStore.readEventsForward(personStreamId, 0, 1);
final List<CommonEvent> events = slice.getEvents();
@@ -71,7 +62,7 @@ public class PersonResourceIT {
final PersonCreatedEvent event = (PersonCreatedEvent) ce.getData();
assertThat(event.getEntityId(), is(equalTo(personId)));
assertThat(event.getName(), is(equalTo(personName)));
}
}

View File

@@ -16,7 +16,7 @@
<packaging>pom</packaging>
<properties>
<quarkus.version>2.1.3.Final</quarkus.version>
<quarkus.version>2.2.1.Final</quarkus.version>
<eventstore.version>5.0.9</eventstore.version>
</properties>
@@ -25,8 +25,8 @@
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-universe-bom</artifactId>
<groupId>io.quarkus.platform</groupId>
<artifactId>quarkus-bom</artifactId>
<version>${quarkus.version}</version>
<type>pom</type>
<scope>import</scope>
@@ -35,13 +35,13 @@
<dependency>
<groupId>jakarta.enterprise</groupId>
<artifactId>jakarta.enterprise.cdi-api</artifactId>
<version>3.0.0</version>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se-core</artifactId>
<version>3.1.5.SP1</version>
<version>3.1.8.Final</version>
</dependency>
</dependencies>

View File

@@ -0,0 +1,117 @@
/*
* Copyright 2007-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}

Binary file not shown.

View File

@@ -0,0 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

View File

@@ -51,7 +51,7 @@ mariadb:10.4
## *OPTIONAL* Build and run the query microservice in native mode
1. Make sure you have enough memory (~6-8 GB) on your PC or VM
2. Open a console (Ubuntu shortcut = <ctrl><alt><t>)
2. Open a console (Ubuntu shortcut = ctrl alt t)
3. Build the native executable
```
cd query

8
quarkus/query/mvnw vendored
View File

@@ -19,7 +19,7 @@
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven2 Start Up Batch script
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
@@ -212,9 +212,9 @@ else
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
@@ -246,7 +246,7 @@ else
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"

View File

@@ -18,7 +18,7 @@
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven2 Start Up Batch script
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@@ -26,7 +26,7 @@
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@@ -120,7 +120,7 @@ SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
@@ -134,7 +134,7 @@ if exist %WRAPPER_JAR% (
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...

View File

@@ -54,6 +54,12 @@
<artifactId>jakarta.security.jacc-api</artifactId>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.9.0</version>
</dependency>
<dependency>
<groupId>org.fuin.cqrs4j.example</groupId>
<artifactId>cqrs4j-example-aggregates</artifactId>
@@ -71,6 +77,11 @@
<artifactId>esc-eshttp</artifactId>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>jakarta.mail</artifactId>
</dependency>
<!-- test -->
<dependency>

View File

@@ -15,7 +15,7 @@ package org.fuin.cqrs4j.example.quarkus.query.api;
import java.util.List;
import javax.inject.Inject;
import jakarta.persistence.EntityManager;
import javax.persistence.EntityManager;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

View File

@@ -12,8 +12,8 @@
*/
package org.fuin.cqrs4j.example.quarkus.query.app;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Event;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Event;
import javax.inject.Inject;
import io.quarkus.scheduler.Scheduled;

View File

@@ -12,11 +12,11 @@
*/
package org.fuin.cqrs4j.example.quarkus.query.views.common;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import org.fuin.esc.api.SimpleStreamId;
import org.fuin.esc.api.StreamId;

View File

@@ -12,10 +12,10 @@
*/
package org.fuin.cqrs4j.example.quarkus.query.views.common;
import jakarta.enterprise.context.ApplicationScoped;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import jakarta.persistence.EntityManager;
import jakarta.validation.constraints.NotNull;
import javax.persistence.EntityManager;
import javax.validation.constraints.NotNull;
import org.fuin.cqrs4j.ProjectionService;
import org.fuin.esc.api.StreamId;
@@ -27,12 +27,13 @@ import org.fuin.objects4j.common.Contract;
@ApplicationScoped
public class QryProjectionPositionRepository implements ProjectionService {
private static final String ARG_STREAM_ID = "streamId";
@Inject
EntityManager em;
@Override
public void resetProjectionPosition(@NotNull final StreamId streamId) {
Contract.requireArgNotNull("streamId", streamId);
Contract.requireArgNotNull(ARG_STREAM_ID, streamId);
final QryProjectionPosition pos = em.find(QryProjectionPosition.class, streamId.asString());
if (pos != null) {
pos.setNextPosition(0L);
@@ -41,7 +42,7 @@ public class QryProjectionPositionRepository implements ProjectionService {
@Override
public Long readProjectionPosition(@NotNull StreamId streamId) {
Contract.requireArgNotNull("streamId", streamId);
Contract.requireArgNotNull(ARG_STREAM_ID, streamId);
final QryProjectionPosition pos = em.find(QryProjectionPosition.class, streamId.asString());
if (pos == null) {
return 0L;
@@ -51,7 +52,7 @@ public class QryProjectionPositionRepository implements ProjectionService {
@Override
public void updateProjectionPosition(@NotNull StreamId streamId, @NotNull Long nextEventNumber) {
Contract.requireArgNotNull("streamId", streamId);
Contract.requireArgNotNull(ARG_STREAM_ID, streamId);
Contract.requireArgNotNull("nextEventNumber", nextEventNumber);
final QryProjectionPosition pos = em.find(QryProjectionPosition.class, streamId.asString());
if (pos == null) {

View File

@@ -14,5 +14,5 @@ package org.fuin.cqrs4j.example.quarkus.query.views;
/**
* Contains the views used in this query application. A view never uses code of another view, means all views are completely independent of
* each other. As an exception, the 'commons' package has some small classes that are not view specific.
* each other. As an exception, the 'commons' package has some small classes that are not view specific.
*/

View File

@@ -12,9 +12,9 @@
*/
package org.fuin.cqrs4j.example.quarkus.query.views.personlist;
import jakarta.enterprise.context.ApplicationScoped;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import jakarta.persistence.EntityManager;
import javax.persistence.EntityManager;
import org.fuin.cqrs4j.EventHandler;
import org.fuin.cqrs4j.example.shared.PersonCreatedEvent;
@@ -28,12 +28,12 @@ import org.slf4j.LoggerFactory;
*/
@ApplicationScoped
public class PersonCreatedEventHandler implements EventHandler<PersonCreatedEvent> {
private static final Logger LOG = LoggerFactory.getLogger(PersonCreatedEventHandler.class);
@Inject
EntityManager em;
@Override
public EventType getEventType() {
return PersonCreatedEvent.TYPE;
@@ -41,7 +41,7 @@ public class PersonCreatedEventHandler implements EventHandler<PersonCreatedEven
@Override
public void handle(final PersonCreatedEvent event) {
LOG.info("Handle {}: {}", event.getClass().getSimpleName() , event);
LOG.info("Handle {}: {}", event.getClass().getSimpleName(), event);
final PersonId personId = event.getEntityId();
if (em.find(PersonListEntry.class, personId.asString()) == null) {
em.persist(new PersonListEntry(personId, event.getName()));

View File

@@ -12,12 +12,12 @@
*/
package org.fuin.cqrs4j.example.quarkus.query.views.personlist;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.NamedQuery;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;

View File

@@ -14,7 +14,7 @@ package org.fuin.cqrs4j.example.quarkus.query.views.personlist;
import java.util.Set;
import jakarta.enterprise.context.ApplicationScoped;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.transaction.Transactional;

View File

@@ -15,8 +15,8 @@ package org.fuin.cqrs4j.example.quarkus.query.views.personlist;
import java.util.List;
import java.util.Set;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.validation.constraints.NotNull;
import javax.enterprise.context.ApplicationScoped;
import javax.validation.constraints.NotNull;
import org.fuin.cqrs4j.EventDispatcher;
import org.fuin.cqrs4j.SimpleEventDispatcher;
@@ -33,7 +33,7 @@ public class PersonListEventDispatcher implements EventDispatcher {
private final SimpleEventDispatcher delegate;
/**
* Constructor with all events to be dispatched.
* Constructor with all events to be dispatched.
*
* @param createdHandler
* PersonCreatedEventHandler.

View File

@@ -19,8 +19,8 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.Semaphore;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.ObservesAsync;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.ObservesAsync;
import javax.inject.Inject;
import org.fuin.cqrs4j.example.quarkus.query.app.QryCheckForViewUpdatesEvent;
@@ -81,9 +81,8 @@ public class PersonListProjector {
// Read and dispatch events
final Long nextEventNumber = chunkHandler.readNextEventNumber();
eventstore.readAllEventsForward(chunkHandler.getProjectionStreamId(), nextEventNumber, 100, (currentSlice) -> {
chunkHandler.handleChunk(currentSlice);
});
eventstore.readAllEventsForward(chunkHandler.getProjectionStreamId(), nextEventNumber, 100,
currentSlice -> chunkHandler.handleChunk(currentSlice));
}

View File

@@ -9,4 +9,5 @@ quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.log.level=INFO
quarkus.native.additional-build-args=--report-unsupported-elements-at-runtime
quarkus.native.additional-build-args=--initialize-at-run-time=org.apache.http.impl.auth.NTLMEngineImpl
quarkus.native.native-image-xmx=8192m

View File

@@ -12,9 +12,9 @@ import static org.hamcrest.Matchers.not;
import java.util.Arrays;
import java.util.UUID;
import jakarta.enterprise.context.control.ActivateRequestContext;
import javax.enterprise.context.control.ActivateRequestContext;
import javax.inject.Inject;
import jakarta.persistence.EntityManager;
import javax.persistence.EntityManager;
import org.fuin.cqrs4j.example.quarkus.query.views.personlist.PersonListEntry;
import org.fuin.cqrs4j.example.shared.PersonCreatedEvent;
@@ -31,71 +31,52 @@ import org.junit.jupiter.api.Test;
import io.quarkus.test.junit.QuarkusTest;
@QuarkusTest
public class QryPersonResourceIT {
class QryPersonResourceIT {
@Inject
IESHttpEventStore eventStore;
@Inject
EntityManager em;
@Test
public void testGetByIdNotFound() {
given()
.pathParam("id", UUID.randomUUID())
.when()
.get("/persons/{id}")
.then()
.statusCode(404);
void testGetByIdNotFound() {
given().pathParam("id", UUID.randomUUID()).when().get("/persons/{id}").then().statusCode(404);
}
@ActivateRequestContext
public boolean findPerson(final PersonId personId) {
return em.find(PersonListEntry.class, personId.asString()) != null;
}
@Test
public void testGetByIdOK() {
void testGetByIdOK() {
// PREPARE
final PersonId personId = new PersonId(UUID.randomUUID());
final PersonName personName = new PersonName("Peter Parker");
final SimpleStreamId personStreamId = new SimpleStreamId(PersonId.TYPE + "-" + personId);
final PersonCreatedEvent event = new PersonCreatedEvent(personId, personName);
final CommonEvent ce = new SimpleCommonEvent(new EventId(event.getEventId().asBaseType()),
new TypeName(event.getEventType().asBaseType()), event);
final CommonEvent ce = new SimpleCommonEvent(new EventId(event.getEventId().asBaseType()),
new TypeName(event.getEventType().asBaseType()), event);
eventStore.appendToStream(personStreamId, ce);
await().atMost(5, SECONDS).until(() -> findPerson(personId));
// TEST & VERIFY
final PersonListEntry person =
given()
.pathParam("id", personId.asString())
.when()
.get("/persons/{id}")
.then()
.statusCode(200)
.extract()
.as(PersonListEntry.class);
final PersonListEntry person = given().pathParam("id", personId.asString()).when().get("/persons/{id}").then().statusCode(200)
.extract().as(PersonListEntry.class);
assertThat(person.getId(), is(equalTo(personId)));
assertThat(person.getName(), is(equalTo(personName)));
final PersonListEntry[] persons =
given()
.when()
.get("/persons")
.then()
.statusCode(200)
.extract()
.as(PersonListEntry[].class);
final PersonListEntry[] persons = given().when().get("/persons").then().statusCode(200).extract().as(PersonListEntry[].class);
assertThat(Arrays.asList(persons), is(not(empty())));
final PersonListEntry person0 = persons[0];
assertThat(person0.getId(), is(equalTo(personId)));
assertThat(person0.getName(), is(equalTo(personName)));
}
}
}

View File

@@ -15,7 +15,7 @@ package org.fuin.cqrs4j.example.quarkus.shared;
import java.net.MalformedURLException;
import java.net.URL;
import jakarta.enterprise.context.ApplicationScoped;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import org.eclipse.microprofile.config.inject.ConfigProperty;
@@ -71,14 +71,19 @@ public class Config {
/**
* Constructor with all data.
*
* @param eventStoreHost Host.
* @param eventStoreHttpPort HTTP port
* @param eventStoreTcpPort TCP port.
* @param eventStoreUser User.
* @param eventStorePassword Password.
* @param eventStoreHost
* Host.
* @param eventStoreHttpPort
* HTTP port
* @param eventStoreTcpPort
* TCP port.
* @param eventStoreUser
* User.
* @param eventStorePassword
* Password.
*/
public Config(final String eventStoreHost, final int eventStoreHttpPort, final int eventStoreTcpPort,
final String eventStoreUser, final String eventStorePassword) {
public Config(final String eventStoreHost, final int eventStoreHttpPort, final int eventStoreTcpPort, final String eventStoreUser,
final String eventStorePassword) {
super();
this.eventStoreHost = eventStoreHost;
this.eventStoreHttpPort = eventStoreHttpPort;

View File

@@ -12,8 +12,8 @@
*/
package org.fuin.cqrs4j.example.quarkus.shared;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import org.eclipse.microprofile.context.ManagedExecutor;
@@ -30,8 +30,7 @@ public class EsjcEventStoreFactory {
@ApplicationScoped
public EventStore createESJC(final ManagedExecutor executor, final Config config) {
return EventStoreBuilder.newBuilder().singleNodeAddress(config.getEventStoreHost(), config.getEventStoreTcpPort())
.executor(executor).userCredentials(config.getEventStoreUser(), config.getEventStorePassword())
.build();
.executor(executor).userCredentials(config.getEventStoreUser(), config.getEventStorePassword()).build();
}
}

View File

@@ -12,15 +12,15 @@
*/
package org.fuin.cqrs4j.example.quarkus.shared;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.context.RequestScoped;
import jakarta.enterprise.inject.Disposes;
import jakarta.enterprise.inject.Produces;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Disposes;
import javax.enterprise.inject.Produces;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
@@ -57,7 +57,7 @@ public class EventStoreFactory {
public IESJCEventStore createEventStore(final com.github.msemys.esjc.EventStore es, final SerDeserializerRegistry registry) {
final IESJCEventStore eventstore = new ESJCEventStore.Builder().eventStore(es).serDesRegistry(registry)
.targetContentType(EnhancedMimeType.create("application", "json", Charset.forName("utf-8"))).build();
.targetContentType(EnhancedMimeType.create("application", "json", StandardCharsets.UTF_8)).build();
eventstore.open();
return eventstore;

View File

@@ -12,11 +12,11 @@
*/
package org.fuin.cqrs4j.example.quarkus.shared;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
import jakarta.json.bind.Jsonb;
import jakarta.json.bind.JsonbBuilder;
import jakarta.json.bind.JsonbConfig;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;
import javax.json.bind.JsonbConfig;
import org.eclipse.yasson.FieldAccessStrategy;
import org.fuin.cqrs4j.example.shared.SharedUtils;
@@ -34,8 +34,7 @@ public class JsonbFactory {
*/
@Produces
public Jsonb createJsonb() {
final JsonbConfig config = new JsonbConfig()
.withAdapters(SharedUtils.JSONB_ADAPTERS)
final JsonbConfig config = new JsonbConfig().withAdapters(SharedUtils.JSONB_ADAPTERS)
.withPropertyVisibilityStrategy(new FieldAccessStrategy());
return JsonbBuilder.create(config);
}

View File

@@ -12,8 +12,8 @@
*/
package org.fuin.cqrs4j.example.quarkus.shared;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import org.fuin.cqrs4j.example.shared.SharedUtils;
import org.fuin.esc.spi.JsonbDeSerializer;
@@ -37,8 +37,7 @@ public class SerDeserializerRegistryFactory {
final JsonbDeSerializer jsonbDeSer = SharedUtils.createJsonbDeSerializer();
// Registry connects the type with the appropriate serializer and de-serializer
return SharedUtils.createSerDeserializerRegistry(typeRegistry,
jsonbDeSer);
return SharedUtils.createSerDeserializerRegistry(typeRegistry, jsonbDeSer);
}

View File

@@ -1,38 +0,0 @@
#!/bin/bash
## Make sure hostname is set
MY_HOSTNAME=$(hostname)
if [ $(cat /etc/hosts | grep -c "$MY_HOSTNAME") -eq 0 ]; then
echo "Adding $MY_HOSTNAME to /etc/hosts"
sudo -- sh -c -e "echo '127.0.0.1 $MY_HOSTNAME' >> /etc/hosts"
else
echo "Host '$MY_HOSTNAME' already found in /etc/hosts"
fi
## Make sure ZLIB is in place
if [ $(dpkg-query -W -f='${Status}' zlib1g-dev 2>/dev/null | grep -c "ok installed") -eq 0 ]; then
sudo apt-get install zlib1g-dev
else
echo "zlib1g-dev already installed"
fi
## Install GraalVM 19.2.x (Based on OpenJDK 1.8.x)
. $SDKMAN_DIR/bin/sdkman-init.sh
if [ $(sdk list java | grep -c "installed | 19.2.1-grl") -eq 0 ]; then
sdk update
sdk install java 19.2.1-grl
else
echo "GraalVM 19.2.x already installed"
fi
## Configure GraalVM
if grep -q "export GRAALVM_HOME" ~/.profile; then
echo "GraalVM already exists in ~/.profile"
else
echo "Appending export of GRAALVM_HOME to ~/.profile"
echo "export GRAALVM_HOME=\"/home/developer/.sdkman/candidates/java/19.2.1-grl\"" >> ~/.profile
source ~/.profile
$GRAALVM_HOME/bin/gu install native-image
fi
echo "Setup successfully finished"

View File

@@ -1,38 +1,31 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
* Copyright 2007-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL =
"https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
@@ -80,13 +73,13 @@ public class MavenWrapperDownloader {
}
}
}
System.out.println("- Downloading from: : " + url);
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
@@ -102,6 +95,16 @@ public class MavenWrapperDownloader {
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());

Binary file not shown.

View File

@@ -1 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

36
shared/mvnw vendored
View File

@@ -8,7 +8,7 @@
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
@@ -19,7 +19,7 @@
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven2 Start Up Batch script
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
@@ -114,7 +114,6 @@ if $mingw ; then
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
# TODO classpath?
fi
if [ -z "$JAVA_HOME" ]; then
@@ -212,7 +211,11 @@ else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
@@ -221,22 +224,38 @@ else
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
wget "$jarUrl" -O "$wrapperJarPath"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
curl -o "$wrapperJarPath" "$jarUrl"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
@@ -277,6 +296,11 @@ if $cygwin; then
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \

45
shared/mvnw.cmd vendored
View File

@@ -7,7 +7,7 @@
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@@ -18,7 +18,7 @@
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven2 Start Up Batch script
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@@ -26,7 +26,7 @@
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@@ -37,7 +37,7 @@
@echo off
@REM set title of command window
title %0
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
@@ -120,23 +120,44 @@ SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
echo Found %WRAPPER_JAR%
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
echo Finished downloading %WRAPPER_JAR%
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end

View File

@@ -17,8 +17,8 @@
*/
package org.fuin.cqrs4j.example.shared;
import jakarta.json.bind.annotation.JsonbProperty;
import jakarta.validation.constraints.NotNull;
import javax.json.bind.annotation.JsonbProperty;
import javax.validation.constraints.NotNull;
import org.fuin.cqrs4j.AbstractAggregateCommand;
import org.fuin.ddd4j.ddd.DomainEventExpectedEntityIdPath;
@@ -56,8 +56,10 @@ public final class CreatePersonCommand extends AbstractAggregateCommand<PersonId
/**
* A new person was created in the system.
*
* @param id Identifies uniquely a person.
* @param name Name of a person.
* @param id
* Identifies uniquely a person.
* @param name
* Name of a person.
*/
public CreatePersonCommand(@NotNull final PersonId id, @NotNull final PersonName name) {
super(id, null);

View File

@@ -17,15 +17,15 @@
*/
package org.fuin.cqrs4j.example.shared;
import org.fuin.objects4j.common.Immutable;
import jakarta.json.bind.annotation.JsonbProperty;
import jakarta.validation.constraints.NotNull;
import javax.json.bind.annotation.JsonbProperty;
import javax.validation.constraints.NotNull;
import org.fuin.ddd4j.ddd.AbstractDomainEvent;
import org.fuin.ddd4j.ddd.EntityIdPath;
import org.fuin.ddd4j.ddd.EventType;
import org.fuin.esc.spi.SerializedDataType;
import org.fuin.objects4j.common.Contract;
import org.fuin.objects4j.common.Immutable;
/**
* A new person was created in the system.
@@ -55,8 +55,10 @@ public final class PersonCreatedEvent extends AbstractDomainEvent<PersonId> {
/**
* A new person was created in the system.
*
* @param id Identifies uniquely a person.
* @param name Name of a person.
* @param id
* Identifies uniquely a person.
* @param name
* Name of a person.
*/
public PersonCreatedEvent(@NotNull final PersonId id, @NotNull final PersonName name) {
super(new EntityIdPath(id));

View File

@@ -19,13 +19,13 @@ package org.fuin.cqrs4j.example.shared;
import java.util.UUID;
import org.fuin.objects4j.common.Immutable;
import jakarta.json.bind.adapter.JsonbAdapter;
import jakarta.validation.constraints.NotNull;
import javax.json.bind.adapter.JsonbAdapter;
import javax.validation.constraints.NotNull;
import org.fuin.ddd4j.ddd.AggregateRootUuid;
import org.fuin.ddd4j.ddd.EntityType;
import org.fuin.ddd4j.ddd.StringBasedEntityType;
import org.fuin.objects4j.common.Immutable;
import org.fuin.objects4j.ui.Label;
import org.fuin.objects4j.ui.ShortLabel;
import org.fuin.objects4j.ui.Tooltip;

View File

@@ -23,15 +23,15 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.fuin.objects4j.common.Immutable;
import jakarta.json.bind.adapter.JsonbAdapter;
import jakarta.validation.Constraint;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import jakarta.validation.Payload;
import jakarta.validation.constraints.NotNull;
import javax.json.bind.adapter.JsonbAdapter;
import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import javax.validation.constraints.NotNull;
import org.fuin.objects4j.common.ConstraintViolationException;
import org.fuin.objects4j.common.Immutable;
import org.fuin.objects4j.ui.Label;
import org.fuin.objects4j.ui.ShortLabel;
import org.fuin.objects4j.ui.Tooltip;
@@ -66,7 +66,8 @@ public final class PersonName extends AbstractStringValueObject {
/**
* Constructor with mandatory data.
*
* @param value Value.
* @param value
* Value.
*/
public PersonName(final String value) {
super();
@@ -83,14 +84,14 @@ public final class PersonName extends AbstractStringValueObject {
public final String toString() {
return value;
}
/**
* Verifies that a given string can be converted into the type.
*
* @param value Value to validate.
* @param value
* Value to validate.
*
* @return Returns <code>true</code> if it's a valid type else
* <code>false</code>.
* @return Returns <code>true</code> if it's a valid type else <code>false</code>.
*/
public static boolean isValid(final String value) {
if (value == null) {
@@ -107,16 +108,17 @@ public final class PersonName extends AbstractStringValueObject {
}
/**
* Verifies if the argument is valid and throws an exception if this is not the
* case.
* Verifies if the argument is valid and throws an exception if this is not the case.
*
* @param name Name of the value for a possible error message.
* @param value Value to check.
* @param name
* Name of the value for a possible error message.
* @param value
* Value to check.
*
* @throws ConstraintViolationException The value was not valid.
* @throws ConstraintViolationException
* The value was not valid.
*/
public static void requireArgValid(@NotNull final String name, @NotNull final String value)
throws ConstraintViolationException {
public static void requireArgValid(@NotNull final String name, @NotNull final String value) throws ConstraintViolationException {
if (!PersonName.isValid(value)) {
throw new ConstraintViolationException("The argument '" + name + "' is not valid: '" + value + "'");
@@ -163,8 +165,7 @@ public final class PersonName extends AbstractStringValueObject {
/**
* Converts the value object from/to string.
*/
public static final class Converter
implements ValueObjectConverter<String, PersonName>, JsonbAdapter<PersonName, String> {
public static final class Converter implements ValueObjectConverter<String, PersonName>, JsonbAdapter<PersonName, String> {
// Attribute Converter

View File

@@ -29,42 +29,42 @@ import org.fuin.ddd4j.ddd.EntityIdFactory;
*/
public final class SharedEntityIdFactory implements EntityIdFactory {
private Map<String, Function<String, EntityId>> valueOfMap;
private Map<String, Function<String, EntityId>> valueOfMap;
private Map<String, Function<String, Boolean>> isValidMap;
private Map<String, Function<String, Boolean>> isValidMap;
/**
* Default constructor.
*/
public SharedEntityIdFactory() {
super();
valueOfMap = new HashMap<>();
isValidMap = new HashMap<>();
valueOfMap.put(PersonId.TYPE.asString(), PersonId::valueOf);
isValidMap.put(PersonId.TYPE.asString(), PersonId::isValid);
}
/**
* Default constructor.
*/
public SharedEntityIdFactory() {
super();
valueOfMap = new HashMap<>();
isValidMap = new HashMap<>();
valueOfMap.put(PersonId.TYPE.asString(), PersonId::valueOf);
isValidMap.put(PersonId.TYPE.asString(), PersonId::isValid);
}
@Override
public EntityId createEntityId(final String type, final String id) {
final Function<String, EntityId> factory = valueOfMap.get(type);
if (factory == null) {
throw new IllegalArgumentException("Unknown type: " + type);
}
return factory.apply(id);
}
@Override
public EntityId createEntityId(final String type, final String id) {
final Function<String, EntityId> factory = valueOfMap.get(type);
if (factory == null) {
throw new IllegalArgumentException("Unknown type: " + type);
}
return factory.apply(id);
}
@Override
public boolean containsType(final String type) {
return valueOfMap.containsKey(type);
}
@Override
public boolean containsType(final String type) {
return valueOfMap.containsKey(type);
}
@Override
public boolean isValid(String type, String id) {
final Function<String, Boolean> func = isValidMap.get(type);
if (func == null) {
return false;
}
return func.apply(id);
}
@Override
public boolean isValid(String type, String id) {
final Function<String, Boolean> func = isValidMap.get(type);
if (func == null) {
return false;
}
return func.apply(id);
}
}

View File

@@ -19,10 +19,13 @@ package org.fuin.cqrs4j.example.shared;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.zip.Adler32;
import javax.json.bind.adapter.JsonbAdapter;
import javax.json.bind.config.PropertyVisibilityStrategy;
import org.fuin.ddd4j.ddd.AggregateVersionConverter;
import org.fuin.ddd4j.ddd.EntityIdConverter;
import org.fuin.ddd4j.ddd.EntityIdPathConverter;
@@ -40,20 +43,19 @@ import org.fuin.esc.spi.SerializedDataTypeRegistry;
import org.fuin.esc.spi.SimpleSerializedDataTypeRegistry;
import org.fuin.esc.spi.SimpleSerializerDeserializerRegistry;
import jakarta.json.bind.adapter.JsonbAdapter;
import jakarta.json.bind.config.PropertyVisibilityStrategy;
/**
* Utility code shared between command (write) and query (read) module.
*/
public final class SharedUtils {
private static final String APPLICATION_JSON = "application/json";
/** All types that will be written into and read from the event store. */
private static TypeClass[] USER_DEFINED_TYPES = new TypeClass[] {
private static final TypeClass[] USER_DEFINED_TYPES = new TypeClass[] {
new TypeClass(PersonCreatedEvent.SER_TYPE, PersonCreatedEvent.class) };
/** All JSON-B adapters from this module. */
public static JsonbAdapter<?, ?>[] JSONB_ADAPTERS = new JsonbAdapter<?, ?>[] { new EventIdConverter(),
public static final JsonbAdapter<?, ?>[] JSONB_ADAPTERS = new JsonbAdapter<?, ?>[] { new EventIdConverter(),
new EntityIdPathConverter(new SharedEntityIdFactory()), new EntityIdConverter(new SharedEntityIdFactory()),
new AggregateVersionConverter(), new PersonId.Converter(), new PersonName.Converter() };
@@ -101,14 +103,14 @@ public final class SharedUtils {
final SimpleSerializerDeserializerRegistry registry = new SimpleSerializerDeserializerRegistry();
// Base types always needed
registry.add(EscEvents.SER_TYPE, "application/json", jsonbDeSer);
registry.add(EscEvent.SER_TYPE, "application/json", jsonbDeSer);
registry.add(EscMeta.SER_TYPE, "application/json", jsonbDeSer);
registry.add(Base64Data.SER_TYPE, "application/json", jsonbDeSer);
registry.add(EscEvents.SER_TYPE, APPLICATION_JSON, jsonbDeSer);
registry.add(EscEvent.SER_TYPE, APPLICATION_JSON, jsonbDeSer);
registry.add(EscMeta.SER_TYPE, APPLICATION_JSON, jsonbDeSer);
registry.add(Base64Data.SER_TYPE, APPLICATION_JSON, jsonbDeSer);
// User defined types
for (final TypeClass tc : USER_DEFINED_TYPES) {
registry.add(tc.getType(), "application/json", jsonbDeSer);
registry.add(tc.getType(), APPLICATION_JSON, jsonbDeSer);
}
jsonbDeSer.init(typeRegistry, registry, registry);
@@ -129,9 +131,7 @@ public final class SharedUtils {
final JsonbDeSerializer jsonbDeSer = SharedUtils.createJsonbDeSerializer();
// Registry connects the type with the appropriate serializer and de-serializer
final SerDeserializerRegistry serDeserRegistry = SharedUtils.createSerDeserializerRegistry(typeRegistry, jsonbDeSer);
return serDeserRegistry;
return SharedUtils.createSerDeserializerRegistry(typeRegistry, jsonbDeSer);
}
@@ -144,7 +144,7 @@ public final class SharedUtils {
return JsonbDeSerializer.builder().withSerializers(EscSpiUtils.createEscJsonbSerializers())
.withDeserializers(EscSpiUtils.createEscJsonbDeserializers()).withAdapters(JSONB_ADAPTERS)
.withPropertyVisibilityStrategy(new FieldAccessStrategy()).withEncoding(Charset.forName("utf-8")).build();
.withPropertyVisibilityStrategy(new FieldAccessStrategy()).withEncoding(StandardCharsets.UTF_8).build();
}
@@ -159,7 +159,7 @@ public final class SharedUtils {
public static long calculateChecksum(final Collection<EventType> eventTypes) {
final Adler32 checksum = new Adler32();
for (final EventType eventType : eventTypes) {
checksum.update(eventType.asBaseType().getBytes(Charset.forName("ascii")));
checksum.update(eventType.asBaseType().getBytes(StandardCharsets.US_ASCII));
}
return checksum.getValue();
}

View File

@@ -24,9 +24,9 @@ import java.nio.charset.Charset;
import java.time.ZonedDateTime;
import java.util.UUID;
import jakarta.json.bind.Jsonb;
import jakarta.json.bind.JsonbBuilder;
import jakarta.json.bind.JsonbConfig;
import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;
import javax.json.bind.JsonbConfig;
import org.apache.commons.io.IOUtils;
import org.eclipse.yasson.FieldAccessStrategy;
@@ -35,74 +35,72 @@ import org.junit.Test;
// CHECKSTYLE:OFF
public final class CreatePersonCommandTest {
private static final String PERSON_UUID = "84565d62-115e-4502-b7c9-38ad69c64b05";
private static final String PERSON_UUID = "84565d62-115e-4502-b7c9-38ad69c64b05";
@Test
public final void testSerializeDeserialize() {
@Test
public final void testSerializeDeserialize() {
// PREPARE
final CreatePersonCommand original = createTestee();
// PREPARE
final CreatePersonCommand original = createTestee();
// TEST
final CreatePersonCommand copy = Utils4J.deserialize(Utils4J.serialize(original));
// TEST
final CreatePersonCommand copy = Utils4J.deserialize(Utils4J.serialize(original));
// VERIFY
assertThat(copy).isEqualTo(original);
assertThat(copy.getAggregateRootId()).isEqualTo(original.getAggregateRootId());
assertThat(copy.getName()).isEqualTo(original.getName());
// VERIFY
assertThat(copy).isEqualTo(original);
assertThat(copy.getAggregateRootId()).isEqualTo(original.getAggregateRootId());
assertThat(copy.getName()).isEqualTo(original.getName());
}
}
@Test
public final void testMarshalUnmarshalJson() {
@Test
public final void testMarshalUnmarshalJson() {
// PREPARE
final CreatePersonCommand original = createTestee();
// PREPARE
final CreatePersonCommand original = createTestee();
final JsonbConfig config = new JsonbConfig().withAdapters(SharedUtils.JSONB_ADAPTERS)
.withPropertyVisibilityStrategy(new FieldAccessStrategy());
final Jsonb jsonb = JsonbBuilder.create(config);
final JsonbConfig config = new JsonbConfig().withAdapters(SharedUtils.JSONB_ADAPTERS)
.withPropertyVisibilityStrategy(new FieldAccessStrategy());
final Jsonb jsonb = JsonbBuilder.create(config);
// TEST
final String json = jsonb.toJson(original, CreatePersonCommand.class);
final CreatePersonCommand copy = jsonb.fromJson(json, CreatePersonCommand.class);
// TEST
final String json = jsonb.toJson(original, CreatePersonCommand.class);
final CreatePersonCommand copy = jsonb.fromJson(json, CreatePersonCommand.class);
// VERIFY
assertThat(copy).isEqualTo(original);
assertThat(copy.getAggregateRootId()).isEqualTo(original.getAggregateRootId());
assertThat(copy.getName()).isEqualTo(original.getName());
// VERIFY
assertThat(copy).isEqualTo(original);
assertThat(copy.getAggregateRootId()).isEqualTo(original.getAggregateRootId());
assertThat(copy.getName()).isEqualTo(original.getName());
}
}
@Test
public final void testUnmarshalJsonFromFile() throws IOException {
@Test
public final void testUnmarshalJsonFromFile() throws IOException {
// PREPARE
// PREPARE
final String json = IOUtils.toString(this.getClass().getResourceAsStream("/commands/CreatePersonCommand.json"),
Charset.forName("utf-8"));
final JsonbConfig config = new JsonbConfig().withAdapters(SharedUtils.JSONB_ADAPTERS)
.withPropertyVisibilityStrategy(new FieldAccessStrategy());
final Jsonb jsonb = JsonbBuilder.create(config);
final JsonbConfig config = new JsonbConfig().withAdapters(SharedUtils.JSONB_ADAPTERS)
.withPropertyVisibilityStrategy(new FieldAccessStrategy());
final Jsonb jsonb = JsonbBuilder.create(config);
// TEST
final CreatePersonCommand copy = jsonb.fromJson(json, CreatePersonCommand.class);
// TEST
final CreatePersonCommand copy = jsonb.fromJson(json, CreatePersonCommand.class);
// VERIFY
assertThat(copy.getEventId().asBaseType()).isEqualTo(UUID.fromString("109a77b2-1de2-46fc-aee1-97fa7740a552"));
assertThat(copy.getEventTimestamp()).isEqualTo(ZonedDateTime.parse("2019-11-17T10:27:13.183+01:00[Europe/Berlin]"));
assertThat(copy.getAggregateRootId().asString()).isEqualTo(PERSON_UUID);
assertThat(copy.getName().asString()).isEqualTo("Peter Parker");
// VERIFY
assertThat(copy.getEventId().asBaseType()).isEqualTo(UUID.fromString("109a77b2-1de2-46fc-aee1-97fa7740a552"));
assertThat(copy.getEventTimestamp()).isEqualTo(ZonedDateTime.parse("2019-11-17T10:27:13.183+01:00[Europe/Berlin]"));
assertThat(copy.getAggregateRootId().asString()).isEqualTo(PERSON_UUID);
assertThat(copy.getName().asString()).isEqualTo("Peter Parker");
}
}
private CreatePersonCommand createTestee() {
final PersonId personId = new PersonId(UUID.fromString(PERSON_UUID));
final PersonName personName = new PersonName("Peter Parker");
return new CreatePersonCommand(personId, personName);
}
private CreatePersonCommand createTestee() {
final PersonId personId = new PersonId(UUID.fromString(PERSON_UUID));
final PersonName personName = new PersonName("Peter Parker");
return new CreatePersonCommand(personId, personName);
}
}
// CHECKSTYLE:ON

View File

@@ -25,15 +25,14 @@ import java.io.IOException;
import java.nio.charset.Charset;
import java.util.UUID;
import jakarta.json.bind.Jsonb;
import jakarta.json.bind.JsonbBuilder;
import jakarta.json.bind.JsonbConfig;
import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;
import javax.json.bind.JsonbConfig;
import org.apache.commons.io.IOUtils;
import org.eclipse.yasson.FieldAccessStrategy;
import org.junit.Test;
// CHECKSTYLE:OFF
public final class PersonCreatedEventTest {
@@ -71,7 +70,7 @@ public final class PersonCreatedEventTest {
assertThat(copy.getName()).isEqualTo(original.getName());
}
@Test
public final void testUnmarshalJson() throws IOException {
@@ -92,12 +91,11 @@ public final class PersonCreatedEventTest {
}
@Test
public final void testToString() {
final PersonCreatedEvent testee = createTestee();
assertThat(testee.toString())
.isEqualTo("Person 'Peter Parker' (" + testee.getEntityId() + ") was created [Event " + testee.getEventId() + "]");
assertThat(testee)
.hasToString("Person 'Peter Parker' (" + testee.getEntityId() + ") was created [Event " + testee.getEventId() + "]");
}
private PersonCreatedEvent createTestee() {

View File

@@ -35,57 +35,55 @@ import nl.jqno.equalsverifier.Warning;
*/
public final class PersonIdTest {
private static final String PERSON_UUID = "84565d62-115e-4502-b7c9-38ad69c64b05";
private static final String PERSON_UUID = "84565d62-115e-4502-b7c9-38ad69c64b05";
@Test
public void testEquals() {
EqualsVerifier.forClass(PersonId.class).suppress(Warning.NONFINAL_FIELDS)
.withNonnullFields("entityType", "uuid")
.withPrefabValues(EntityType.class, new StringBasedEntityType("A"), new StringBasedEntityType("B"))
.verify();
}
@Test
public void testEquals() {
EqualsVerifier.forClass(PersonId.class).suppress(Warning.NONFINAL_FIELDS).withNonnullFields("entityType", "uuid")
.withPrefabValues(EntityType.class, new StringBasedEntityType("A"), new StringBasedEntityType("B")).verify();
}
@Test
public void testValueOf() {
final PersonId personId = PersonId.valueOf(PERSON_UUID);
@Test
public void testValueOf() {
final PersonId personId = PersonId.valueOf(PERSON_UUID);
assertThat(personId.asString()).isEqualTo(PERSON_UUID);
assertThat(personId.asString()).isEqualTo(PERSON_UUID);
}
}
@Test
public void testValueOfIllegalArgumentCharacter() {
try {
PersonId.valueOf("abc");
fail();
} catch (final ConstraintViolationException ex) {
assertThat(ex.getMessage()).isEqualTo("The argument 'value' is not valid: 'abc'");
}
}
@Test
public void testValueOfIllegalArgumentCharacter() {
try {
PersonId.valueOf("abc");
fail();
} catch (final ConstraintViolationException ex) {
assertThat(ex.getMessage()).isEqualTo("The argument 'value' is not valid: 'abc'");
}
}
@Test
public final void testConverterUnmarshal() throws Exception {
@Test
public final void testConverterUnmarshal() throws Exception {
// PREPARE
final String personIdValue = PERSON_UUID;
// PREPARE
final String personIdValue = PERSON_UUID;
// TEST
final PersonId personId = new PersonId.Converter().adaptFromJson(UUID.fromString(PERSON_UUID));
// TEST
final PersonId personId = new PersonId.Converter().adaptFromJson(UUID.fromString(PERSON_UUID));
// VERIFY
assertThat(personId.asString()).isEqualTo(personIdValue);
}
// VERIFY
assertThat(personId.asString()).isEqualTo(personIdValue);
}
@Test
public void testConverterMarshal() throws Exception {
@Test
public void testConverterMarshal() throws Exception {
final PersonId personId = PersonId.valueOf(PERSON_UUID);
final PersonId personId = PersonId.valueOf(PERSON_UUID);
// TEST
final UUID uuid = new PersonId.Converter().adaptToJson(personId);
// TEST
final UUID uuid = new PersonId.Converter().adaptToJson(personId);
// VERIFY
assertThat(uuid).isEqualTo(UUID.fromString(PERSON_UUID));
}
// VERIFY
assertThat(uuid).isEqualTo(UUID.fromString(PERSON_UUID));
}
}

View File

@@ -17,7 +17,6 @@
*/
package org.fuin.cqrs4j.example.shared;
import static org.assertj.core.api.Assertions.assertThat;
import org.fuin.objects4j.common.ConstraintViolationException;
@@ -76,8 +75,9 @@ public final class PersonNameTest {
assertThat(PersonName.isValid("Peter Parker")).isTrue();
assertThat(PersonName.isValid("")).isFalse();
assertThat(PersonName.isValid("123456789.123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789.123456789." + "12345")).isFalse();
assertThat(PersonName.isValid(
"123456789.123456789.123456789.123456789.123456789." + "123456789.123456789.123456789.123456789.123456789." + "12345"))
.isFalse();
}
@@ -95,13 +95,12 @@ public final class PersonNameTest {
}
try {
PersonName.requireArgValid("d", "123456789.123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789.123456789." + "12345");
PersonName.requireArgValid("d",
"123456789.123456789.123456789.123456789.123456789." + "123456789.123456789.123456789.123456789.123456789." + "12345");
Assert.fail();
} catch (final ConstraintViolationException ex) {
assertThat(ex.getMessage())
.isEqualTo("The argument 'd' is not valid: '" + "123456789.123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789.123456789." + "12345" + "'");
assertThat(ex.getMessage()).isEqualTo("The argument 'd' is not valid: '" + "123456789.123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789.123456789." + "12345" + "'");
}
}
@@ -113,8 +112,9 @@ public final class PersonNameTest {
assertThat(new PersonName.Validator().isValid("Peter Parker", null)).isTrue();
assertThat(new PersonName.Validator().isValid("", null)).isFalse();
assertThat(new PersonName.Validator().isValid("123456789.123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789.123456789." + "12345", null)).isFalse();
assertThat(new PersonName.Validator().isValid(
"123456789.123456789.123456789.123456789.123456789." + "123456789.123456789.123456789.123456789.123456789." + "12345",
null)).isFalse();
}
@@ -126,8 +126,9 @@ public final class PersonNameTest {
assertThat(new PersonName.Converter().isValid(null)).isTrue();
assertThat(new PersonName.Converter().isValid("Peter Parker")).isTrue();
assertThat(new PersonName.Converter().isValid("123456789.123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789.123456789." + "12345")).isFalse();
assertThat(new PersonName.Converter().isValid(
"123456789.123456789.123456789.123456789.123456789." + "123456789.123456789.123456789.123456789.123456789." + "12345"))
.isFalse();
}

View File

@@ -1,38 +1,31 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
* Copyright 2007-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL =
"https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
@@ -80,13 +73,13 @@ public class MavenWrapperDownloader {
}
}
}
System.out.println("- Downloading from: : " + url);
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
@@ -102,6 +95,16 @@ public class MavenWrapperDownloader {
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More