[P25284-20] Initial commit with setup and first draft rest servcice

This commit is contained in:
verboomp
2026-01-20 11:39:25 +01:00
parent 071b1f7f95
commit 9d36ea7780
66 changed files with 4981 additions and 0 deletions

17
.project Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>hartmann-foto_documentation</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

243
Jenkinsfile vendored Normal file
View File

@@ -0,0 +1,243 @@
//
// Created by Patrick Verboom on 04.11.2024.
// Copyright © 2024 heyday Marketing GmbH. All rights reserved.
//
def defaultRocketChatChannel = "#builds"
def rocketChatColor = "#e813c8"
def rocketChatEmoji = ":skunk:"
def numOfArtifactsToKeep = env.GIT_BRANCH == "master" ? "10" : "5"
def result = []
pipeline {
agent {
label "macOS"
}
tools {
maven 'Maven Latest'
jdk 'OpenJDK-21.0.5'
}
environment {
PATH = "$PATH:/Users/Shared/jenkins/flutter/bin"
}
options {
// keeps only the atifacts of the last 15 builds
buildDiscarder(
logRotator(
artifactDaysToKeepStr: '',
artifactNumToKeepStr: numOfArtifactsToKeep,
daysToKeepStr: '',
numToKeepStr: numOfArtifactsToKeep
)
)
}
stages {
stage ('Initialize') {
steps {
script {
def msg = "Pipeline ${env.JOB_NAME} ${env.BUILD_NUMBER} has started. \n More info at: ${env.BUILD_URL} "
try {
echo msg
rocketSend channel: defaultRocketChatChannel, message: "jenkins-${env.JOB_NAME}-${env.BUILD_NUMBER}", emoji: rocketChatEmoji, attachments: [[$class: 'MessageAttachment', color: rocketChatColor, text: msg, title: 'Build started']]
} catch (Exception e) {
echo "Exception occurred sending : " + e.toString() + "\nmessage: " + msg
throw e
}
}
sh '''
echo "PATH = ${PATH}"
echo "M2_HOME = ${M2_HOME}"
printenv
'''
}
}
/*
stage ('Build Frontend') {
steps {
echo "running Frontend build for branch ${env.BRANCH_NAME}"
dir("hartmann-foto-documentation-frontend"){
//flutter build web --dart-define=FLUTTER_WEB_CANVASKIT_URL=OURBASEURL/canvaskit/
sh 'flutter pub get'
//sh 'dart run build_runner build'
sh 'flutter build web --no-tree-shake-icons'
dir("build/web"){
sh "cp -R . ../../../hartmann-foto-documentation-web/src/main/webapp/."
}
}
}
post {
always {
script {
def msg = "Build ${env.JOB_NAME} ${env.BUILD_NUMBER} frontend build has finished. Result: ${currentBuild.currentResult}. Took ${currentBuild.duration}.\n More info at: ${env.BUILD_URL} "
result.add( ["Stage: Build ${currentBuild.currentResult}", msg] )
}
}
}
}
stage ('Test Frontend') {
steps {
echo "running Frontend test for branch ${env.BRANCH_NAME}"
dir("hartmann-foto-documentation-frontend"){
// Run tests with JSON output for Jenkins parsing
sh '''
flutter test --coverage --reporter=json --file-reporter=json:test_results.json --reporter=expanded || true
dart test_runner.dart test_results.json test_results.xml
'''
}
}
post {
success {
archiveArtifacts artifacts: 'hartmann-foto-documentation-frontend/coverage/lcov.info', fingerprint: true
}
always {
// Publish test results to Jenkins
junit 'hartmann-foto-documentation-frontend/test_results.xml'
// Archive test artifacts
archiveArtifacts artifacts: 'hartmann-foto-documentation-frontend/test_results.json, hartmann-foto-documentation-frontend/test_results.xml', allowEmptyArchive: true
script {
def msg = "Build ${env.JOB_NAME} ${env.BUILD_NUMBER} frontend test has finished. Result: ${currentBuild.currentResult}. Took ${currentBuild.duration}.\n More info at: ${env.BUILD_URL} "
result.add( ["Stage: Build ${currentBuild.currentResult}", msg] )
}
}
}
}
*/
stage ('Build') {
steps {
echo "running build for branch ${env.BRANCH_NAME}"
//sh 'mvn dependency:purge-local-repository clean -U -f hartmann-foto-documentation/pom.xml '
sh 'mvn deploy -U -f pom.xml '
}
post {
success {
junit '**/target/surefire-reports/*.xml'
archiveArtifacts artifacts: '**/target/*.war, **/target/*.zip', fingerprint: true
}
always {
script {
def msg = "Build ${env.JOB_NAME} ${env.BUILD_NUMBER} build has finished. Result: ${currentBuild.currentResult}. Took ${currentBuild.duration}.\n More info at: ${env.BUILD_URL} "
result.add( ["Stage: Build ${currentBuild.currentResult}", msg] )
}
}
}
}
stage ('Tests') {
steps {
sh 'mvn deploy -P docker -f hartmann-foto-documentation-docker/pom.xml'
}
post {
success {
junit '**/target/surefire-reports/*.xml'
}
always {
script {
def msg = "Build ${env.JOB_NAME} ${env.BUILD_NUMBER} tests has finished. Result: ${currentBuild.currentResult}. Took ${currentBuild.duration}.\n More info at: ${env.BUILD_URL} "
result.add( ["Stage: Test ${currentBuild.currentResult}", msg])
}
}
}
}
stage ('Code Coverage') {
steps {
sh 'mvn jacoco:report-aggregate -P docker -f pom.xml'
sh 'cp hartmann-foto-documentation-docker/target/site/jacoco-aggregate/jacoco.xml hartmann-foto-documentation-app/target/site/jacoco-aggregate/jacoco.xml'
}
post {
always {
script {
def msg = "Build ${env.JOB_NAME} ${env.BUILD_NUMBER} Code coverage has finished. Result: ${currentBuild.currentResult}. Took ${currentBuild.duration}.\n More info at: ${env.BUILD_URL} "
result.add( ["Stage: Test ${currentBuild.currentResult}", msg])
}
}
}
}
stage ('SonarQube analysis') {
steps {
withSonarQubeEnv('heyday sonar') {
script {
def key = "${env.BRANCH_NAME.replaceAll("/", "_")}"
def projectKey = "\"marketing.heyday.hartmann:hartmann-foto-documentation:${key}\""
echo "running sonar for branch ${projectKey}"
sh "mvn org.sonarsource.scanner.maven:sonar-maven-plugin:5.3.0.6276:sonar -f pom.xml -Dsonar.projectKey=${projectKey}"
}
}
}
post {
always {
script {
def msg = "Build ${env.JOB_NAME} ${env.BUILD_NUMBER} sonar has finished. Result: ${currentBuild.currentResult}. Took ${currentBuild.duration}.\n More info at: ${env.BUILD_URL} "
result.add(["Stage: Sonar ${currentBuild.currentResult}", msg])
}
}
}
}
stage ('Release') {
when {
branch 'master'
}
steps {
sh "mvn -B -U -X -e -Dmaven.test.skip=true -Djava.awt.headless=true release:prepare release:perform -DbambooBuildNumber=${env.BUILD_NUMBER} -Dmaven.javadoc.skip=true -f pom.xml "
}
post {
success {
archiveArtifacts artifacts: '**/target/*.war, **/target/*.zip', fingerprint: true
}
always {
script {
def msg = "Build ${env.JOB_NAME} ${env.BUILD_NUMBER} release has finished. Result: ${currentBuild.currentResult}. Took ${currentBuild.duration}.\n More info at: ${env.BUILD_URL} "
result.add(["Stage: Release ${currentBuild.currentResult}",msg])
}
}
}
}
}
post {
always {
script {
def msg = "Build ${env.JOB_NAME} ${env.BUILD_NUMBER} Pipeline finished. Result: ${currentBuild.currentResult}. Took ${currentBuild.duration}.\n More info at: ${env.BUILD_URL} "
result.add(["Stage: Pipeline ${currentBuild.currentResult}", msg])
try {
//echo msg
def attachements = []
for (elem in result) {
attachements+=([$class: 'MessageAttachment', color: rocketChatColor, text: elem.get(1), title: elem.get(0)])
}
rocketSend channel: defaultRocketChatChannel, message: "jenkins-${env.JOB_NAME}-${env.BUILD_NUMBER}", emoji: rocketChatEmoji, attachments: attachements
} catch (Exception e) {
echo "Exception occurred sending : " + e.toString() + "\nmessage: " + msg
throw e
}
}
}
unsuccessful {
emailext body: "${currentBuild.currentResult}: Job ${env.JOB_NAME} build ${env.BUILD_NUMBER}\n More info at: ${env.BUILD_URL}",
recipientProviders: [[$class: 'DevelopersRecipientProvider'], [$class: 'RequesterRecipientProvider']],
subject: "Failed Jenkins Build ${currentBuild.currentResult}: Job ${env.JOB_NAME}"
}
fixed {
emailext body: "${currentBuild.currentResult}: Job ${env.JOB_NAME} build ${env.BUILD_NUMBER}\n More info at: ${env.BUILD_URL}",
recipientProviders: [[$class: 'DevelopersRecipientProvider'], [$class: 'RequesterRecipientProvider']],
subject: "Success Jenkins Build ${currentBuild.currentResult}: Job ${env.JOB_NAME}"
}
}
}

View File

@@ -0,0 +1,343 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>marketing.heyday.hartmann.fotodocumentation</groupId>
<artifactId>hartmann-foto-documentation</artifactId>
<version>1.0.0</version>
<relativePath>../hartmann-foto-documentation/pom.xml</relativePath>
</parent>
<artifactId>hartmann-foto-documentation-app</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>hartmann-foto-documentation app</name>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<configuration>
<skip>true</skip>
<skipDeploy>true</skipDeploy>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Elytron secrity used for username/password login -->
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron</artifactId>
<version>2.5.2.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-credential</artifactId>
<version>2.5.2.Final</version>
<scope>provided</scope>
</dependency>
<!-- Apache POI -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</dependency>
<!-- Apache POI-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>fluent-hc</artifactId>
<version>4.5.1</version>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-jaxrs2-jakarta</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>swagger-ui</artifactId>
<version>3.22.2</version>
</dependency>
<dependency>
<groupId>com.github.spullara.mustache.java</groupId>
<artifactId>compiler</artifactId>
<version>0.9.5</version>
</dependency>
<dependency>
<groupId>com.networknt</groupId>
<artifactId>json-schema-validator</artifactId>
<version>0.1.2</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
<exclusion>
<groupId>io.undertow</groupId>
<artifactId>undertow-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>${version.commons-logging}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${version.commons-lang3}</version>
</dependency>
<dependency>
<groupId>io.javaslang</groupId>
<artifactId>javaslang</artifactId>
<version>${version.javaslang}</version>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.jboss.ejb3</groupId>
<artifactId>jboss-ejb3-ext-api</artifactId>
<version>${version.org.jboss.ejb3.ext-api}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- Resteasy -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-core-spi</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson2-provider</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-multipart-provider</artifactId>
<scope>provided</scope>
</dependency>
<!-- Apache Commons -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${version.commons-fileupload}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${version.commons-io}</version>
</dependency>
<!-- Apache POI -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
<scope>provided</scope>
</dependency>
<!-- Logging -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Test -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>17.0</version>
<scope>test</scope>
</dependency>
<!-- to fix the java.lang.NoClassDefFoundError:
org/w3c/dom/ElementTraversal -->
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.subethamail</groupId>
<artifactId>subethasmtp-smtp</artifactId>
<version>${subethamail.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.subethamail</groupId>
<artifactId>subethasmtp-wiser</artifactId>
<version>${subethamail.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.subethamail</groupId>
<artifactId>subethasmtp-smtp</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-commons</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>test</scope>
</dependency>
<!-- for jacoco -->
<dependency>
<groupId>org.jacoco</groupId>
<artifactId>org.jacoco.core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,48 @@
package marketing.heyday.hartmann.fotodocumentation.core.db.migration;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import jakarta.ejb.Singleton;
import jakarta.ejb.Startup;
import jakarta.ejb.TransactionManagement;
import jakarta.ejb.TransactionManagementType;
import javax.sql.DataSource;
import org.flywaydb.core.Flyway;
/**
*
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 19 Jan 2026
*/
@Singleton
@Startup
@TransactionManagement(TransactionManagementType.BEAN)
public class DbMigrator {
@Resource(lookup = "java:/jdbc/fotoDocumentationDS")
private DataSource dataSource;
@PostConstruct
public void onStartup() {
Flyway flyway = getFlyway();
flyway.setDataSource(dataSource);
flyway.setTable("DB_MIGRATION");
flyway.setLocations(this.getClass().getPackage().getName());
flyway.setBaselineOnMigrate(false);
flyway.setValidateOnMigrate(false);
flyway.setIgnoreFailedFutureMigration(true);
flyway.migrate();
}
protected Flyway getFlyway() {
return new Flyway();
}
}

View File

@@ -0,0 +1,71 @@
package marketing.heyday.hartmann.fotodocumentation.core.model;
import java.util.Date;
import jakarta.persistence.*;
import com.fasterxml.jackson.annotation.JsonIgnore;
/**
*
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 19 Jan 2026
*/
@MappedSuperclass
public abstract class AbstractDateEntity extends AbstractEntity {
private static final long serialVersionUID = 1L;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "JPA_CREATED", nullable = false)
@JsonIgnore
private Date jpaCreated;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "JPA_UPDATED", nullable = false)
@JsonIgnore
private Date jpaUpdated;
@Column(name = "JPA_ACTIVE", nullable = false)
private boolean active = true;
@Version
@Column(name = "JPA_VERSION", nullable = false)
private int jpaVersion = 0;
@PrePersist
protected void onCreate() {
Date now = new Date();
jpaCreated = now;
jpaUpdated = now;
}
@PreUpdate
protected void onUpdate() {
jpaUpdated = new Date();
}
public Date getJpaCreated() {
return jpaCreated;
}
public Date getJpaUpdated() {
return jpaUpdated;
}
public int getJpaVersion() {
return jpaVersion;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
}

View File

@@ -0,0 +1,21 @@
package marketing.heyday.hartmann.fotodocumentation.core.model;
import java.io.Serializable;
import jakarta.persistence.MappedSuperclass;
/**
*
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 19 Jan 2026
*/
@MappedSuperclass
public abstract class AbstractEntity implements Serializable {
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,108 @@
package marketing.heyday.hartmann.fotodocumentation.core.model;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.lang.builder.HashCodeBuilder;
import jakarta.persistence.*;
/**
*
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 19 Jan 2026
*/
@Entity
@Table(name = "customer")
@NamedQuery(name = Customer.FIND_BY_NUMBER, query = "select c from Customer c where c.customerNumber = :cutomerNumber")
public class Customer extends AbstractDateEntity {
private static final long serialVersionUID = 1L;
public static final String SEQUENCE = "customer_seq";
public static final String FIND_BY_NUMBER = "Customer.findByNumber";
public static final String PARAM_NUMBER = "cutomerNumber";
@Id
@Column(name = "customer_id", length = 22)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQUENCE)
@SequenceGenerator(name = SEQUENCE, sequenceName = SEQUENCE, allocationSize = 1)
private Long customerId;
@Column(name = "customer_number", unique = true, nullable = false)
private String customerNumber;
@Column(name = "name", nullable = false)
private String name;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "customer_id_fk")
private Set<Picture> pictures = new HashSet<>();
public Long getCustomerId() {
return customerId;
}
public void setCustomerId(Long customerId) {
this.customerId = customerId;
}
public String getCustomerNumber() {
return customerNumber;
}
public void setCustomerNumber(String customerNumber) {
this.customerNumber = customerNumber;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Picture> getPictures() {
return pictures;
}
public void setPictures(Set<Picture> pictures) {
this.pictures = pictures;
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(customerNumber).toHashCode();
}
@Override
public boolean equals(Object obj) {
if (obj == null || this.getClass() != obj.getClass()) {
return false;
}
return this.customerNumber.equals(((Customer) obj).getCustomerNumber());
}
public static class Builder {
private Customer instance = new Customer();
public Builder customerNumber(String customerNumber) {
instance.setCustomerNumber(customerNumber);
return this;
}
public Builder name(String name) {
instance.setName(name);
return this;
}
public Customer build() {
return instance;
}
}
}

View File

@@ -0,0 +1,125 @@
package marketing.heyday.hartmann.fotodocumentation.core.model;
import java.util.Date;
import org.apache.commons.lang.builder.HashCodeBuilder;
import jakarta.persistence.*;
/**
*
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 19 Jan 2026
*/
@Entity
@Table(name = "picture")
public class Picture extends AbstractDateEntity {
private static final long serialVersionUID = 1L;
public static final String SEQUENCE = "picture_seq";
@Id
@Column(name = "picture_id", length = 22)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQUENCE)
@SequenceGenerator(name = SEQUENCE, sequenceName = SEQUENCE, allocationSize = 1)
private Long pictureId;
// username from the person that shot the picture
@Column(name = "username")
private String username;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "picture_date", nullable = false)
private Date pictureDate;
private String comment;
@Column(name = "image")
private String image;
public Long getPictureId() {
return pictureId;
}
public void setPictureId(Long pictureId) {
this.pictureId = pictureId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getPictureDate() {
return pictureDate;
}
public void setPictureDate(Date pictureDate) {
this.pictureDate = pictureDate;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(pictureId).toHashCode();
}
@Override
public boolean equals(Object obj) {
if (obj == null || this.getClass() != obj.getClass() || pictureId == null) {
return false;
}
return this.pictureId.equals(((Picture) obj).getPictureId());
}
public static class Builder {
private Picture instance = new Picture();
public Builder username(String username) {
instance.setUsername(username);
return this;
}
public Builder pictureDate(Date pictureDate) {
instance.setPictureDate(pictureDate);
return this;
}
public Builder comment(String comment) {
instance.setComment(comment);
return this;
}
public Builder image(String image) {
instance.setImage(image);
return this;
}
public Picture build() {
return instance;
}
}
}

View File

@@ -0,0 +1,95 @@
package marketing.heyday.hartmann.fotodocumentation.core.model;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import jakarta.persistence.*;
/**
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 19 Jan 2026
*/
@Entity
@Table(name = "x_right")
public class Right extends AbstractDateEntity {
private static final long serialVersionUID = 1L;
public static final String SEQUENCE = "right_seq";
@Id
@Column(name = "right_id", length = 22)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQUENCE)
@SequenceGenerator(name = SEQUENCE, sequenceName = SEQUENCE, allocationSize = 1)
private Long rightId;
@Column(nullable = false, unique = true)
private String code;
@Column(nullable = false, unique = true)
private String name;
@ManyToMany(mappedBy = "rights")
private Set<User> roles = new HashSet<>();
public Long getRightId() {
return rightId;
}
public void setRightId(Long rightId) {
this.rightId = rightId;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(code).toHashCode();
}
@Override
public boolean equals(Object obj) {
if (obj == null || this.getClass() != obj.getClass()) {
return false;
}
return this.code.equals(((Right) obj).getCode());
}
public static class Builder {
private Right instance = new Right();
public Builder code(String code) {
instance.setCode(code);
return this;
}
public Builder name(String name) {
instance.setName(name);
return this;
}
public Right build() {
return instance;
}
}
}

View File

@@ -0,0 +1,179 @@
package marketing.heyday.hartmann.fotodocumentation.core.model;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.lang.builder.HashCodeBuilder;
import jakarta.persistence.*;
/**
*
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 19 Jan 2026
*/
@Entity
@Table(name = "x_user")
public class User extends AbstractDateEntity {
private static final long serialVersionUID = 1L;
public static final String SEQUENCE = "user_seq";
@Id
@Column(name = "user_id", length = 22)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQUENCE)
@SequenceGenerator(name = SEQUENCE, sequenceName = SEQUENCE, allocationSize = 1)
private Long userId;
@Column(name = "username", unique = true, nullable = false)
private String username;
@Column(nullable = false)
private String password;
private String salt;
@Column(name = "title")
private String title;
@Column(nullable = false)
private String firstname;
@Column(nullable = false)
private String lastname;
@Column(nullable = false)
private String email;
@ManyToMany
@JoinTable(name = "user_to_right", joinColumns = { @JoinColumn(name = "user_id_fk") }, inverseJoinColumns = { @JoinColumn(name = "right_id_fk") })
private Set<Right> rights = new HashSet<>();
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getSalt() {
return salt;
}
public void setSalt(String salt) {
this.salt = salt;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Set<Right> getRights() {
return rights;
}
public void setRights(Set<Right> rights) {
this.rights = rights;
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(username).toHashCode();
}
@Override
public boolean equals(Object obj) {
if (obj == null || this.getClass() != obj.getClass()) {
return false;
}
return this.username.equals(((User) obj).getUsername());
}
public static class Builder {
private User instance = new User();
public Builder email(String email) {
instance.setEmail(email);
return this;
}
public Builder firstname(String firstname) {
instance.setFirstname(firstname);
return this;
}
public Builder lastname(String lastname) {
instance.setLastname(lastname);
return this;
}
public Builder title(String title) {
instance.setTitle(title);
return this;
}
public Builder username(String username) {
instance.setUsername(username);
return this;
}
public Builder password(String password) {
instance.setPassword(password);
return this;
}
public User build() {
return instance;
}
}
}

View File

@@ -0,0 +1,16 @@
package marketing.heyday.hartmann.fotodocumentation.core.query;
/**
*
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 19 Jan 2026
*/
public record Param(String name, Object value) {
}

View File

@@ -0,0 +1,100 @@
package marketing.heyday.hartmann.fotodocumentation.core.query;
import java.util.Arrays;
import java.util.Collection;
import java.util.Optional;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import jakarta.annotation.security.PermitAll;
import jakarta.ejb.Stateless;
import jakarta.persistence.EntityManager;
import jakarta.persistence.NoResultException;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;
/**
*
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 19 Jan 2026
*/
@Stateless
@SuppressWarnings("unchecked")
@PermitAll
public class QueryService {
private static final Log LOG = LogFactory.getLog(QueryService.class);
@PersistenceContext
private EntityManager eManager;
public int count(String namedQuery, Param... params) {
Query query = eManager.createNamedQuery(namedQuery);
for (Param param : params) {
query.setParameter(param.name(), param.value());
}
return ((Number) query.getSingleResult()).intValue();
}
public <T> Optional<T> callNamedQuerySingleResult(String namedQuery, Param... params) {
return singleResult(eManager.createNamedQuery(namedQuery), Arrays.asList(params));
}
private <T> Optional<T> singleResult(Query query, Collection<Param> params) {
try {
for (Param param : params) {
query.setParameter(param.name(), param.value());
}
return Optional.ofNullable((T) query.getSingleResult());
} catch (NoResultException nre) {
LOG.debug("No entity found for query " + query + " with params " + params);
LOG.trace("NoResultException", nre);
return Optional.empty();
}
}
public <T> T callNamedQueryList(String namedQuery, Param... objects) {
Query query = eManager.createNamedQuery(namedQuery);
for (Param param : objects) {
query.setParameter(param.name(), param.value());
}
return (T) query.getResultList();
}
public <T> Optional<T> callQuerySingleResult(String sql, Param... objects) {
Query query = eManager.createQuery(sql);
for (Param param : objects) {
query.setParameter(param.name(), param.value());
}
return Optional.of((T) query.getSingleResult());
}
public <T> T callNativeQuery(String sql, Param... objects) {
Query query = eManager.createNativeQuery(sql);
for (Param param : objects) {
query.setParameter(param.name(), param.value());
}
return (T) query.getResultList();
}
public int callNativeQueryUpdate(String sql, Param... objects) {
Query query = eManager.createNativeQuery(sql);
for (Param param : objects) {
query.setParameter(param.name(), param.value());
}
return query.executeUpdate();
}
public int callNamedQueryUpdate(String namedQuery, Param... objects) {
Query query = eManager.createNamedQuery(namedQuery);
for (Param param : objects) {
query.setParameter(param.name(), param.value());
}
return query.executeUpdate();
}
}

View File

@@ -0,0 +1,48 @@
package marketing.heyday.hartmann.fotodocumentation.core.service;
import java.util.Optional;
import jakarta.ejb.EJB;
import jakarta.ejb.LocalBean;
import jakarta.ejb.Stateless;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import marketing.heyday.hartmann.fotodocumentation.core.model.Customer;
import marketing.heyday.hartmann.fotodocumentation.core.model.Picture;
import marketing.heyday.hartmann.fotodocumentation.core.query.Param;
import marketing.heyday.hartmann.fotodocumentation.core.query.QueryService;
import marketing.heyday.hartmann.fotodocumentation.rest.vo.CustomerPictureValue;
/**
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 19 Jan 2026
*/
@Stateless
@LocalBean
public class CustomerPictureService {
@PersistenceContext
private EntityManager entityManager;
@EJB
private QueryService queryService;
public boolean addCustomerPicture(CustomerPictureValue customerPictureValue) {
Optional<Customer> customerOpt = queryService.callNamedQuerySingleResult(Customer.FIND_BY_NUMBER, new Param(Customer.PARAM_NUMBER, customerPictureValue.customerNumber()));
Customer customer = customerOpt.orElseGet(() -> new Customer.Builder().customerNumber(customerPictureValue.customerNumber()).name(customerPictureValue.pharmacyName()).build());
Picture picture = new Picture.Builder().username(customerPictureValue.username()).comment(customerPictureValue.comment()).image(customerPictureValue.base64String()).pictureDate(customerPictureValue.date()).build();
customer.getPictures().add(picture);
entityManager.persist(picture);
entityManager.merge(customer);
entityManager.flush();
return true;
}
}

View File

@@ -0,0 +1,49 @@
package marketing.heyday.hartmann.fotodocumentation.rest;
import org.jboss.resteasy.annotations.GZIP;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import jakarta.ejb.EJB;
import jakarta.enterprise.context.RequestScoped;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import marketing.heyday.hartmann.fotodocumentation.core.service.CustomerPictureService;
import marketing.heyday.hartmann.fotodocumentation.rest.jackson.JsonSchemaValidate;
import marketing.heyday.hartmann.fotodocumentation.rest.vo.CustomerPictureValue;
/**
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 19 Jan 2026
*/
@RequestScoped
@Path("customer-picture")
public class CustomerPictureResource {
@EJB
private CustomerPictureService customerPictureService;
@GZIP
@POST
@Path("")
//@Authenticate(shouldBeInAllRoles = RightUtils.ADMIN_RIGHT)
@Consumes(MediaType.APPLICATION_JSON)
@Operation(summary = "Add Customer Image to database")
@ApiResponse(responseCode = "200", description = "Add successfull")
public Response doAddCustomerPicture(@JsonSchemaValidate("schema/customer_picture_add.json") CustomerPictureValue customerPictureValue) {
boolean success = customerPictureService.addCustomerPicture(customerPictureValue);
return success ? Response.ok().build() : Response.status(Status.BAD_REQUEST).build();
}
}

View File

@@ -0,0 +1,36 @@
package marketing.heyday.hartmann.fotodocumentation.rest;
import jakarta.enterprise.context.RequestScoped;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
/**
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 14 Nov 2024
*/
@Path("monitoring")
@RequestScoped
public class MonitoringResource {
@GET
@Path("check/{text}")
@Produces(MediaType.TEXT_PLAIN)
@Operation(summary = "Monitoring service for testing if the server is up and running.")
@ApiResponse(responseCode = "200", description = "ok with as body the given path param text. ")
public Response check(@PathParam("text") String text) {
return Response.status(Status.OK).entity(text).build();
}
}

View File

@@ -0,0 +1,51 @@
package marketing.heyday.hartmann.fotodocumentation.rest.jackson;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import io.swagger.v3.jaxrs2.integration.resources.OpenApiResource;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Contact;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.servers.Server;
import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.MediaType;
import marketing.heyday.hartmann.fotodocumentation.rest.CustomerPictureResource;
import marketing.heyday.hartmann.fotodocumentation.rest.MonitoringResource;
/**
*
*
* <p>Copyright: Copyright (c) 2017</p>
* <p>Company: heyday marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 18 Oct 2017
*/
@OpenAPIDefinition(info = @Info(title = "Hartmann Photo upload API", version = "1.0", description = "All available routes for the Hartmann Photo upload API", contact = @Contact(url = "https://localhost", name = "Patrick Verboom", email = "p.verboom@heyday.marketing")), servers = {
@Server(description = "development", url = "http://localhost"),
@Server(description = "integration", url = "http://localhost"),
@Server(description = "production", url = "http://localhost")
})
@ApplicationPath("/api")
public class ApplicationConfigApi extends Application {
private static final Log LOG = LogFactory.getLog(ApplicationConfigApi.class);
public static final String JSON_OUT = MediaType.APPLICATION_JSON + "; charset=utf-8";
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> retVal = new HashSet<>();
retVal.add(OpenApiResource.class);
retVal.add(ValidatedMessageBodyReader.class);
//retVal.add(AuthenticateFilter.class);
retVal.add(MonitoringResource.class);
retVal.add(CustomerPictureResource.class);
LOG.info("returning rest api classes " + retVal);
return retVal;
}
}

View File

@@ -0,0 +1,21 @@
package marketing.heyday.hartmann.fotodocumentation.rest.jackson;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* <p>Copyright: Copyright (c) 2017</p>
* <p>Company: heyday marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: Feb 10, 2017
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(value={ElementType.PARAMETER})
public @interface JsonSchemaValidate {
String value();
}

View File

@@ -0,0 +1,14 @@
package marketing.heyday.hartmann.fotodocumentation.rest.jackson;
/**
*
* <p>Copyright: Copyright (c) 2017</p>
* <p>Company: heyday marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: Feb 10, 2017
*/
public interface SchemaValidated {
}

View File

@@ -0,0 +1,114 @@
package marketing.heyday.hartmann.fotodocumentation.rest.jackson;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.ext.MessageBodyReader;
import jakarta.ws.rs.ext.Provider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.networknt.schema.JsonSchema;
import com.networknt.schema.JsonSchemaFactory;
import com.networknt.schema.ValidationMessage;
/**
*
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 6 Dec 2024
*/
@Provider
@Consumes(value = {
MediaType.APPLICATION_JSON, "application/json; charset=utf-8"
})
public class ValidatedMessageBodyReader implements MessageBodyReader<SchemaValidated> {
private static final Log LOG = LogFactory.getLog(ValidatedMessageBodyReader.class);
/* (non-Javadoc)
* @see jakarta.ws.rs.ext.MessageBodyReader#isReadable(java.lang.Class, java.lang.reflect.Type, java.lang.annotation.Annotation[], jakarta.ws.rs.core.MediaType)
*/
@Override
public boolean isReadable(Class<?> classType, Type type, Annotation[] annotations, MediaType mediaType) {
if (mediaType.getType().contains("application/json")) {
return false;
}
return Arrays.stream(annotations).anyMatch(a -> a.annotationType() == JsonSchemaValidate.class);
}
/* (non-Javadoc)
* @see jakarta.ws.rs.ext.MessageBodyReader#readFrom(java.lang.Class, java.lang.reflect.Type, java.lang.annotation.Annotation[], jakarta.ws.rs.core.MediaType, jakarta.ws.rs.core.MultivaluedMap, java.io.InputStream)
*/
@Override
public SchemaValidated readFrom(Class<SchemaValidated> classType, Type type, Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> httpHeaders, InputStream input) throws IOException {
final String jsonData = read(input);
Optional<JsonSchemaValidate> annotation = Arrays.stream(annotations).filter(a -> a.annotationType() == JsonSchemaValidate.class).map(a -> (JsonSchemaValidate) a).findAny();
if (annotation.isPresent()) {
ValidationReply reply = validate(annotation.get(), jsonData);
if (!reply.success) {
throw new WebApplicationException(reply.getErrorResponse());
}
}
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(new StringReader(jsonData), classType);
}
/**
* @param jsonSchema
* @param jsonData
* @return
*/
private ValidationReply validate(JsonSchemaValidate jsonSchema, String jsonData) {
String schemaPath = jsonSchema.value();
try {
JsonSchema schema = getJsonSchema(schemaPath);
JsonNode node = getJsonNode(jsonData);
Set<ValidationMessage> errors = schema.validate(node);
if (!errors.isEmpty()) {
LOG.error("Failed to validate json to schema " + schemaPath);
errors.stream().forEach(LOG::error);
}
return new ValidationReply.Builder().success(errors.isEmpty()).errors(errors).build();
} catch (IOException e) {
LOG.error(e.getMessage(), e);
return new ValidationReply.Builder().success(false).build();
}
}
protected JsonSchema getJsonSchema(String name) throws IOException {
JsonSchemaFactory factory = new JsonSchemaFactory();
try (InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream(name);) {
return factory.getSchema(input);
}
}
protected JsonNode getJsonNode(String content) throws IOException {
return new ObjectMapper().readTree(content);
}
private String read(InputStream input) throws IOException {
try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input, Charset.forName("UTF-8")))) {
return buffer.lines().collect(Collectors.joining("\n"));
}
}
}

View File

@@ -0,0 +1,51 @@
package marketing.heyday.hartmann.fotodocumentation.rest.jackson;
import java.util.HashSet;
import java.util.Set;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import com.networknt.schema.ValidationMessage;
/**
*
* <p>Copyright: Copyright (c) 2017</p>
* <p>Company: heyday marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: Feb 14, 2017
*/
public final class ValidationReply {
public final boolean success;
public final Set<ValidationMessage> errors = new HashSet<>();
private ValidationReply(boolean success, Set<ValidationMessage> errors) {
this.success = success;
this.errors.addAll(errors);
}
public Response getErrorResponse() {
return Response.status(Status.BAD_REQUEST).entity(errors).build();
}
public static final class Builder {
private boolean success;
private Set<ValidationMessage> errors = new HashSet<>();
public Builder success(boolean success) {
this.success = success;
return this;
}
public Builder errors(Set<ValidationMessage> errors) {
this.errors = errors;
return this;
}
public ValidationReply build() {
return new ValidationReply(success, errors);
}
}
}

View File

@@ -0,0 +1,17 @@
package marketing.heyday.hartmann.fotodocumentation.rest.vo;
import java.util.Date;
/**
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 19 Jan 2026
*/
public record CustomerPictureValue(String username, String pharmacyName, String customerNumber, Date date, String comment, String base64String) {
}

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd"
version="4.0" bean-discovery-mode="all">
</beans>

View File

@@ -0,0 +1,24 @@
<persistence version="3.0" xmlns="https://jakarta.ee/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence
https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd">
<persistence-unit name="auth" transaction-type="JTA">
<jta-data-source>java:/jdbc/fotoDocumentationDS</jta-data-source>
<class>marketing.heyday.hartmann.fotodocumentation.core.model.Right</class>
<class>marketing.heyday.hartmann.fotodocumentation.core.model.User</class>
<class>marketing.heyday.hartmann.fotodocumentation.core.model.Customer</class>
<class>marketing.heyday.hartmann.fotodocumentation.core.model.Picture</class>
<properties>
<property name="hibernate.format_sql" value="false" />
<property name="hibernate.show_sql" value="false" />
<!-- <property name="hibernate.archive.autodetection" value="class" /> -->
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
<property name="hibernate.hbm2ddl.auto" value="none" />
<property name="hibernate.jpa.compliance.query" value="false" />
</properties>
</persistence-unit>
</persistence>

View File

@@ -0,0 +1,76 @@
-- Right
create sequence right_seq start 25;
create table x_right (
right_id bigint PRIMARY KEY,
code varchar(50) NOT NULL,
name varchar(150) NOT NULL,
jpa_active boolean NOT NULL,
jpa_created timestamp NOT NULL,
jpa_updated timestamp NOT NULL,
jpa_version integer NOT NULL,
CONSTRAINT unq_x_right_code UNIQUE(code)
);
-- user
create sequence user_seq start 25;
create table x_user (
user_id bigint PRIMARY KEY,
username varchar(150) NOT NULL,
password varchar(150) NOT NULL,
salt varchar(150) NOT NULL,
title varchar(15) ,
firstname varchar(150) NOT NULL,
lastname varchar(150) NOT NULL,
email varchar(150) NOT NULL,
jpa_active boolean NOT NULL,
jpa_created timestamp NOT NULL,
jpa_updated timestamp NOT NULL,
jpa_version integer NOT NULL,
CONSTRAINT unq_x_user_username UNIQUE(username)
);
create table user_to_right (
user_id_fk bigint REFERENCES x_user,
right_id_fk bigint REFERENCES x_right,
PRIMARY KEY(user_id_fk, right_id_fk)
);
-- customer
create sequence customer_seq start 25;
create table customer (
customer_id bigint PRIMARY KEY,
customer_number varchar(150) NOT NULL,
name varchar(150) NOT NULL,
jpa_active boolean NOT NULL,
jpa_created timestamp NOT NULL,
jpa_updated timestamp NOT NULL,
jpa_version integer NOT NULL,
CONSTRAINT unq_customer_number UNIQUE(customer_number)
);
-- picture
create sequence picture_seq start 25;
create table picture (
picture_id bigint PRIMARY KEY,
username varchar(150),
picture_date timestamp NOT NULL,
comment TEXT,
image TEXT,
jpa_active boolean NOT NULL,
jpa_created timestamp NOT NULL,
jpa_updated timestamp NOT NULL,
jpa_version integer NOT NULL,
customer_id_fk bigint REFERENCES customer
);

View File

@@ -0,0 +1,40 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Add Customer Picture",
"description": "Add a Customer Picture to the system",
"type": "object",
"properties": {
"username": {
"description": "The username from the user who uploads the picture",
"type": "string"
},
"pharmacyName": {
"description": "The Name from the pharmacy customer ",
"type": "string"
},
"customerNumber": {
"description": "The unique number from the pharmacy customer ",
"type": "string"
},
"date": {
"description": "The date when the picture is taken ",
"type": "string"
},
"comment": {
"description": "A free text comment field ",
"type": "string"
},
"base64String": {
"description": "The Picture content as base64 ",
"type": "string"
}
},
"required": [
"username",
"pharmacyName",
"customerNumber",
"date",
"comment",
"base64String"
]
}

View File

@@ -0,0 +1,16 @@
{
"api_key": {
"type": "apiKey",
"name": "api_key",
"in": "header"
},
"petstore_auth": {
"type": "oauth2",
"authorizationUrl": "http://swagger.io/api/oauth/dialog",
"flow": "implicit",
"scopes": {
"write:pets": "modify pets in your account",
"read:pets": "read your pets"
}
}
}

View File

@@ -0,0 +1,107 @@
#{{#info}}{{title}}
## {{join schemes " | "}}://{{host}}{{basePath}}
{{description}}
{{#contact}}
[**Contact the developer**](mailto:{{email}})
{{/contact}}
**Version** {{version}}
[**Terms of Service**]({{termsOfService}})
{{#license}}[**{{name}}**]({{url}}){{/license}}
{{/info}}
{{#if consumes}}**Consumes:** {{join consumes ", "}}{{/if}}
{{#if produces}}**Produces:** {{join produces ", "}}{{/if}}
{{#if securityDefinitions}}
# Security Definitions
{{/if}}
{{> security}}
# APIs
{{#each paths}}
## {{@key}}
{{#this}}
{{#get}}
### GET
{{> operation}}
{{/get}}
{{#put}}
### PUT
{{> operation}}
{{/put}}
{{#post}}
### POST
{{> operation}}
{{/post}}
{{#delete}}
### DELETE
{{> operation}}
{{/delete}}
{{#option}}
### OPTION
{{> operation}}
{{/option}}
{{#patch}}
### PATCH
{{> operation}}
{{/patch}}
{{#head}}
### HEAD
{{> operation}}
{{/head}}
{{/this}}
{{/each}}
# Definitions
{{#each definitions}}
## <a name="/definitions/{{key}}">{{@key}}</a>
<table border="1">
<tr>
<th>name</th>
<th>type</th>
<th>required</th>
<th>description</th>
<th>example</th>
</tr>
{{#each this.properties}}
<tr>
<td>{{@key}}</td>
<td>
{{#ifeq type "array"}}
{{#items.$ref}}
{{type}}[<a href="{{items.$ref}}">{{basename items.$ref}}</a>]
{{/items.$ref}}
{{^items.$ref}}{{type}}[{{items.type}}]{{/items.$ref}}
{{else}}
{{#$ref}}<a href="{{$ref}}">{{basename $ref}}</a>{{/$ref}}
{{^$ref}}{{type}}{{#format}} ({{format}}){{/format}}{{/$ref}}
{{/ifeq}}
</td>
<td>{{#required}}required{{/required}}{{^required}}optional{{/required}}</td>
<td>{{#description}}{{{description}}}{{/description}}{{^description}}-{{/description}}</td>
<td>{{example}}</td>
</tr>
{{/each}}
</table>
{{/each}}

View File

@@ -0,0 +1,81 @@
{{#deprecated}}-deprecated-{{/deprecated}}
<a id="{{operationId}}">{{summary}}</a>
{{{description}}}
{{#if externalDocs.url}}{{externalDocs.description}}. [See external documents for more details]({{externalDocs.url}})
{{/if}}
{{#if security}}
#### Security
{{/if}}
{{#security}}
{{#each this}}
* {{@key}}
{{#this}} * {{this}}
{{/this}}
{{/each}}
{{/security}}
#### Request
{{#if consumes}}
**Content-Type: ** {{join consumes ", "}}{{/if}}
##### Parameters
{{#if parameters}}
<table border="1">
<tr>
<th>Name</th>
<th>Located in</th>
<th>Required</th>
<th>Description</th>
<th>Default</th>
<th>Schema</th>
<th>Example</th>
</tr>
{{/if}}
{{#parameters}}
<tr>
<th>{{name}}</th>
<td>{{in}}</td>
<td>{{#if required}}yes{{else}}no{{/if}}</td>
<td>{{description}}{{#if pattern}} (**Pattern**: `{{pattern}}`){{/if}}</td>
<td> - </td>
{{#ifeq in "body"}}
<td>
{{#ifeq schema.type "array"}}Array[<a href="{{schema.items.$ref}}">{{basename schema.items.$ref}}</a>]{{/ifeq}}
{{#schema.$ref}}<a href="{{schema.$ref}}">{{basename schema.$ref}}</a> {{/schema.$ref}}
</td>
{{else}}
{{#ifeq type "array"}}
<td>Array[{{items.type}}] ({{collectionFormat}})</td>
{{else}}
<td>{{type}} {{#format}}({{format}}){{/format}}</td>
{{/ifeq}}
{{/ifeq}}
<td>
{{#each examples}}
{{{this}}}
{{/each}}
</td>
</tr>
{{/parameters}}
{{#if parameters}}
</table>
{{/if}}
#### Response
{{#if produces}}**Content-Type: ** {{join produces ", "}}{{/if}}
| Status Code | Reason | Response Model |
|-------------|-------------|----------------|
{{#each responses}}| {{@key}} | {{description}} | {{#schema.$ref}}<a href="{{schema.$ref}}">{{basename schema.$ref}}</a>{{/schema.$ref}}{{^schema.$ref}}{{#ifeq schema.type "array"}}Array[<a href="{{schema.items.$ref}}">{{basename schema.items.$ref}}</a>]{{else}}{{schema.type}}{{/ifeq}}{{/schema.$ref}}{{^schema}} - {{/schema}}|
{{/each}}

View File

@@ -0,0 +1,88 @@
{{#each securityDefinitions}}
### {{@key}}
{{#this}}
{{#ifeq type "oauth2"}}
<table>
<tr>
<th>type</th>
<th colspan="2">{{type}}</th>
</tr>
{{#if description}}
<tr>
<th>description</th>
<th colspan="2">{{description}}</th>
</tr>
{{/if}}
{{#if authorizationUrl}}
<tr>
<th>authorizationUrl</th>
<th colspan="2">{{authorizationUrl}}</th>
</tr>
{{/if}}
{{#if flow}}
<tr>
<th>flow</th>
<th colspan="2">{{flow}}</th>
</tr>
{{/if}}
{{#if tokenUrl}}
<tr>
<th>tokenUrl</th>
<th colspan="2">{{tokenUrl}}</th>
</tr>
{{/if}}
{{#if scopes}}
<tr>
<td rowspan="3">scopes</td>
{{#each scopes}}
<td>{{@key}}</td>
<td>{{this}}</td>
</tr>
<tr>
{{/each}}
</tr>
{{/if}}
</table>
{{/ifeq}}
{{#ifeq type "apiKey"}}
<table>
<tr>
<th>type</th>
<th colspan="2">{{type}}</th>
</tr>
{{#if description}}
<tr>
<th>description</th>
<th colspan="2">{{description}}</th>
</tr>
{{/if}}
{{#if name}}
<tr>
<th>name</th>
<th colspan="2">{{name}}</th>
</tr>
{{/if}}
{{#if in}}
<tr>
<th>in</th>
<th colspan="2">{{in}}</th>
</tr>
{{/if}}
</table>
{{/ifeq}}
{{#ifeq type "basic"}}
<table>
<tr>
<th>type</th>
<th colspan="2">{{type}}</th>
</tr>
{{#if description}}
<tr>
<th>description</th>
<th colspan="2">{{description}}</th>
</tr>
{{/if}}
</table>
{{/ifeq}}
{{/this}}
{{/each}}

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<title>API Document</title>
<xmp theme="united" style="display:none;">
{{>markdown}}
</xmp>
<script src="http://strapdownjs.com/v/0.2/strapdown.js"></script>
<!-- code for TOC (jquery plugin) (see http://projects.jga.me/toc/#toc0) -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://rawgit.com/jgallen23/toc/master/dist/toc.min.js"></script>
<script src="https://rawgit.com/zipizap/strapdown_template/master/js/init_TOC.js"></script>
</html>

View File

@@ -0,0 +1,19 @@
package org.mockito.configuration;
/**
*
* <p>Copyright: Copyright (c) 2016</p>
* <p>Company: heyday marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: Oct 14, 2016
*/
public class MockitoConfiguration extends DefaultMockitoConfiguration {
@Override
public boolean enableClassCache() {
return false;
}
}

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<param name="Threshold" value="DEBUG"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c] %m%n"/>
</layout>
</appender>
<!-- ================ -->
<!-- Limit categories -->
<!-- ================ -->
<!-- Limit the org.apache category to INFO as its DEBUG is verbose -->
<category name="org.apache">
<priority value="INFO"/>
</category>
<category name="com.bm">
<priority value="INFO"/>
</category>
<category name="com.bm.introspectors">
<priority value="ERROR"/>
</category>
<category name="org.hibernate.cfg.annotations">
<priority value="WARN"/>
</category>
<category name="org.hibernate.cfg">
<priority value="WARN"/>
</category>
<category name="org.hibernate.tool">
<priority value="WARN"/>
</category>
<category name="org.hibernate.validator">
<priority value="WARN"/>
</category>
<category name="org.hibernate">
<priority value="ERROR"/>
</category>
<category name="org.dbunit">
<priority value="DEBUG"/>
</category>
<category name="de.juwimm">
<priority value="DEBUG"/>
</category>
<category name="STDOUT">
<priority value="DEBUG"/>
</category>
<root>
<appender-ref ref="CONSOLE"/>
</root>
</log4j:configuration>

View File

@@ -0,0 +1,530 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>marketing.heyday.hartmann.fotodocumentation</groupId>
<artifactId>hartmann-foto-documentation</artifactId>
<version>1.0.0</version>
<relativePath>../hartmann-foto-documentation/pom.xml</relativePath>
</parent>
<artifactId>hartmann-foto-documentation-docker</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>hartmann-foto-documentation docker</name>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<configuration>
<skip>true</skip>
<skipDeploy>true</skipDeploy>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M1</version>
<configuration>
<skipTests>true</skipTests>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<sonar.java.libraries>${project.build.directory}/lib/*.jar</sonar.java.libraries>
<sonar.libraries>${project.build.directory}/lib/*.jar</sonar.libraries>
</properties>
<profiles>
<profile>
<id>docker</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.1</version>
<configuration>
<skip>true</skip>
<skipDeploy>true</skipDeploy>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M1</version>
<configuration>
<skip>true</skip>
<skipTests>true</skipTests>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>test</goal>
</goals>
<phase>integration-test</phase>
<configuration>
<skip>false</skip>
<skipTests>false</skipTests>
<argLine />
<forkMode>once</forkMode>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.45.1</version>
<extensions>true</extensions>
<configuration>
<autoPull>true</autoPull>
<startParallel>false</startParallel>
<showLogs>true</showLogs>
<autoCreateCustomNetworks>true</autoCreateCustomNetworks>
<images>
<image>
<alias>hartmann_postgres</alias>
<name>postgres:11</name>
<run>
<ports>
<port>5430:5432</port>
</ports>
<network>
<name>hartmann_nw</name>
<alias>hartmann_postgres</alias>
</network>
<env>
<POSTGRES_HOST_AUTH_METHOD>trust</POSTGRES_HOST_AUTH_METHOD>
</env>
<volumes>
<bind>
<volume>${basedir}/src/main/docker/sql:/docker-entrypoint-initdb.d</volume>
</bind>
</volumes>
<wait>
<log>database system is ready to accept connections</log>
<time>2500000</time>
</wait>
</run>
</image>
<image>
<!-- Artifact Image -->
<name>${project.artifactId}</name>
<alias>hartmann</alias>
<build>
<dockerFile>Dockerfile</dockerFile>
<args>
<deploymentDir>maven</deploymentDir>
</args>
<tags>
<tag>latest</tag>
</tags>
</build>
<registry>hub.heyday.marketing</registry>
<run>
<cmd>
/srv/wait-for-it.sh
hartmann_postgres:5432" --
/srv/wildfly/bin/standalone-jacoco.sh
-b 0.0.0.0 -c test-standalone.xml
</cmd>
<ports>
<port>8180:8080</port>
</ports>
<dependsOn>
<container>hartmann_postgres</container>
</dependsOn>
<network>
<name>hartmann_nw</name>
<alias>hartmann</alias>
</network>
<volumes>
<bind>
<volume>${basedir}/target:/srv/target</volume>
</bind>
</volumes>
<wait>
<!-- The plugin waits until this URL
is reachable via HTTP ... -->
<http>
<url>http://${docker.host.address}:8180/api/monitoring/check/hello</url>
</http>
<time>300000</time>
</wait>
</run>
</image>
</images>
</configuration>
<executions>
<execution>
<id>build</id>
<phase>package</phase>
<goals>
<goal>build</goal>
<!-- <goal>push</goal> -->
</goals>
</execution>
<execution>
<id>start</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<id>copy-resources</id>
<!-- here the phase you need -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/src/main/docker</outputDirectory>
<resources>
<resource>
<directory>${basedir}/../hartmann-foto-documentation-web/target/</directory>
<includes>
<include>*.war</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
<execution>
<id>copy-resources2</id>
<!-- here the phase you need -->
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.basedir}/target/classes</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/../hartmann-foto-documentation-app/target/classes</directory>
<filtering>false</filtering>
</resource>
</resources>
</configuration>
</execution>
<execution>
<id>copy-jacoco-app</id>
<!-- here the phase you need -->
<phase>verify</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.basedir}/../hartmann-foto-documentation-app/target</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/target</directory>
<filtering>false</filtering>
<includes>
<include>jacoco-it.exec</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version> <!-- was 3.11.0 -->
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-edge-driver</artifactId>
</exclusion>
<exclusion>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-firefox-driver</artifactId>
</exclusion>
<exclusion>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-ie-driver</artifactId>
</exclusion>
<exclusion>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-opera-driver</artifactId>
</exclusion>
<exclusion>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-safari-driver</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-api</artifactId>
<version>3.141.59</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
<version>3.141.59</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-remote-driver</artifactId>
<version>3.141.59</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-support</artifactId>
<version>3.141.59</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>hartmann-foto-documentation-web</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>hartmann-foto-documentation-app</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Websocket test api's -->
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-client-api</artifactId>
<version>1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-client</artifactId>
<version>1.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-container-grizzly</artifactId>
<version>1.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId>
<version>1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.1</version>
<scope>test</scope>
</dependency>
<!-- Websocket test api's -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${version.commons-lang3}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jacoco</groupId>
<artifactId>org.jacoco.core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.dbunit</groupId>
<artifactId>dbunit</artifactId>
<version>2.7.0</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson2-provider</artifactId>
<version>${version.org.jboss.resteasy}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-commons</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${version.commons-io}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>${version.commons-logging}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>fluent-hc</artifactId>
<version>4.5.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.xmlunit</groupId>
<artifactId>xmlunit-core</artifactId>
<version>2.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.skyscreamer</groupId>
<artifactId>jsonassert</artifactId>
<version>1.2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.5</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,52 @@
############################################################
# Dockerfile to build wildfly Hartmann Foto Documentation docker image
# Based on jboss/wildfly
############################################################
# Pull base image.
FROM hub.heyday.marketing/verboomp/wildfly:33.0.2-Final
# File Author / Maintainer
LABEL org.opencontainers.image.authors="Patrick Verboom <p.verboom@heyday.marketing>"
USER root
RUN apt-get update && apt-get install -y unzip
# install the postgres driver
RUN wget 'https://nexus.heyday.marketing/repository/maven-releases/com/ayeqbenu/wildfly/database/modules/postgres-jdbc/1.1.0/postgres-jdbc-1.1.0.zip' -O /srv/postgres-jdbc.zip \
&& unzip /srv/postgres-jdbc.zip -d ${JBOSS_HOME}/modules \
&& rm -rf /srv/postgres-jdbc.zip
# install the startup wait script to make sure postgres is booted before wildfly
COPY wait-for-it.sh /srv/wait-for-it.sh
RUN chmod 777 /srv/wait-for-it.sh
# copy the jacoco agent for code coverage
COPY jacoco/jacocoagent.jar /srv/jacocoagent.jar
run chmod 777 /srv/jacocoagent.jar
COPY standalone-jacoco.sh ${JBOSS_HOME}/bin/standalone-jacoco.sh
RUN chmod 777 ${JBOSS_HOME}/bin/standalone-jacoco.sh
# install the wildfly config xml file
# COPY test-standalone.xml ${JBOSS_HOME}/standalone/configuration/test-standalone.xml
COPY standalone-fotodocumentation.xml ${JBOSS_HOME}/standalone/configuration/test-standalone.xml
# install the web war file
COPY hartmann-foto-documentation-web-*.war ${JBOSS_HOME}/standalone/deployments
# Expose the ports we're interested in
EXPOSE 8080
EXPOSE 9990
# Set the default command to run on boot
# This will boot WildFly in the standalone mode and bind to all interface
CMD ["/srv/wildfly/bin/standalone.sh", "-b", "0.0.0.0", "-c", "test-standalone.xml"]

View File

@@ -0,0 +1,40 @@
services:
smtp-server:
image: andreptb/smtp-server-for-it:0.2.0
ports:
- "8280:8080"
networks:
- hartmann_nw
environment:
- smtp.port=26
hartmann_postgres:
image: postgres:11
volumes:
- ./sql:/docker-entrypoint-initdb.d
ports:
- "5430:5432"
networks:
- hartmann_nw
environment:
- POSTGRES_HOST_AUTH_METHOD=trust
hartmann:
build: .
ports:
- "8180:8080"
- "9990:9990"
depends_on:
- hartmann_postgres
networks:
- hartmann_nw
command: ["/srv/wait-for-it.sh", "cue_postgres:5432", "--", "/srv/wildfly/bin/standalone-jacoco.sh", "-b", "0.0.0.0", "-c", "test-standalone.xml"]
volumes:
- ./../../../target:/srv/target:z
networks:
hartmann_nw:
volumes:
jacoco:

View File

@@ -0,0 +1,80 @@
--
-- PostgreSQL database dump
--
-- Dumped from database version 9.4.5
-- Dumped by pg_dump version 9.6.5
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SET check_function_bodies = false;
SET client_min_messages = warning;
SET row_security = off;
--
-- Name: fotodocumentation; Type: DATABASE; Schema: -; Owner: postgres
--
CREATE ROLE fotodocumentation WITH
LOGIN
NOSUPERUSER
NOCREATEDB
NOCREATEROLE
INHERIT
NOREPLICATION
CONNECTION LIMIT -1
PASSWORD 'fotodocumentation';
CREATE DATABASE fotodocumentation WITH TEMPLATE = template0 ENCODING = 'UTF8' LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8';
ALTER DATABASE fotodocumentation OWNER TO postgres;
\connect fotodocumentation
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SET check_function_bodies = false;
SET client_min_messages = warning;
SET row_security = off;
--
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner:
--
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
--
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner:
--
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
SET search_path = public, pg_catalog;
SET default_tablespace = '';
SET default_with_oids = false;
--
-- Name: public; Type: ACL; Schema: -; Owner: postgres
--
REVOKE ALL ON SCHEMA public FROM PUBLIC;
REVOKE ALL ON SCHEMA public FROM postgres;
GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO PUBLIC;
--
-- PostgreSQL database dump complete
--

View File

@@ -0,0 +1,618 @@
<?xml version="1.0" encoding="UTF-8"?>
<server xmlns="urn:jboss:domain:20.0">
<extensions>
<extension module="org.jboss.as.clustering.infinispan"/>
<extension module="org.jboss.as.connector"/>
<extension module="org.jboss.as.deployment-scanner"/>
<extension module="org.jboss.as.ee"/>
<extension module="org.jboss.as.ejb3"/>
<extension module="org.jboss.as.jaxrs"/>
<extension module="org.jboss.as.jdr"/>
<extension module="org.jboss.as.jmx"/>
<extension module="org.jboss.as.jpa"/>
<extension module="org.jboss.as.jsf"/>
<extension module="org.jboss.as.logging"/>
<extension module="org.jboss.as.mail"/>
<extension module="org.jboss.as.naming"/>
<extension module="org.jboss.as.pojo"/>
<extension module="org.jboss.as.remoting"/>
<extension module="org.jboss.as.sar"/>
<extension module="org.jboss.as.transactions"/>
<extension module="org.jboss.as.webservices"/>
<extension module="org.jboss.as.weld"/>
<extension module="org.wildfly.extension.batch.jberet"/>
<extension module="org.wildfly.extension.bean-validation"/>
<extension module="org.wildfly.extension.clustering.ejb"/>
<extension module="org.wildfly.extension.clustering.web"/>
<extension module="org.wildfly.extension.core-management"/>
<extension module="org.wildfly.extension.discovery"/>
<extension module="org.wildfly.extension.ee-security"/>
<extension module="org.wildfly.extension.elytron"/>
<extension module="org.wildfly.extension.elytron-oidc-client"/>
<extension module="org.wildfly.extension.health"/>
<extension module="org.wildfly.extension.io"/>
<extension module="org.wildfly.extension.metrics"/>
<extension module="org.wildfly.extension.microprofile.config-smallrye"/>
<extension module="org.wildfly.extension.microprofile.jwt-smallrye"/>
<extension module="org.wildfly.extension.request-controller"/>
<extension module="org.wildfly.extension.security.manager"/>
<extension module="org.wildfly.extension.undertow"/>
</extensions>
<system-properties>
</system-properties>
<management>
<audit-log>
<formatters>
<json-formatter name="json-formatter"/>
</formatters>
<handlers>
<file-handler name="file" formatter="json-formatter" path="audit-log.log" relative-to="jboss.server.data.dir"/>
</handlers>
<logger log-boot="true" log-read-only="false" enabled="false">
<handlers>
<handler name="file"/>
</handlers>
</logger>
</audit-log>
<management-interfaces>
<http-interface http-authentication-factory="management-http-authentication">
<http-upgrade enabled="true" sasl-authentication-factory="management-sasl-authentication"/>
<socket-binding http="management-http"/>
</http-interface>
</management-interfaces>
<access-control provider="simple">
<role-mapping>
<role name="SuperUser">
<include>
<user name="$local"/>
</include>
</role>
</role-mapping>
</access-control>
</management>
<profile>
<subsystem xmlns="urn:jboss:domain:logging:8.0">
<console-handler name="CONSOLE">
<level name="DEBUG"/>
<formatter>
<named-formatter name="COLOR-PATTERN"/>
</formatter>
</console-handler>
<periodic-rotating-file-handler name="FILE" autoflush="true">
<formatter>
<named-formatter name="PATTERN"/>
</formatter>
<file relative-to="jboss.server.log.dir" path="server.log"/>
<suffix value=".yyyy-MM-dd"/>
<append value="true"/>
</periodic-rotating-file-handler>
<logger category="com.arjuna">
<level name="WARN"/>
</logger>
<logger category="com.networknt.schema">
<level name="WARN"/>
</logger>
<logger category="io.jaegertracing.Configuration">
<level name="WARN"/>
</logger>
<logger category="org.jboss.as.config">
<level name="DEBUG"/>
</logger>
<logger category="org.jboss">
<level name="INFO"/>
</logger>
<logger category="org.hibernate">
<level name="INFO"/>
</logger>
<logger category="marketing.heyday.hartmann">
<level name="DEBUG"/>
</logger>
<logger category="sun.rmi">
<level name="WARN"/>
</logger>
<root-logger>
<level name="DEBUG"/>
<handlers>
<handler name="CONSOLE"/>
<handler name="FILE"/>
</handlers>
</root-logger>
<formatter name="PATTERN">
<pattern-formatter pattern="%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/>
</formatter>
<formatter name="COLOR-PATTERN">
<pattern-formatter pattern="%K{level}%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/>
</formatter>
</subsystem>
<subsystem xmlns="urn:jboss:domain:batch-jberet:3.0">
<default-job-repository name="in-memory"/>
<default-thread-pool name="batch"/>
<security-domain name="ApplicationDomain"/>
<job-repository name="in-memory">
<in-memory/>
</job-repository>
<thread-pool name="batch">
<max-threads count="10"/>
<keepalive-time time="30" unit="seconds"/>
</thread-pool>
</subsystem>
<subsystem xmlns="urn:jboss:domain:bean-validation:1.0"/>
<subsystem xmlns="urn:jboss:domain:core-management:1.0"/>
<subsystem xmlns="urn:jboss:domain:datasources:7.1">
<datasources>
<datasource jndi-name="java:/jdbc/fotoDocumentationDS" pool-name="fotoDocumentationDS" enabled="true" use-java-context="true" use-ccm="false">
<connection-url>jdbc:postgresql://hartmann_postgres:5432/fotodocumentation</connection-url>
<driver>postgres</driver>
<transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
<pool>
<min-pool-size>1</min-pool-size>
<max-pool-size>10</max-pool-size>
</pool>
<security user-name="fotodocumentation" password="fotodocumentation"/>
<validation>
<valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker"/>
<exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter"/>
</validation>
<statement>
<prepared-statement-cache-size>32</prepared-statement-cache-size>
<share-prepared-statements>true</share-prepared-statements>
</statement>
</datasource>
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true" statistics-enabled="${wildfly.datasources.statistics-enabled:${wildfly.statistics-enabled:false}}">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=${wildfly.h2.compatibility.mode:REGULAR}</connection-url>
<driver>h2</driver>
<security user-name="sa" password="sa"/>
</datasource>
<drivers>
<driver name="postgres" module="org.postgresql.jdbc">
<xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
</driver>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
</drivers>
</datasources>
</subsystem>
<subsystem xmlns="urn:jboss:domain:deployment-scanner:2.0">
<deployment-scanner path="deployments" relative-to="jboss.server.base.dir" scan-interval="5000" runtime-failure-causes-rollback="${jboss.deployment.scanner.rollback.on.failure:false}"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:discovery:1.0"/>
<subsystem xmlns="urn:jboss:domain:distributable-ejb:1.0" default-bean-management="default">
<infinispan-bean-management name="default" max-active-beans="10000" cache-container="ejb" cache="passivation"/>
<local-client-mappings-registry/>
<infinispan-timer-management name="persistent" cache-container="ejb" cache="persistent" max-active-timers="10000"/>
<infinispan-timer-management name="transient" cache-container="ejb" cache="transient" max-active-timers="10000"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:distributable-web:4.0" default-session-management="default" default-single-sign-on-management="default">
<infinispan-session-management name="default" cache-container="web" granularity="SESSION">
<local-affinity/>
</infinispan-session-management>
<infinispan-single-sign-on-management name="default" cache-container="web" cache="sso"/>
<local-routing/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:ee:6.0">
<spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
<concurrent>
<context-services>
<context-service name="default" jndi-name="java:jboss/ee/concurrency/context/default"/>
</context-services>
<managed-thread-factories>
<managed-thread-factory name="default" jndi-name="java:jboss/ee/concurrency/factory/default" context-service="default"/>
</managed-thread-factories>
<managed-executor-services>
<managed-executor-service name="default" jndi-name="java:jboss/ee/concurrency/executor/default" context-service="default" hung-task-termination-period="0" hung-task-threshold="60000" keepalive-time="5000"/>
</managed-executor-services>
<managed-scheduled-executor-services>
<managed-scheduled-executor-service name="default" jndi-name="java:jboss/ee/concurrency/scheduler/default" context-service="default" hung-task-termination-period="0" hung-task-threshold="60000" keepalive-time="3000"/>
</managed-scheduled-executor-services>
</concurrent>
<default-bindings context-service="java:jboss/ee/concurrency/context/default" datasource="java:jboss/datasources/ExampleDS" managed-executor-service="java:jboss/ee/concurrency/executor/default" managed-scheduled-executor-service="java:jboss/ee/concurrency/scheduler/default" managed-thread-factory="java:jboss/ee/concurrency/factory/default"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:ee-security:1.0"/>
<subsystem xmlns="urn:jboss:domain:ejb3:10.0">
<session-bean>
<stateless>
<bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>
</stateless>
<stateful default-access-timeout="5000" cache-ref="simple" passivation-disabled-cache-ref="simple"/>
<singleton default-access-timeout="5000"/>
</session-bean>
<pools>
<bean-instance-pools>
<strict-max-pool name="slsb-strict-max-pool" derive-size="from-worker-pools" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
<strict-max-pool name="mdb-strict-max-pool" derive-size="from-cpu-count" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
</bean-instance-pools>
</pools>
<caches>
<simple-cache name="simple"/>
<distributable-cache name="distributable"/>
</caches>
<async thread-pool-name="default"/>
<timer-service thread-pool-name="default" default-data-store="default-file-store">
<data-stores>
<file-data-store name="default-file-store" path="timer-service-data" relative-to="jboss.server.data.dir"/>
</data-stores>
</timer-service>
<remote connectors="http-remoting-connector" thread-pool-name="default">
<channel-creation-options>
<option name="MAX_OUTBOUND_MESSAGES" value="1234" type="remoting"/>
</channel-creation-options>
</remote>
<thread-pools>
<thread-pool name="default">
<max-threads count="10"/>
<keepalive-time time="60" unit="seconds"/>
</thread-pool>
</thread-pools>
<default-security-domain value="other"/>
<application-security-domains>
<application-security-domain name="other" security-domain="ApplicationDomain"/>
<!--patrick-->
<application-security-domain name="fotoDocumentationSecurity" security-domain="fotoDocumentationDomain"/>
</application-security-domains>
<default-missing-method-permissions-deny-access value="true"/>
<statistics enabled="${wildfly.ejb3.statistics-enabled:${wildfly.statistics-enabled:false}}"/>
<log-system-exceptions value="true"/>
</subsystem>
<subsystem xmlns="urn:wildfly:elytron:community:18.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto">
<providers>
<aggregate-providers name="combined-providers">
<providers name="elytron"/>
<providers name="openssl"/>
</aggregate-providers>
<provider-loader name="elytron" module="org.wildfly.security.elytron"/>
<provider-loader name="openssl" module="org.wildfly.openssl"/>
</providers>
<audit-logging>
<file-audit-log name="local-audit" path="audit.log" relative-to="jboss.server.log.dir" format="JSON"/>
</audit-logging>
<security-domains>
<security-domain name="ApplicationDomain" default-realm="ApplicationRealm" permission-mapper="default-permission-mapper">
<realm name="ApplicationRealm" role-decoder="groups-to-roles"/>
<realm name="local"/>
</security-domain>
<security-domain name="ManagementDomain" default-realm="ManagementRealm" permission-mapper="default-permission-mapper">
<realm name="ManagementRealm" role-decoder="groups-to-roles"/>
<realm name="local" role-mapper="super-user-mapper"/>
</security-domain>
<!-- patrick -->
<security-domain name="fotoDocumentationDomain" default-realm="fotoDocumentationRealm" permission-mapper="default-permission-mapper">
<realm name="fotoDocumentationRealm" role-decoder="groups-to-roles"/>
</security-domain>
</security-domains>
<security-realms>
<identity-realm name="local" identity="$local"/>
<properties-realm name="ApplicationRealm">
<users-properties path="application-users.properties" relative-to="jboss.server.config.dir" digest-realm-name="ApplicationRealm"/>
<groups-properties path="application-roles.properties" relative-to="jboss.server.config.dir"/>
</properties-realm>
<properties-realm name="ManagementRealm">
<users-properties path="mgmt-users.properties" relative-to="jboss.server.config.dir" digest-realm-name="ManagementRealm"/>
<groups-properties path="mgmt-groups.properties" relative-to="jboss.server.config.dir"/>
</properties-realm>
<!-- patrick -->
<jdbc-realm name="fotoDocumentationRealm" >
<principal-query data-source="fotoDocumentationDS" sql="select password, salt, ri.code as Role from x_user u left join role_to_right rtr on rtr.role_id_fk = u.role_id_fk left join x_right ri on rtr.right_id_fk = ri.right_id where username = ?;">
<salted-simple-digest-mapper algorithm="password-salt-digest-sha-256" password-index="1" salt-index="2" />
<attribute-mapping>
<attribute to="groups" index="3"/>
</attribute-mapping>
</principal-query>
</jdbc-realm>
</security-realms>
<mappers>
<simple-permission-mapper name="default-permission-mapper" mapping-mode="first">
<permission-mapping>
<principal name="anonymous"/>
<permission-set name="default-permissions"/>
</permission-mapping>
<permission-mapping match-all="true">
<permission-set name="login-permission"/>
<permission-set name="default-permissions"/>
</permission-mapping>
</simple-permission-mapper>
<constant-realm-mapper name="local" realm-name="local"/>
<simple-role-decoder name="groups-to-roles" attribute="groups"/>
<constant-role-mapper name="super-user-mapper">
<role name="SuperUser"/>
</constant-role-mapper>
</mappers>
<permission-sets>
<permission-set name="login-permission">
<permission class-name="org.wildfly.security.auth.permission.LoginPermission"/>
</permission-set>
<permission-set name="default-permissions">
<permission class-name="org.wildfly.transaction.client.RemoteTransactionPermission" module="org.wildfly.transaction.client"/>
<permission class-name="org.jboss.ejb.client.RemoteEJBPermission" module="org.jboss.ejb-client"/>
<permission class-name="org.wildfly.extension.batch.jberet.deployment.BatchPermission" module="org.wildfly.extension.batch.jberet" target-name="*"/>
</permission-set>
</permission-sets>
<http>
<http-authentication-factory name="application-http-authentication" security-domain="ApplicationDomain" http-server-mechanism-factory="global">
<mechanism-configuration>
<mechanism mechanism-name="BASIC">
<mechanism-realm realm-name="ApplicationRealm"/>
</mechanism>
</mechanism-configuration>
</http-authentication-factory>
<http-authentication-factory name="management-http-authentication" security-domain="ManagementDomain" http-server-mechanism-factory="global">
<mechanism-configuration>
<mechanism mechanism-name="DIGEST">
<mechanism-realm realm-name="ManagementRealm"/>
</mechanism>
</mechanism-configuration>
</http-authentication-factory>
<!-- patrick -->
<http-authentication-factory name="fotoDocumentation-http-authentication" security-domain="fotoDocumentationDomain" http-server-mechanism-factory="global">
<mechanism-configuration>
<mechanism mechanism-name="BASIC">
<mechanism-realm realm-name="fotoDocumentationRealm"/>
</mechanism>
</mechanism-configuration>
</http-authentication-factory>
<provider-http-server-mechanism-factory name="global"/>
</http>
<sasl>
<sasl-authentication-factory name="application-sasl-authentication" sasl-server-factory="configured" security-domain="ApplicationDomain">
<mechanism-configuration>
<mechanism mechanism-name="JBOSS-LOCAL-USER" realm-mapper="local"/>
<mechanism mechanism-name="DIGEST-MD5">
<mechanism-realm realm-name="ApplicationRealm"/>
</mechanism>
</mechanism-configuration>
</sasl-authentication-factory>
<sasl-authentication-factory name="management-sasl-authentication" sasl-server-factory="configured" security-domain="ManagementDomain">
<mechanism-configuration>
<mechanism mechanism-name="JBOSS-LOCAL-USER" realm-mapper="local"/>
<mechanism mechanism-name="DIGEST-MD5">
<mechanism-realm realm-name="ManagementRealm"/>
</mechanism>
</mechanism-configuration>
</sasl-authentication-factory>
<configurable-sasl-server-factory name="configured" sasl-server-factory="elytron">
<properties>
<property name="wildfly.sasl.local-user.default-user" value="$local"/>
<property name="wildfly.sasl.local-user.challenge-path" value="${jboss.server.temp.dir}/auth"/>
</properties>
</configurable-sasl-server-factory>
<mechanism-provider-filtering-sasl-server-factory name="elytron" sasl-server-factory="global">
<filters>
<filter provider-name="WildFlyElytron"/>
</filters>
</mechanism-provider-filtering-sasl-server-factory>
<provider-sasl-server-factory name="global"/>
</sasl>
<tls>
<key-stores>
<key-store name="applicationKS">
<credential-reference clear-text="password"/>
<implementation type="JKS"/>
<file path="application.keystore" relative-to="jboss.server.config.dir"/>
</key-store>
</key-stores>
<key-managers>
<key-manager name="applicationKM" key-store="applicationKS" generate-self-signed-certificate-host="localhost">
<credential-reference clear-text="password"/>
</key-manager>
</key-managers>
<server-ssl-contexts>
<server-ssl-context name="applicationSSC" key-manager="applicationKM"/>
</server-ssl-contexts>
</tls>
<policy name="jacc">
<jacc-policy/>
</policy>
</subsystem>
<subsystem xmlns="urn:wildfly:elytron-oidc-client:2.0"/>
<subsystem xmlns="urn:wildfly:health:1.0" security-enabled="false"/>
<subsystem xmlns="urn:jboss:domain:infinispan:14.0">
<cache-container name="hibernate" marshaller="JBOSS" modules="org.infinispan.hibernate-cache">
<local-cache name="entity">
<heap-memory size="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<local-cache name="local-query">
<heap-memory size="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<local-cache name="timestamps">
<expiration interval="0"/>
</local-cache>
<local-cache name="pending-puts">
<expiration max-idle="60000"/>
</local-cache>
</cache-container>
<cache-container name="ejb" default-cache="passivation" marshaller="PROTOSTREAM" aliases="sfsb" modules="org.wildfly.clustering.ejb.infinispan">
<local-cache name="passivation">
<expiration interval="0"/>
<file-store passivation="true"/>
</local-cache>
<local-cache name="persistent">
<locking isolation="REPEATABLE_READ"/>
<transaction mode="BATCH"/>
<expiration interval="0"/>
<file-store preload="true"/>
</local-cache>
<local-cache name="transient">
<locking isolation="REPEATABLE_READ"/>
<transaction mode="BATCH"/>
<expiration interval="0"/>
<file-store passivation="true" purge="true"/>
</local-cache>
</cache-container>
<cache-container name="web" default-cache="passivation" marshaller="PROTOSTREAM" modules="org.wildfly.clustering.web.infinispan">
<local-cache name="passivation">
<expiration interval="0"/>
<file-store passivation="true"/>
</local-cache>
<local-cache name="sso">
<expiration interval="0"/>
</local-cache>
</cache-container>
</subsystem>
<subsystem xmlns="urn:jboss:domain:io:4.0" default-worker="default">
<worker name="default"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:jaxrs:3.0"/>
<subsystem xmlns="urn:jboss:domain:jca:6.0">
<archive-validation enabled="true" fail-on-error="true" fail-on-warn="false"/>
<bean-validation enabled="true"/>
<default-workmanager>
<short-running-threads>
<core-threads count="50"/>
<queue-length count="50"/>
<max-threads count="50"/>
<keepalive-time time="10" unit="seconds"/>
</short-running-threads>
<long-running-threads>
<core-threads count="50"/>
<queue-length count="50"/>
<max-threads count="50"/>
<keepalive-time time="10" unit="seconds"/>
</long-running-threads>
</default-workmanager>
<cached-connection-manager/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:jdr:1.0"/>
<subsystem xmlns="urn:jboss:domain:jmx:1.3">
<expose-resolved-model/>
<expose-expression-model/>
<remoting-connector/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:jpa:1.1">
<jpa default-extended-persistence-inheritance="DEEP"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:jsf:1.1"/>
<subsystem xmlns="urn:jboss:domain:mail:4.0">
<mail-session name="default" jndi-name="java:jboss/mail/Default">
<smtp-server outbound-socket-binding-ref="mail-smtp"/>
</mail-session>
<!-- Patrick -->
<mail-session name="fotoDocumentationMail" debug="true" jndi-name="java:/mail/fotoDocumentation-mail">
<smtp-server outbound-socket-binding-ref="mail-smtp"/>
</mail-session>
</subsystem>
<subsystem xmlns="urn:wildfly:metrics:1.0" security-enabled="false" exposed-subsystems="*" prefix="${wildfly.metrics.prefix:wildfly}"/>
<subsystem xmlns="urn:wildfly:microprofile-config-smallrye:2.0"/>
<subsystem xmlns="urn:wildfly:microprofile-jwt-smallrye:1.0"/>
<subsystem xmlns="urn:jboss:domain:naming:2.0">
<remote-naming/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:pojo:1.0"/>
<subsystem xmlns="urn:jboss:domain:remoting:7.0">
<endpoint worker="default"/>
<http-connector name="http-remoting-connector" connector-ref="default" sasl-authentication-factory="application-sasl-authentication"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:request-controller:1.0"/>
<subsystem xmlns="urn:jboss:domain:resource-adapters:7.1"/>
<subsystem xmlns="urn:jboss:domain:sar:1.0"/>
<subsystem xmlns="urn:jboss:domain:security-manager:1.0">
<deployment-permissions>
<maximum-set>
<permission class="java.security.AllPermission"/>
</maximum-set>
</deployment-permissions>
</subsystem>
<subsystem xmlns="urn:jboss:domain:transactions:6.0">
<core-environment node-identifier="${jboss.tx.node.id:1}">
<process-id>
<uuid/>
</process-id>
</core-environment>
<recovery-environment socket-binding="txn-recovery-environment" status-socket-binding="txn-status-manager"/>
<coordinator-environment statistics-enabled="${wildfly.transactions.statistics-enabled:${wildfly.statistics-enabled:false}}"/>
<object-store path="tx-object-store" relative-to="jboss.server.data.dir"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:undertow:14.0" default-virtual-host="default-host" default-servlet-container="default" default-server="default-server" statistics-enabled="${wildfly.undertow.statistics-enabled:${wildfly.statistics-enabled:false}}" default-security-domain="other">
<byte-buffer-pool name="default"/>
<buffer-cache name="default"/>
<server name="default-server">
<http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/>
<https-listener name="https" socket-binding="https" ssl-context="applicationSSC" enable-http2="true"/>
<host name="default-host" alias="localhost">
<location name="/" handler="welcome-content"/>
<http-invoker http-authentication-factory="application-http-authentication"/>
<!-- patrick -->
<filter-ref name="server-header"/>
<filter-ref name="x-powered-by-header"/>
<filter-ref name="Access-Control-Allow-Origin"/>
<filter-ref name="Access-Control-Allow-Methods"/>
<filter-ref name="Access-Control-Allow-Headers"/>
<filter-ref name="Access-Control-Allow-Credentials"/>
<filter-ref name="Access-Control-Max-Age"/>
</host>
</server>
<servlet-container name="default">
<jsp-config/>
<websockets/>
</servlet-container>
<handlers>
<file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
</handlers>
<application-security-domains>
<application-security-domain name="other" security-domain="ApplicationDomain"/>
<!-- patrick -->
<application-security-domain name="fotoDocumentationSecurity" http-authentication-factory="fotoDocumentation-http-authentication"/>
</application-security-domains>
<!-- patrick -->
<filters>
<response-header name="server-header" header-name="Server" header-value="WildFly/10"/>
<response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Undertow/1"/>
<response-header name="Access-Control-Allow-Origin" header-name="Access-Control-Allow-Origin" header-value="http://localhost:1234"/>
<response-header name="Access-Control-Allow-Methods" header-name="Access-Control-Allow-Methods" header-value="GET, POST, OPTIONS, PUT, DELETE"/>
<response-header name="Access-Control-Allow-Headers" header-name="Access-Control-Allow-Headers" header-value="accept, authorization, content-type, x-requested-with, xsrf-token"/>
<response-header name="Access-Control-Expose-Headers" header-name="Access-Control-Expose-Headers" header-value="xsrf-token"/>
<response-header name="Access-Control-Allow-Credentials" header-name="Access-Control-Allow-Credentials" header-value="true"/>
<response-header name="Access-Control-Max-Age" header-name="Access-Control-Max-Age" header-value="1"/>
</filters>
</subsystem>
<subsystem xmlns="urn:jboss:domain:webservices:2.0" statistics-enabled="${wildfly.webservices.statistics-enabled:${wildfly.statistics-enabled:false}}">
<wsdl-host>${jboss.bind.address:127.0.0.1}</wsdl-host>
<endpoint-config name="Standard-Endpoint-Config"/>
<endpoint-config name="Recording-Endpoint-Config">
<pre-handler-chain name="recording-handlers" protocol-bindings="##SOAP11_HTTP ##SOAP11_HTTP_MTOM ##SOAP12_HTTP ##SOAP12_HTTP_MTOM">
<handler name="RecordingHandler" class="org.jboss.ws.common.invocation.RecordingServerHandler"/>
</pre-handler-chain>
</endpoint-config>
<client-config name="Standard-Client-Config"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:weld:5.0"/>
</profile>
<interfaces>
<interface name="management">
<inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
</interface>
<interface name="public">
<inet-address value="${jboss.bind.address:127.0.0.1}"/>
</interface>
</interfaces>
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
<socket-binding name="ajp" port="${jboss.ajp.port:8009}"/>
<socket-binding name="http" port="${jboss.http.port:8080}"/>
<socket-binding name="https" port="${jboss.https.port:8443}"/>
<socket-binding name="management-http" interface="management" port="${jboss.management.http.port:9990}"/>
<socket-binding name="management-https" interface="management" port="${jboss.management.https.port:9993}"/>
<socket-binding name="txn-recovery-environment" port="4712"/>
<socket-binding name="txn-status-manager" port="4713"/>
<outbound-socket-binding name="mail-smtp">
<remote-destination host="smtp-server" port="26"/>
</outbound-socket-binding>
</socket-binding-group>
</server>

View File

@@ -0,0 +1,3 @@
#!/bin/bash
export JAVA_OPTS="$JAVA_OPTS -server -Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true -javaagent:/srv/jacocoagent.jar=destfile=/srv/target/jacoco-it.exec,includes=marketing/heyday/hartmann/fotodocumentation/*,output=file "
exec `dirname $0`/standalone.sh $@

View File

@@ -0,0 +1,177 @@
#!/usr/bin/env bash
# Use this script to test if a given TCP host/port are available
cmdname=$(basename $0)
echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi }
usage()
{
cat << USAGE >&2
Usage:
$cmdname host:port [-s] [-t timeout] [-- command args]
-h HOST | --host=HOST Host or IP under test
-p PORT | --port=PORT TCP port under test
Alternatively, you specify the host and port as host:port
-s | --strict Only execute subcommand if the test succeeds
-q | --quiet Don't output any status messages
-t TIMEOUT | --timeout=TIMEOUT
Timeout in seconds, zero for no timeout
-- COMMAND ARGS Execute command with args after the test finishes
USAGE
exit 1
}
wait_for()
{
if [[ $TIMEOUT -gt 0 ]]; then
echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT"
else
echoerr "$cmdname: waiting for $HOST:$PORT without a timeout"
fi
start_ts=$(date +%s)
while :
do
if [[ $ISBUSY -eq 1 ]]; then
nc -z $HOST $PORT
result=$?
else
(echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1
result=$?
fi
if [[ $result -eq 0 ]]; then
end_ts=$(date +%s)
echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds"
break
fi
sleep 1
done
return $result
}
wait_for_wrapper()
{
# In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
if [[ $QUIET -eq 1 ]]; then
timeout $BUSYTIMEFLAG $TIMEOUT $0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT &
else
timeout $BUSYTIMEFLAG $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT &
fi
PID=$!
trap "kill -INT -$PID" INT
wait $PID
RESULT=$?
if [[ $RESULT -ne 0 ]]; then
echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT"
fi
return $RESULT
}
# process arguments
while [[ $# -gt 0 ]]
do
case "$1" in
*:* )
hostport=(${1//:/ })
HOST=${hostport[0]}
PORT=${hostport[1]}
shift 1
;;
--child)
CHILD=1
shift 1
;;
-q | --quiet)
QUIET=1
shift 1
;;
-s | --strict)
STRICT=1
shift 1
;;
-h)
HOST="$2"
if [[ $HOST == "" ]]; then break; fi
shift 2
;;
--host=*)
HOST="${1#*=}"
shift 1
;;
-p)
PORT="$2"
if [[ $PORT == "" ]]; then break; fi
shift 2
;;
--port=*)
PORT="${1#*=}"
shift 1
;;
-t)
TIMEOUT="$2"
if [[ $TIMEOUT == "" ]]; then break; fi
shift 2
;;
--timeout=*)
TIMEOUT="${1#*=}"
shift 1
;;
--)
shift
CLI=("$@")
break
;;
--help)
usage
;;
*)
echoerr "Unknown argument: $1"
usage
;;
esac
done
if [[ "$HOST" == "" || "$PORT" == "" ]]; then
echoerr "Error: you need to provide a host and port to test."
usage
fi
TIMEOUT=${TIMEOUT:-15}
STRICT=${STRICT:-0}
CHILD=${CHILD:-0}
QUIET=${QUIET:-0}
# check to see if timeout is from busybox?
# check to see if timeout is from busybox?
TIMEOUT_PATH=$(realpath $(which timeout))
if [[ $TIMEOUT_PATH =~ "busybox" ]]; then
ISBUSY=1
BUSYTIMEFLAG="-t"
else
ISBUSY=0
BUSYTIMEFLAG=""
fi
if [[ $CHILD -gt 0 ]]; then
wait_for
RESULT=$?
exit $RESULT
else
if [[ $TIMEOUT -gt 0 ]]; then
wait_for_wrapper
RESULT=$?
else
wait_for
RESULT=$?
fi
fi
if [[ $CLI != "" ]]; then
if [[ $RESULT -ne 0 && $STRICT -eq 1 ]]; then
echoerr "$cmdname: strict mode, refusing to execute subprocess"
exit $RESULT
fi
exec "${CLI[@]}"
else
exit $RESULT
fi

View File

@@ -0,0 +1,23 @@
package marketing.heyday.hartmann.fotodocumentation.rest;
import org.junit.platform.suite.api.SelectPackages;
import org.junit.platform.suite.api.Suite;
import org.junit.platform.suite.api.SuiteDisplayName;
/**
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 22 Nov 2024
*/
@Suite
@SuiteDisplayName("Rest Resource Suite")
@SelectPackages("marketing.heyday.hartmann.fotodocumentation.rest")
public class AAAResourceTestSuite {
}

View File

@@ -0,0 +1,95 @@
package marketing.heyday.hartmann.fotodocumentation.rest;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.*;
import java.util.Base64;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import javax.json.Json;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.fluent.Executor;
import org.apache.http.client.fluent.Request;
import org.apache.http.impl.client.BasicCookieStore;
/**
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 13 Nov 2024
*/
public abstract class AbstractRestTest extends AbstractTest {
private static final Log LOG = LogFactory.getLog(AbstractRestTest.class);
public static final String TEXT_PLAIN = "text/plain";
public HttpResponse executeRequest(Request request) throws IOException {
var executor = Executor.newInstance();
return executor.use(new BasicCookieStore()).execute(request).returnResponse();
}
protected String getAuthorization() {
return getAuthorization(username, password);
}
protected String getAuthorization(String user, String pass) {
String auth = user + ":" + pass;
String encoded = Base64.getEncoder().encodeToString(auth.getBytes());
String authorization = "Basic " + encoded;
return authorization;
}
protected String getBearerToken(String authorization) {
try {
String path = deploymentURL + "api/login";
Request request = Request.Get(path).addHeader("Accept", "application/json; charset=utf-8")
.addHeader("Authorization", authorization);
HttpResponse httpResponse = executeRequest(request);
int code = httpResponse.getStatusLine().getStatusCode();
assertEquals(200, code);
String bearerStr = getResponseText(httpResponse);
try (var reader = Json.createReader(new StringReader(bearerStr));) {
return reader.readObject().getString("accessToken");
}
} catch (IOException e) {
LOG.error("Failed to get bearer token " + e.getMessage(), e);
return "";
}
}
protected byte[] getResponse(HttpResponse httpResponse) throws IOException {
try (var output = new ByteArrayOutputStream(); var input = httpResponse.getEntity().getContent()) {
input.transferTo(output);
output.flush();
return output.toByteArray();
}
}
protected String getResponseText(HttpResponse httpResponse) throws IOException {
String text;
try (BufferedReader input = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()))) {
text = input.lines().collect(Collectors.joining("\n"));
}
return text;
}
protected String getResponseText(HttpResponse httpResponse, Supplier<String> supplier) throws IOException {
String text = getResponseText(httpResponse);
writeJsonFile(text, supplier.get());
return text;
}
protected String getResponseText(HttpResponse httpResponse, String name) throws IOException {
String className = this.getClass().getName();
return getResponseText(httpResponse, () -> className + "-" + name + ".json");
}
}

View File

@@ -0,0 +1,189 @@
package marketing.heyday.hartmann.fotodocumentation.rest;
import java.io.*;
import java.nio.charset.Charset;
import java.sql.*;
import java.util.Date;
import java.util.Properties;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.jackson.map.ObjectMapper;
import org.dbunit.database.DatabaseConfig;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ReplacementDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.dbunit.ext.postgresql.PostgresqlDataTypeFactory;
import org.dbunit.operation.DatabaseOperation;
import org.json.JSONException;
import org.skyscreamer.jsonassert.JSONAssert;
/**
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 13 Nov 2024
*/
public class AbstractTest {
private static final Log LOG = LogFactory.getLog(AbstractTest.class);
public String deploymentURL = "http://localhost:8180/";
public String username = "admin";
public String password = "test";
private static Properties props = null;
public static Connection getConnection() throws SQLException {
if (props == null) {
try (FileReader reader = new FileReader(new File("src/test/resources/junit.properties"))) {
Class.forName("org.postgresql.Driver");
props = new Properties();
props.load(reader);
} catch (Exception e) {
throw new SQLException(e.getMessage());
}
}
return DriverManager.getConnection(props.getProperty("connection"), props.getProperty("username"), props.getProperty("password"));
}
public static void initDB() {
initDB("dataset.xml");
}
public static void initDB(String xmlFile) {
try (Connection jdbcConnection = getConnection();) {
initDb(jdbcConnection, xmlFile);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
private static void initDb(Connection jdbcConnection, String xmlFile) {
// using manual DBUnit since the persistence plugin has performance problems.
// https://community.jboss.org/thread/235511
// https://issues.jboss.org/browse/ARQ-1440
try {
System.out.println("start dbunit " + new Date(System.currentTimeMillis()));
IDatabaseConnection conn = new org.dbunit.database.DatabaseConnection(jdbcConnection);
DatabaseConfig config = conn.getConfig();
config.setProperty("http://www.dbunit.org/features/datatypeWarning", Boolean.FALSE);
config.setProperty(DatabaseConfig.FEATURE_ALLOW_EMPTY_FIELDS, Boolean.TRUE);
config.setProperty(DatabaseConfig.FEATURE_BATCHED_STATEMENTS, Boolean.TRUE);
config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new PostgresqlDataTypeFactory());
// initialize your dataset here
IDataSet dataSet = new FlatXmlDataSetBuilder().build(new File("src/test/resources/datasets/" + xmlFile));
ReplacementDataSet repDataSet = new ReplacementDataSet(dataSet);
repDataSet.addReplacementObject("EXP_DATE", DateUtils.addDays(new Date(), 1));
repDataSet.addReplacementObject("NULL_DATE", null);
repDataSet.addReplacementObject("NULL_NUMBER", null);
repDataSet.addReplacementObject("NULL_STRING", null);
try {
DatabaseOperation.CLEAN_INSERT.execute(conn, repDataSet);
} finally {
conn.close();
}
} catch (java.sql.BatchUpdateException e) {
e.printStackTrace();
e.getNextException().printStackTrace();
throw new RuntimeException(e.getMessage(), e);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage(), e);
}
System.out.println("End dbunit " + new Date(System.currentTimeMillis()));
}
public String fileToString(final String fileName) {
try (FileInputStream input = new FileInputStream("src/test/resources/" + fileName)) {
return IOUtils.toString(input, Charset.forName("utf-8"));
} catch (IOException e) {
return "";
}
}
public static void writeJsonFile(final String content, final String fileName) {
if (content.isEmpty()) {
return;
}
File file = new File("target/test/output/");
file.mkdirs();
try (FileOutputStream out = new FileOutputStream(new File(file, fileName))) {
ObjectMapper mapper = new ObjectMapper();
Object json = mapper.readValue(content, Object.class);
String formattedContent = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(json);
System.out.println(formattedContent);
IOUtils.write(formattedContent, out, Charset.forName("utf-8"));
} catch (Exception e) {
LOG.error("Error storing json file", e);
}
}
public static void writeFile(byte[] content, String fileName) {
File file = new File("target/test/output/");
file.mkdirs();
try (FileOutputStream out = new FileOutputStream(new File(file, fileName))) {
IOUtils.write(content, out);
} catch (Exception e) {
LOG.error("Error storing binary file", e);
}
}
public static byte[] readFile(String fileName) {
try (FileInputStream in = new FileInputStream("src/test/resources/" + fileName)) {
return IOUtils.toByteArray(in);
} catch (Exception e) {
throw new RuntimeException("Error reading file src/test/resources/" + fileName);
}
}
public void writeFile(InputStream content, String fileName) {
File file = new File("target/test/output/");
file.mkdirs();
try (FileOutputStream out = new FileOutputStream(new File(file, fileName))) {
IOUtils.copy(content, out);
} catch (Exception e) {
LOG.error("Error storing binary file", e);
}
}
public static int getCount(String sql) {
try (Connection conn = getConnection(); PreparedStatement statement = conn.prepareStatement(sql); ResultSet resultSet = statement.executeQuery();) {
if (resultSet.next()) {
return resultSet.getInt(1);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
LOG.error("no result found");
return 0;
}
protected void jsonAssert(String expected, String content) {
jsonAssert(expected, content, false);
}
protected void jsonAssert(String expected, String content, boolean strict) {
try {
JSONAssert.assertEquals(expected, content, strict);
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
/*
public static void main(String[] args) throws SQLException {
try (var connection = DriverManager.getConnection("jdbc:postgresql://localhost:5432/skillmatrix", "skillmatrix", "skillmatrix")) {
initDb(connection, "dataset.xml");
}
}*/
}

View File

@@ -0,0 +1,53 @@
package marketing.heyday.hartmann.fotodocumentation.rest;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.File;
import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.fluent.Request;
import org.apache.http.entity.ContentType;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
/**
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 14 Nov 2024
*/
@TestMethodOrder(OrderAnnotation.class)
public class CustomerPictureTest extends AbstractRestTest {
private static final Log LOG = LogFactory.getLog(CustomerPictureTest.class);
private static final String PATH = "api/customer-picture";
private static final String BASE_UPLOAD = "src/test/resources/upload/";
@BeforeAll
public static void init() {
initDB();
}
@Test
@Order(1)
public void doAddCustomerPicture() throws IOException {
LOG.info("doAddCustomerPicture");
String path = deploymentURL + PATH;
Request request = Request.Post(path).addHeader("Accept", "application/json; charset=utf-8")
.addHeader("Authorization", getAuthorization())
.bodyFile(new File(BASE_UPLOAD + "add.json"), ContentType.APPLICATION_JSON);
HttpResponse httpResponse = executeRequest(request);
int code = httpResponse.getStatusLine().getStatusCode();
assertEquals(200, code);
}
}

View File

@@ -0,0 +1,34 @@
package marketing.heyday.hartmann.fotodocumentation.rest;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.client.fluent.Request;
import org.junit.jupiter.api.Test;
/**
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 13 Nov 2024
*/
public class MonitoringResourceTest extends AbstractRestTest {
@Test
public void check() throws IOException {
String path = deploymentURL + "api/monitoring/check/hello";
Request request = Request.Get(path).addHeader("Accept", TEXT_PLAIN);
HttpResponse httpResponse = executeRequest(request);
int code = httpResponse.getStatusLine().getStatusCode();
assertEquals(200, code);
}
}

View File

@@ -0,0 +1,14 @@
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<x_right right_id="1" code="ADNUB" name="Admin Right" jpa_active="true" jpa_created="2024-10-24 10:09:30" jpa_updated="2024-10-24 10:09:30" jpa_version="0" />
<x_right right_id="2" code="USER" name="User Right" jpa_active="true" jpa_created="2024-10-24 10:09:52" jpa_updated="2024-10-24 10:09:52" jpa_version="0" />
<x_user user_id="1" username="admin" password="mMlJzJq4kMn9d0s1FcrKILkrWNYXlWSt5B0T+YpySn8=" salt="6cmWHbdbcIeg50WzW75RHb8grYgEY99JLJfHLLzjcR8=" title="Herr" firstname="Admin" lastname="Admin" email="p.verboom@heyday.marketing" jpa_active="true" jpa_created="2024-10-24 10:09:52" jpa_updated="2024-10-24 10:09:52" jpa_version="0" />
<x_user user_id="2" username="gf" password="YAEPFUIwtpXC+1Jv9PucgXLWisXmWe+zZsl+I3xQ/x8=" salt="zdALDFK+fe7U/3G9jSH0k2pBJFsUAe6PCVGRE56ckrc=" title="Herr" firstname="GF" lastname="gf" email="gf@heyday.marketing" jpa_active="true" jpa_created="2024-10-24 10:09:52" jpa_updated="2024-10-24 10:09:52" jpa_version="0" />
<user_to_right user_id_fk="1" right_id_fk="1" />
<user_to_right user_id_fk="2" right_id_fk="2" />
</dataset>

View File

@@ -0,0 +1,3 @@
connection=jdbc:postgresql://localhost:5430/fotodocumentation
username=fotodocumentation
password=fotodocumentation

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<param name="Threshold" value="DEBUG"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c] %m%n"/>
</layout>
</appender>
<!-- ================ -->
<!-- Limit categories -->
<!-- ================ -->
<!-- Limit the org.apache category to INFO as its DEBUG is verbose -->
<category name="org.apache">
<priority value="INFO"/>
</category>
<category name="com.bm">
<priority value="INFO"/>
</category>
<category name="com.bm.introspectors">
<priority value="ERROR"/>
</category>
<category name="org.hibernate.cfg.annotations">
<priority value="WARN"/>
</category>
<category name="org.hibernate.cfg">
<priority value="WARN"/>
</category>
<category name="org.hibernate.tool">
<priority value="WARN"/>
</category>
<category name="org.hibernate.validator">
<priority value="WARN"/>
</category>
<category name="org.hibernate">
<priority value="ERROR"/>
</category>
<category name="org.dbunit">
<priority value="DEBUG"/>
</category>
<category name="org.apache.http">
<priority value="INFO"/>
</category>
<category name="STDOUT">
<priority value="DEBUG"/>
</category>
<root>
<appender-ref ref="CONSOLE"/>
</root>
</log4j:configuration>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,70 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>marketing.heyday.hartmann.fotodocumentation</groupId>
<artifactId>hartmann-foto-documentation</artifactId>
<version>1.0.0</version>
<relativePath>../hartmann-foto-documentation/pom.xml</relativePath>
</parent>
<artifactId>hartmann-foto-documentation-web</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>hartmann-foto-documentation web</name>
<packaging>war</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<configuration>
<skip>true</skip>
<skipDeploy>true</skipDeploy>
</configuration>
</plugin>
<!--
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy_for_release</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/src/main/webapp</outputDirectory>
<resources>
<resource>
<directory>${basedir}/../../../-frontend/build/web/</directory>
</resource>
</resources>
</configuration>
</execution>
<execution>
<id>copy_for_general</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/src/main/webapp</outputDirectory>
<resources>
<resource>
<directory>${basedir}/../-frontend/build/web/</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
-->
</plugins>
</build>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>hartmann-foto-documentation-app</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1 @@
20d9c068b272d7a2718d0d8e3e04271e

View File

@@ -0,0 +1,24 @@
Manifest-Version: 1.0
Class-Path: commons-logging-1.1.1.jar cue-platform-storage-3.0.1-SN
APSHOT.jar commons-lang3-3.5.jar javaslang-2.0.2.jar javaslang-match-2.
0.2.jar commons-io-2.4.jar org.eclipse.jgit-4.2.0.201601211800-r.jar js
ch-0.1.53.jar JavaEWAH-0.7.9.jar slf4j-api-1.7.2.jar cue-platform-
app-3.0.1-SNAPSHOT.jar cue-platform-push-3.0.1-SNAPSHOT.jar pushy-
0.13.5.jar netty-codec-http2-4.1.25.Final.jar netty-codec-http-4.1.25.F
inal.jar netty-codec-4.1.25.Final.jar netty-transport-4.1.25.Final.jar
netty-buffer-4.1.25.Final.jar netty-common-4.1.25.Final.jar netty-resol
ver-4.1.25.Final.jar netty-handler-4.1.25.Final.jar netty-handler-proxy
-4.1.25.Final.jar netty-codec-socks-4.1.25.Final.jar netty-resolver-dns
-4.1.25.Final.jar netty-codec-dns-4.1.25.Final.jar fast-uuid-0.1.jar gs
on-2.2.4.jar primefaces-6.1.jar primefaces-extensions-6.1.1.jar compile
r-0.9.5.jar antlr4-4.5.jar antlr4-runtime-4.5.jar org.abego.treelayout.
core-1.0.1.jar antlr-runtime-3.5.2.jar ST4-4.0.8.jar json-schema-valida
tor-0.1.2.jar slf4j-ext-1.7.21.jar cal10n-api-0.8.1.jar commons-lang-2.
6.jar omnifaces-2.6.2.jar flyway-core-3.1.jar commons-fileupload-1.3.ja
r poi-4.1.0.jar commons-codec-1.12.jar commons-collections4-4.3.jar com
mons-math3-3.6.1.jar poi-ooxml-4.1.0.jar poi-ooxml-schemas-4.1.0.jar xm
lbeans-3.1.0.jar commons-compress-1.18.jar curvesapi-1.06.jar cue-
platform-module-detailing-3.0.1-SNAPSHOT.jar cue-platform-module-c
ontent-3.0.1-SNAPSHOT.jar cue-platform-module-poll-3.0.1-SNAPSHOT.
jar resources-codemirror-6.1.1.jar

View File

@@ -0,0 +1,3 @@
<Context allowCasualMultipartParsing="true">
<!-- no content required -->
</Context>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd"
version="4.0" bean-discovery-mode="all">
</beans>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.1">
<deployment>
<dependencies>
<module name="org.jboss.as.controller-client" />
<module name="org.wildfly.security.elytron"/>
<module name="org.jboss.dmr"/>
<module name="javaee.api" />
</dependencies>
</deployment>
</jboss-deployment-structure>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0"?>
<jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:s="urn:security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd
http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_2.xsd" version="3.2" impl-version="2.0">
</jboss:ejb-jar>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<security-domain flushOnSessionInvalidation="true">fotoDocumentationSecurity</security-domain>
<context-root>/</context-root>
</jboss-web>

View File

@@ -0,0 +1,5 @@
prettyPrint: true
servers:
- url: https://localhost/api
description: Production server
-

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<!-- <context-param> <param-name>resteasy.role.based.security</param-name> <param-value>true</param-value> </context-param> -->
<security-constraint>
<web-resource-collection>
<web-resource-name>Secure</web-resource-name>
<url-pattern>/api/login</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>PUT</http-method>
<http-method>DELETE</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>**</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>fotoDocumentationRealm</realm-name>
</login-config>
</web-app>

View File

@@ -0,0 +1,506 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>marketing.heyday.maven</groupId>
<artifactId>parentpom</artifactId>
<version>16</version>
</parent>
<groupId>marketing.heyday.hartmann.fotodocumentation</groupId>
<artifactId>hartmann-foto-documentation</artifactId>
<packaging>pom</packaging>
<version>1.0.0</version>
<name>hartmann-foto-documentation</name>
<scm>
<connection>scm:git:git@git.heyday.marketing:heyday-marketing-gmbh/hartmann-foto_documentation.git</connection>
<url>https://git.heyday.marketing/?p=heyday-marketing-gmbh/hartmann-foto_documentation.git</url>
<tag>HEAD</tag>
</scm>
<build>
<defaultGoal>install</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.5.0</version>
<executions>
<execution>
<id>enforce-maven</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireMavenVersion>
<version>3.0</version>
</requireMavenVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<configuration>
<skip>true</skip>
<skipDeploy>true</skipDeploy>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
<manifestEntries>
<Implementation-Build>${buildNumber}</Implementation-Build>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>21</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M1</version>
<configuration>
<argLine>${surefireArgLine}
--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/java.lang.reflect=ALL-UNNAMED
--add-opens java.base/java.util.concurrent=ALL-UNNAMED
--add-opens java.base/java.util=ALL-UNNAMED
</argLine>
<testFailureIgnore>true</testFailureIgnore>
<excludes>
<!-- exclude test helper classes -->
<exclude>**/test/helper/*.*</exclude>
<exclude>**/AllTest.*</exclude>
</excludes>
<forkCount>1</forkCount>
<includes>
<include>**/*Test.java</include>
<include>**/*IT.java</include>
</includes>
<properties>
<property>
<name>listener</name>
<value>org.sonar.java.jacoco.JUnitListener</value>
</property>
</properties>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<includes>
<include>marketing/heyday/hartmann/fotodocumentation/**/*</include>
</includes>
</configuration>
<executions>
<execution>
<id>test</id>
<phase>initialize</phase>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<!-- Prepares the property pointing to the JaCoCo runtime
agent which is passed as VM argument when Maven the Surefire
plugin is executed. -->
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<!-- Sets the name of the property containing the
settings for JaCoCo runtime agent. -->
<propertyName>surefireArgLine</propertyName>
</configuration>
</execution>
<!-- Ensures that the code coverage report for unit tests is
created after unit tests have been run. -->
<execution>
<id>post-unit-test</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<!-- Prepares the property pointing to the JaCoCo runtime
agent which is passed as VM argument when Maven the Failsafe
plugin is executed. -->
<execution>
<id>pre-integration-test</id>
<phase>pre-integration-test</phase>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
<configuration>
<dumpOnExit>true</dumpOnExit>
<!-- Sets the name of the property containing the
settings for JaCoCo runtime agent. -->
<propertyName>failsafeArgLine</propertyName>
</configuration>
</execution>
<!-- Ensures that the code coverage report for integration
tests after integration tests have been run. -->
<execution>
<id>post-integration-test</id>
<!-- must be after tomcat shutdown -->
<phase>verify</phase>
<goals>
<goal>report</goal>
<goal>report-aggregate</goal>
</goals>
<configuration>
<formats>
<format>XML</format>
<format>CSV</format>
</formats>
<dataFileIncludes>
<dataFileInclude>**/jacoco.exec</dataFileInclude>
<dataFileInclude>**/jacoco-it.exec</dataFileInclude>
</dataFileIncludes>
<outputDirectory>
${project.reporting.outputDirectory}/jacoco-aggregate</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${version.jacoco}</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
<configuration>
<doCheck>false</doCheck>
<doUpdate>false</doUpdate>
<shortRevisionLength>7</shortRevisionLength>
<revisionOnScmFailure>true</revisionOnScmFailure>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<properties>
<maven.javadoc.skip>true</maven.javadoc.skip>
<!-- Sonar -->
<sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<!--<sonar.language>java</sonar.language>-->
<sonar.coverage.jacoco.xmlReportPaths>
${project.basedir}/target/site/jacoco-aggregate/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
<jacoco-maven-plugin.version>0.8.12</jacoco-maven-plugin.version>
<version.jacoco>0.8.12</version.jacoco>
<version.arquillian>1.1.11.Final</version.arquillian>
<version.org.jboss.ejb3.ext-api>2.2.0.Final</version.org.jboss.ejb3.ext-api>
<version.org.jboss.resteasy>6.2.5.Final</version.org.jboss.resteasy>
<subethamail.version>1.2</subethamail.version>
<version.commons-io>2.7</version.commons-io>
<version.commons-lang>2.6</version.commons-lang>
<version.commons-lang3>3.5</version.commons-lang3>
<version.commons-logging>1.2</version.commons-logging>
<version.commons-fileupload>1.3</version.commons-fileupload>
<version.javaslang>2.0.2</version.javaslang>
<version.omnifaces>4.3</version.omnifaces>
<version.primefaces>13.0.3</version.primefaces>
<version.primefaces.ext>13.0.3</version.primefaces.ext>
<version.jsonwebtoken>0.12.5</version.jsonwebtoken>
<swagger-version>2.2.19</swagger-version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.wildfly.bom</groupId>
<artifactId>wildfly</artifactId>
<version>26.1.3.Final</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<version>10.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
<version>6.2.13.Final</version>
<scope>provided</scope>
</dependency>
<!-- json -->
<dependency>
<groupId>org.eclipse.parsson</groupId>
<artifactId>parsson</artifactId>
<version>1.1.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.json</groupId>
<artifactId>jakarta.json-api</artifactId>
<version>2.1.2</version>
<scope>provided</scope>
</dependency>
<!-- Apache POI -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.1.0</version>
<exclusions>
<exclusion>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
</exclusion>
<exclusion>
<groupId>stax</groupId>
<artifactId>stax-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- swagger -->
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-jaxrs2-jakarta</artifactId>
<scope>compile</scope>
<version>${swagger-version}</version>
<exclusions>
<exclusion>
<groupId>java.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
</exclusion>
<!-- <exclusion>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
</exclusion> -->
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-dataformat</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-jaxrs2-servlet-initializer-jakarta</artifactId>
<version>${swagger-version}</version>
</dependency>
<!-- end swagger -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.15.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.15.0</version>
</dependency>
<!-- Resteasy -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-core</artifactId>
<version>${version.org.jboss.resteasy}</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-core-spi</artifactId>
<version>${version.org.jboss.resteasy}</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-multipart-provider</artifactId>
<version>${version.org.jboss.resteasy}</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson2-provider</artifactId>
<version>${version.org.jboss.resteasy}</version>
<scope>provided</scope>
</dependency>
<!-- JWT Library -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>${version.jsonwebtoken}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>${version.jsonwebtoken}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>${version.jsonwebtoken}</version>
<scope>runtime</scope>
</dependency>
<!-- JWT Library -->
<!-- Test dependencies -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4-1201-jdbc41</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.14.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite-engine</artifactId>
<version>1.9.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite-api</artifactId>
<version>1.9.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.9.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-commons</artifactId>
<version>1.9.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jacoco</groupId>
<artifactId>org.jacoco.core</artifactId>
<version>${version.jacoco}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

27
pom.xml Normal file
View File

@@ -0,0 +1,27 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>marketing.heyday.hartmann.fotodocumentation</groupId>
<artifactId>hartman-foto-documentation</artifactId>
<version>1.0.0</version>
<relativePath>hartmann-foto-documentation/pom.xml</relativePath>
</parent>
<groupId>marketing.heyday.hartmann.fotodocumentation</groupId>
<artifactId>hartmann-foto-documentation-root</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>hartman-foto-documentation-root</name>
<scm>
<connection>scm:git:git@git.heyday.marketing:heyday-marketing-gmbh/hartmann-foto_documentation.git</connection>
<url>https://git.heyday.marketing/?p=heyday-marketing-gmbh/hartmann-foto_documentation.git</url>
<tag>HEAD</tag>
</scm>
<modules>
<module>hartmann-foto-documentation-app</module>
<module>hartmann-foto-documentation-web</module>
<module>hartmann-foto-documentation-docker</module>
<!--<module>hartmann-foto-documentation-frontend</module>-->
</modules>
</project>