Compare commits
11 Commits
1673f1680b
...
d5c2a5f813
Author | SHA1 | Date | |
---|---|---|---|
d5c2a5f813 | |||
85ac72648f | |||
1281415c48 | |||
![]() |
a4521853c3 | ||
![]() |
abe2dd9480 | ||
![]() |
b7af0b4575 | ||
![]() |
5412eadf2e | ||
![]() |
d5e2e0f5b3 | ||
28ab6c49d4 | |||
260a3abd13 | |||
895e8c2b37 |
@ -30,15 +30,6 @@
|
|||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="test" value="true"/>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
<attribute name="ignore_optional_problems" value="true"/>
|
|
||||||
<attribute name="m2e-apt" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="src" path="target/generated-sources/annotations">
|
<classpathentry kind="src" path="target/generated-sources/annotations">
|
||||||
<attributes>
|
<attributes>
|
||||||
<attribute name="optional" value="true"/>
|
<attribute name="optional" value="true"/>
|
||||||
|
28
.github/dependabot.yml
vendored
28
.github/dependabot.yml
vendored
@ -1,12 +1,24 @@
|
|||||||
# To get started with Dependabot version updates, you'll need to specify which
|
---
|
||||||
# package ecosystems to update and where the package manifests are located.
|
|
||||||
# Please see the documentation for all configuration options:
|
|
||||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
|
||||||
|
|
||||||
version: 2
|
version: 2
|
||||||
updates:
|
updates:
|
||||||
- package-ecosystem: "" # See documentation for possible values
|
- package-ecosystem: "github-actions"
|
||||||
directory: "/" # Location of package manifests
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "weekly"
|
interval: "daily"
|
||||||
|
time: "05:00"
|
||||||
|
timezone: "Europe/Paris"
|
||||||
|
commit-message:
|
||||||
|
prefix: "[DEV-OPS] (dependabot) "
|
||||||
|
assignees:
|
||||||
|
- HeeroYui
|
||||||
|
|
||||||
|
- package-ecosystem: "maven"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
time: "06:00"
|
||||||
|
timezone: "Europe/Paris"
|
||||||
|
commit-message:
|
||||||
|
prefix: "[DEV-OPS] (dependabot) "
|
||||||
|
assignees:
|
||||||
|
- HeeroYui
|
||||||
|
4
.github/workflows/check-title.yml
vendored
4
.github/workflows/check-title.yml
vendored
@ -9,6 +9,8 @@ on:
|
|||||||
- synchronize
|
- synchronize
|
||||||
- ready_for_review
|
- ready_for_review
|
||||||
- reopened
|
- reopened
|
||||||
|
- labeled
|
||||||
|
- unlabeled
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-title:
|
check-title:
|
||||||
@ -17,7 +19,7 @@ jobs:
|
|||||||
- name: "Check title"
|
- name: "Check title"
|
||||||
uses: Slashgear/action-check-pr-title@v4.3.0
|
uses: Slashgear/action-check-pr-title@v4.3.0
|
||||||
with:
|
with:
|
||||||
regexp: "\\[(API,)?(API|DEV-OPS|DOC|FEAT|FIX|FIX\\-CI|STYLE)\\]( \\([A-Za-z0-9.\\-]+\\))? [A-Za-z0-9 ,.'\\-!]+$"
|
regexp: "\\[(API,)?(API|DEV-OPS|DOC|FEAT|FIX|FIX\\-CI|STYLE)\\]( \\([A-Za-z0-9.\\-/_]+\\))? [A-Za-z0-9: ,.'\\-!/_]+$"
|
||||||
helpMessage: |
|
helpMessage: |
|
||||||
Title of the PR MUST respect format: "[{TYPE}] clear description without typos in english" with {TYPE}:
|
Title of the PR MUST respect format: "[{TYPE}] clear description without typos in english" with {TYPE}:
|
||||||
* [API] Change API that permit to access on the application (un-compatibility only). This one can specifically added with [API,{TYPE}]
|
* [API] Change API that permit to access on the application (un-compatibility only). This one can specifically added with [API,{TYPE}]
|
||||||
|
59
pom.xml
59
pom.xml
@ -4,16 +4,6 @@
|
|||||||
<groupId>kangaroo-and-rabbit</groupId>
|
<groupId>kangaroo-and-rabbit</groupId>
|
||||||
<artifactId>archidata</artifactId>
|
<artifactId>archidata</artifactId>
|
||||||
<version>0.24.1-SNAPSHOT</version>
|
<version>0.24.1-SNAPSHOT</version>
|
||||||
<properties>
|
|
||||||
<java.version>21</java.version>
|
|
||||||
<maven.compiler.version>3.1</maven.compiler.version>
|
|
||||||
<maven.compiler.source>21</maven.compiler.source>
|
|
||||||
<maven.compiler.target>21</maven.compiler.target>
|
|
||||||
<maven.dependency.version>3.1.1</maven.dependency.version>
|
|
||||||
<jersey.version>3.1.5</jersey.version>
|
|
||||||
<jaxb.version>2.3.1</jaxb.version>
|
|
||||||
<istack.version>4.1.1</istack.version>
|
|
||||||
</properties>
|
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
<id>gitea</id>
|
<id>gitea</id>
|
||||||
@ -35,7 +25,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jersey</groupId>
|
<groupId>org.glassfish.jersey</groupId>
|
||||||
<artifactId>jersey-bom</artifactId>
|
<artifactId>jersey-bom</artifactId>
|
||||||
<version>${jersey.version}</version>
|
<version>3.1.10</version>
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
@ -58,7 +48,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio-webp</artifactId>
|
<artifactId>imageio-webp</artifactId>
|
||||||
<version>3.11.0</version>
|
<version>3.12.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- Decode JPEG image -->
|
<!-- Decode JPEG image -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -95,10 +85,19 @@
|
|||||||
<groupId>org.glassfish.jersey.containers</groupId>
|
<groupId>org.glassfish.jersey.containers</groupId>
|
||||||
<artifactId>jersey-container-grizzly2-http</artifactId>
|
<artifactId>jersey-container-grizzly2-http</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.glassfish.jersey.ext</groupId>
|
||||||
|
<artifactId>jersey-bean-validation</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.xml.bind</groupId>
|
<groupId>javax.xml.bind</groupId>
|
||||||
<artifactId>jaxb-api</artifactId>
|
<artifactId>jaxb-api</artifactId>
|
||||||
<version>${jaxb.version}</version>
|
<version>2.4.0-b180830.0359</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.sun.xml.bind</groupId>
|
||||||
|
<artifactId>jaxb-impl</artifactId>
|
||||||
|
<version>4.0.0-M4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jaxb</groupId>
|
<groupId>org.glassfish.jaxb</groupId>
|
||||||
@ -110,15 +109,10 @@
|
|||||||
<artifactId>jakarta.ws.rs-api</artifactId>
|
<artifactId>jakarta.ws.rs-api</artifactId>
|
||||||
<version>4.0.0</version>
|
<version>4.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.sun.xml.bind</groupId>
|
|
||||||
<artifactId>jaxb-impl</artifactId>
|
|
||||||
<version>${jaxb.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.sun.istack</groupId>
|
<groupId>com.sun.istack</groupId>
|
||||||
<artifactId>istack-commons-runtime</artifactId>
|
<artifactId>istack-commons-runtime</artifactId>
|
||||||
<version>${istack.version}</version>
|
<version>4.1.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- continu to be needed ??? -->
|
<!-- continu to be needed ??? -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -168,7 +162,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.nimbusds</groupId>
|
<groupId>com.nimbusds</groupId>
|
||||||
<artifactId>nimbus-jose-jwt</artifactId>
|
<artifactId>nimbus-jose-jwt</artifactId>
|
||||||
<version>9.41.1</version>
|
<version>10.0.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>jakarta.persistence</groupId>
|
<groupId>jakarta.persistence</groupId>
|
||||||
@ -198,13 +192,13 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mongodb</groupId>
|
<groupId>org.mongodb</groupId>
|
||||||
<artifactId>mongodb-driver-sync</artifactId>
|
<artifactId>mongodb-driver-sync</artifactId>
|
||||||
<version>4.3.0</version>
|
<version>5.1.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- Bean Validation (JSR 303 / 380) -->
|
<!-- Bean Validation (JSR 303 / 380) -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hibernate.validator</groupId>
|
<groupId>org.hibernate.validator</groupId>
|
||||||
<artifactId>hibernate-validator</artifactId>
|
<artifactId>hibernate-validator</artifactId>
|
||||||
<version>7.0.0.Final</version>
|
<version>8.0.2.Final</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.validation</groupId>
|
<groupId>javax.validation</groupId>
|
||||||
@ -236,7 +230,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||||
<version>3.5.0</version>
|
<version>3.6.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
@ -256,18 +250,17 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>${maven.compiler.version}</version>
|
<version>3.14.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>${maven.compiler.source}</source>
|
<source>21</source>
|
||||||
<target>${maven.compiler.target}</target>
|
<target>21</target>
|
||||||
<!--<encoding>${project.build.sourceEncoding}</encoding>-->
|
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<!-- Create the source bundle -->
|
<!-- Create the source bundle -->
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-source-plugin</artifactId>
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
<version>3.3.0</version>
|
<version>3.3.1</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>attach-sources</id>
|
<id>attach-sources</id>
|
||||||
@ -295,7 +288,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
<version>3.0.0-M5</version>
|
<version>3.2.5</version>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
@ -314,7 +307,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
<version>3.2.0</version>
|
<version>3.3.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<show>private</show>
|
<show>private</show>
|
||||||
<nohelp>true</nohelp>
|
<nohelp>true</nohelp>
|
||||||
@ -324,7 +317,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||||
<version>3.3.1</version>
|
<version>3.6.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<configLocation>CheckStyle.xml</configLocation>
|
<configLocation>CheckStyle.xml</configLocation>
|
||||||
<consoleOutput>true</consoleOutput>
|
<consoleOutput>true</consoleOutput>
|
||||||
@ -336,7 +329,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>net.revelc.code.formatter</groupId>
|
<groupId>net.revelc.code.formatter</groupId>
|
||||||
<artifactId>formatter-maven-plugin</artifactId>
|
<artifactId>formatter-maven-plugin</artifactId>
|
||||||
<version>2.23.0</version>
|
<version>2.24.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<encoding>UTF-8</encoding>
|
<encoding>UTF-8</encoding>
|
||||||
<lineEnding>LF</lineEnding>
|
<lineEnding>LF</lineEnding>
|
||||||
@ -385,7 +378,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
<version>3.2.0</version>
|
<version>3.3.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<show>public</show>
|
<show>public</show>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
@ -5,8 +5,18 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Target({ ElementType.TYPE, ElementType.FIELD })
|
import jakarta.validation.Constraint;
|
||||||
|
import jakarta.validation.Payload;
|
||||||
|
|
||||||
|
@Constraint(validatedBy = CheckForeignKeyValidator.class)
|
||||||
|
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface CheckForeignKey {
|
public @interface CheckForeignKey {
|
||||||
Class<?> target();
|
Class<?> target();
|
||||||
|
|
||||||
|
String message() default "Foreign-key does not exist in the DB";
|
||||||
|
|
||||||
|
Class<?>[] groups() default {};
|
||||||
|
|
||||||
|
Class<? extends Payload>[] payload() default {};
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
package org.kar.archidata.annotation.checker;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.kar.archidata.dataAccess.DataAccess;
|
||||||
|
|
||||||
|
import jakarta.validation.ConstraintValidator;
|
||||||
|
import jakarta.validation.ConstraintValidatorContext;
|
||||||
|
|
||||||
|
public class CheckForeignKeyValidator implements ConstraintValidator<CheckForeignKey, Object> {
|
||||||
|
Class<?> target = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(final CheckForeignKey annotation) {
|
||||||
|
this.target = annotation.target();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(final Object value, final ConstraintValidatorContext context) {
|
||||||
|
if (value != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (value instanceof final Collection<?> tmpCollection) {
|
||||||
|
final Object[] elements = tmpCollection.toArray();
|
||||||
|
for (final Object element : elements) {
|
||||||
|
if (element == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final long count = DataAccess.count(this.target, element);
|
||||||
|
if (count != 1) {
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (final Exception e) {
|
||||||
|
// TODO ...
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -5,8 +5,16 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Target(ElementType.FIELD)
|
import jakarta.validation.Constraint;
|
||||||
|
import jakarta.validation.Payload;
|
||||||
|
|
||||||
|
@Constraint(validatedBy = CollectionItemNotNullValidator.class)
|
||||||
|
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface CollectionItemNotNull {
|
public @interface CollectionItemNotNull {
|
||||||
|
String message() default "Collection can not contain NULL item";
|
||||||
|
|
||||||
|
Class<?>[] groups() default {};
|
||||||
|
|
||||||
|
Class<? extends Payload>[] payload() default {};
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
package org.kar.archidata.annotation.checker;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import jakarta.validation.ConstraintValidator;
|
||||||
|
import jakarta.validation.ConstraintValidatorContext;
|
||||||
|
|
||||||
|
public class CollectionItemNotNullValidator implements ConstraintValidator<CollectionItemNotNull, Object> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(final CollectionItemNotNull annotation) {
|
||||||
|
// nothing to do...
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(final Object value, final ConstraintValidatorContext context) {
|
||||||
|
if (value == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (value instanceof final Collection<?> tmpCollection) {
|
||||||
|
final Object[] elements = tmpCollection.toArray();
|
||||||
|
for (final Object element : elements) {
|
||||||
|
if (element == null) {
|
||||||
|
return false;
|
||||||
|
//throw new InputException(baseName + fieldName + '[' + iii + ']', "Collection can not contain NULL item");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -5,8 +5,17 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Target(ElementType.FIELD)
|
import jakarta.validation.Constraint;
|
||||||
|
import jakarta.validation.Payload;
|
||||||
|
|
||||||
|
@Constraint(validatedBy = CollectionItemUniqueValidator.class)
|
||||||
|
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface CollectionItemUnique {
|
public @interface CollectionItemUnique {
|
||||||
|
|
||||||
|
String message() default "Cannot insert multiple times the same elements";
|
||||||
|
|
||||||
|
Class<?>[] groups() default {};
|
||||||
|
|
||||||
|
Class<? extends Payload>[] payload() default {};
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package org.kar.archidata.annotation.checker;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import jakarta.validation.ConstraintValidator;
|
||||||
|
import jakarta.validation.ConstraintValidatorContext;
|
||||||
|
|
||||||
|
public class CollectionItemUniqueValidator implements ConstraintValidator<CollectionItemUnique, Object> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(final CollectionItemUnique annotation) {
|
||||||
|
// nothing to do...
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(final Object value, final ConstraintValidatorContext context) {
|
||||||
|
if (value == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (value instanceof final Collection<?> tmpCollection) {
|
||||||
|
final Set<Object> uniqueValues = new HashSet<>(tmpCollection);
|
||||||
|
if (uniqueValues.size() != tmpCollection.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -5,8 +5,17 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Target(ElementType.FIELD)
|
import jakarta.validation.Constraint;
|
||||||
|
import jakarta.validation.Payload;
|
||||||
|
|
||||||
|
@Constraint(validatedBy = CollectionNotEmptyValidator.class)
|
||||||
|
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface CollectionNotEmpty {
|
public @interface CollectionNotEmpty {
|
||||||
|
|
||||||
|
String message() default "Collection can not be empty";
|
||||||
|
|
||||||
|
Class<?>[] groups() default {};
|
||||||
|
|
||||||
|
Class<? extends Payload>[] payload() default {};
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
package org.kar.archidata.annotation.checker;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import jakarta.validation.ConstraintValidator;
|
||||||
|
import jakarta.validation.ConstraintValidatorContext;
|
||||||
|
|
||||||
|
public class CollectionNotEmptyValidator implements ConstraintValidator<CollectionNotEmpty, Object> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(final CollectionNotEmpty annotation) {
|
||||||
|
// nothing to do...
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(final Object value, final ConstraintValidatorContext context) {
|
||||||
|
if (value == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (value instanceof final Collection<?> tmpCollection) {
|
||||||
|
if (tmpCollection.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
20
src/org/kar/archidata/annotation/checker/ReadOnlyField.java
Normal file
20
src/org/kar/archidata/annotation/checker/ReadOnlyField.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package org.kar.archidata.annotation.checker;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import jakarta.validation.Constraint;
|
||||||
|
import jakarta.validation.Payload;
|
||||||
|
|
||||||
|
@Constraint(validatedBy = ReadOnlyFieldValidator.class)
|
||||||
|
@Target({ ElementType.METHOD, ElementType.FIELD })
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface ReadOnlyField {
|
||||||
|
String message() default "Field can not be set, it is a read-only field.";
|
||||||
|
|
||||||
|
Class<?>[] groups() default {};
|
||||||
|
|
||||||
|
Class<? extends Payload>[] payload() default {};
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package org.kar.archidata.annotation.checker;
|
||||||
|
|
||||||
|
import jakarta.validation.ConstraintValidator;
|
||||||
|
import jakarta.validation.ConstraintValidatorContext;
|
||||||
|
|
||||||
|
public class ReadOnlyFieldValidator implements ConstraintValidator<ReadOnlyField, Object> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(final ReadOnlyField annotation) {
|
||||||
|
// nothing to do...
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(final Object value, final ConstraintValidatorContext context) {
|
||||||
|
if (value != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,11 @@
|
|||||||
package org.kar.archidata.catcher;
|
package org.kar.archidata.catcher;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -20,7 +26,22 @@ public class ConstraintViolationExceptionCatcher implements ExceptionMapper<Cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
private RestErrorResponse build(final ConstraintViolationException exception) {
|
private RestErrorResponse build(final ConstraintViolationException exception) {
|
||||||
return new RestErrorResponse(Response.Status.BAD_REQUEST, "Constraint Violation", exception.getMessage());
|
final List<RestInputError> inputError = new ArrayList<>();
|
||||||
|
for (final var cv : exception.getConstraintViolations()) {
|
||||||
|
if (cv == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
inputError.add(new RestInputError(cv.getPropertyPath(), cv.getMessage()));
|
||||||
|
}
|
||||||
|
Collections.sort(inputError, Comparator.comparing(RestInputError::getFullPath));
|
||||||
|
String errorType = "Multiple error on input";
|
||||||
|
if (inputError.size() == 0) {
|
||||||
|
errorType = "Constraint Violation";
|
||||||
|
} else if (inputError.size() == 1) {
|
||||||
|
errorType = "Error on input='" + inputError.get(0).path + "'";
|
||||||
|
}
|
||||||
|
return new RestErrorResponse(Response.Status.BAD_REQUEST, Instant.now().toString(), errorType,
|
||||||
|
exception.getMessage(), inputError);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package org.kar.archidata.catcher;
|
package org.kar.archidata.catcher;
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
import org.kar.archidata.annotation.apiGenerator.ApiGenerationMode;
|
import org.kar.archidata.annotation.apiGenerator.ApiGenerationMode;
|
||||||
|
|
||||||
|
import jakarta.annotation.Nullable;
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import jakarta.ws.rs.core.Response;
|
import jakarta.ws.rs.core.Response;
|
||||||
@ -27,6 +29,19 @@ public class RestErrorResponse {
|
|||||||
@Column(length = 0)
|
@Column(length = 0)
|
||||||
final public String statusMessage;
|
final public String statusMessage;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
final public List<RestInputError> inputError;
|
||||||
|
|
||||||
|
public RestErrorResponse(final Response.Status status, final String time, final String error, final String message,
|
||||||
|
final List<RestInputError> inputError) {
|
||||||
|
this.time = time;
|
||||||
|
this.name = error;
|
||||||
|
this.message = message;
|
||||||
|
this.status = status.getStatusCode();
|
||||||
|
this.statusMessage = status.getReasonPhrase();
|
||||||
|
this.inputError = inputError;
|
||||||
|
}
|
||||||
|
|
||||||
public RestErrorResponse(final Response.Status status, final String time, final String error,
|
public RestErrorResponse(final Response.Status status, final String time, final String error,
|
||||||
final String message) {
|
final String message) {
|
||||||
this.time = time;
|
this.time = time;
|
||||||
@ -34,6 +49,7 @@ public class RestErrorResponse {
|
|||||||
this.message = message;
|
this.message = message;
|
||||||
this.status = status.getStatusCode();
|
this.status = status.getStatusCode();
|
||||||
this.statusMessage = status.getReasonPhrase();
|
this.statusMessage = status.getReasonPhrase();
|
||||||
|
this.inputError = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RestErrorResponse(final Response.Status status, final String error, final String message) {
|
public RestErrorResponse(final Response.Status status, final String error, final String message) {
|
||||||
@ -42,6 +58,7 @@ public class RestErrorResponse {
|
|||||||
this.message = message;
|
this.message = message;
|
||||||
this.status = status.getStatusCode();
|
this.status = status.getStatusCode();
|
||||||
this.statusMessage = status.getReasonPhrase();
|
this.statusMessage = status.getReasonPhrase();
|
||||||
|
this.inputError = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RestErrorResponse(final Response.Status status) {
|
public RestErrorResponse(final Response.Status status) {
|
||||||
@ -50,6 +67,7 @@ public class RestErrorResponse {
|
|||||||
this.time = Instant.now().toString();
|
this.time = Instant.now().toString();
|
||||||
this.status = status.getStatusCode();
|
this.status = status.getStatusCode();
|
||||||
this.statusMessage = status.getReasonPhrase();
|
this.statusMessage = status.getReasonPhrase();
|
||||||
|
this.inputError = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
50
src/org/kar/archidata/catcher/RestInputError.java
Normal file
50
src/org/kar/archidata/catcher/RestInputError.java
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package org.kar.archidata.catcher;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.validation.Path;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
public class RestInputError {
|
||||||
|
private static Pattern PATTERN = Pattern.compile("^([^.]+)\\.([^.]+)(\\.(.*))?");
|
||||||
|
@Column(length = 0)
|
||||||
|
public String argument;
|
||||||
|
@Column(length = 0)
|
||||||
|
public String path;
|
||||||
|
@NotNull
|
||||||
|
@Column(length = 0)
|
||||||
|
public String message;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "RestInputError [argument=" + this.argument + ", path=" + this.path + ", message=" + this.message + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public RestInputError() {}
|
||||||
|
|
||||||
|
public RestInputError(final Path path, final String message) {
|
||||||
|
final Matcher matcher = PATTERN.matcher(path.toString());
|
||||||
|
if (matcher.find()) {
|
||||||
|
//String firstPart = matcher.group(1); this is the request base element ==> not needed
|
||||||
|
this.argument = matcher.group(2);
|
||||||
|
this.path = matcher.group(4);
|
||||||
|
} else {
|
||||||
|
this.path = path.toString();
|
||||||
|
}
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RestInputError(final String path, final String message) {
|
||||||
|
this.path = path;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getFullPath() {
|
||||||
|
if (this.path == null) {
|
||||||
|
return this.argument;
|
||||||
|
}
|
||||||
|
return this.argument + "." + this.path;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,9 @@
|
|||||||
package org.kar.archidata.exception;
|
package org.kar.archidata.exception;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
|
import org.kar.archidata.catcher.RestInputError;
|
||||||
|
|
||||||
public class RESTErrorResponseException extends Exception {
|
public class RESTErrorResponseException extends Exception {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
@ -10,6 +13,7 @@ public class RESTErrorResponseException extends Exception {
|
|||||||
public String message;
|
public String message;
|
||||||
public int status;
|
public int status;
|
||||||
public String statusMessage;
|
public String statusMessage;
|
||||||
|
public List<RestInputError> inputError;
|
||||||
|
|
||||||
public RESTErrorResponseException() {
|
public RESTErrorResponseException() {
|
||||||
this.oid = new ObjectId();
|
this.oid = new ObjectId();
|
||||||
@ -18,16 +22,18 @@ public class RESTErrorResponseException extends Exception {
|
|||||||
this.message = null;
|
this.message = null;
|
||||||
this.status = 0;
|
this.status = 0;
|
||||||
this.statusMessage = null;
|
this.statusMessage = null;
|
||||||
|
this.inputError = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RESTErrorResponseException(final ObjectId oid, final String time, final String name, final String message,
|
public RESTErrorResponseException(final ObjectId oid, final String time, final String name, final String message,
|
||||||
final int status, final String statusMessage) {
|
final int status, final String statusMessage, final List<RestInputError> inputError) {
|
||||||
this.oid = oid;
|
this.oid = oid;
|
||||||
this.time = time;
|
this.time = time;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.status = status;
|
this.status = status;
|
||||||
this.statusMessage = statusMessage;
|
this.statusMessage = statusMessage;
|
||||||
|
this.inputError = inputError;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -20,6 +20,7 @@ import java.util.UUID;
|
|||||||
|
|
||||||
import org.kar.archidata.annotation.DataIfNotExists;
|
import org.kar.archidata.annotation.DataIfNotExists;
|
||||||
import org.kar.archidata.annotation.DataJson;
|
import org.kar.archidata.annotation.DataJson;
|
||||||
|
import org.kar.archidata.annotation.apiGenerator.ApiGenerationMode;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
@ -36,6 +37,7 @@ import jakarta.ws.rs.DefaultValue;
|
|||||||
@Table(name = "user")
|
@Table(name = "user")
|
||||||
@DataIfNotExists
|
@DataIfNotExists
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
@ApiGenerationMode(create = true, update = true)
|
||||||
public class User extends GenericDataSoftDelete {
|
public class User extends GenericDataSoftDelete {
|
||||||
@NotNull
|
@NotNull
|
||||||
@Column(length = 128)
|
@Column(length = 128)
|
||||||
|
@ -17,6 +17,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonParseException;
|
import com.fasterxml.jackson.core.JsonParseException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
|
||||||
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
|
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
|
||||||
|
|
||||||
import jakarta.ws.rs.core.HttpHeaders;
|
import jakarta.ws.rs.core.HttpHeaders;
|
||||||
@ -170,14 +171,21 @@ public class RESTApi {
|
|||||||
final RESTErrorResponseException out = this.mapper.readValue(httpResponse.body(),
|
final RESTErrorResponseException out = this.mapper.readValue(httpResponse.body(),
|
||||||
RESTErrorResponseException.class);
|
RESTErrorResponseException.class);
|
||||||
throw out;
|
throw out;
|
||||||
|
} catch (final InvalidDefinitionException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
LOGGER.error("body: {}", httpResponse.body());
|
||||||
|
throw new IOException("RestAPI Fail to parse the error " + ex.getClass().getName() + " ["
|
||||||
|
+ httpResponse.statusCode() + "] " + httpResponse.body());
|
||||||
} catch (final MismatchedInputException ex) {
|
} catch (final MismatchedInputException ex) {
|
||||||
throw new IOException(
|
ex.printStackTrace();
|
||||||
"Fail to get the data [" + httpResponse.statusCode() + "] " + httpResponse.body());
|
LOGGER.error("body: {}", httpResponse.body());
|
||||||
|
throw new IOException("RestAPI Fail to parse the error " + ex.getClass().getName() + " ["
|
||||||
|
+ httpResponse.statusCode() + "] " + httpResponse.body());
|
||||||
} catch (final JsonParseException ex) {
|
} catch (final JsonParseException ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
LOGGER.error("body: {}", httpResponse.body());
|
LOGGER.error("body: {}", httpResponse.body());
|
||||||
throw new IOException(
|
throw new IOException("RestAPI Fail to parse the error " + ex.getClass().getName() + " ["
|
||||||
"Fail to get the ERROR data [" + httpResponse.statusCode() + "] " + httpResponse.body());
|
+ httpResponse.statusCode() + "] " + httpResponse.body());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (clazz == Void.class || clazz == void.class) {
|
if (clazz == Void.class || clazz == void.class) {
|
||||||
|
@ -30,8 +30,6 @@ public class TestTime {
|
|||||||
static WebLauncherTest webInterface = null;
|
static WebLauncherTest webInterface = null;
|
||||||
static RESTApi api = null;
|
static RESTApi api = null;
|
||||||
|
|
||||||
private static Long idTest = 0L;
|
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public static void configureWebServer() throws Exception {
|
public static void configureWebServer() throws Exception {
|
||||||
ConfigureDb.configure();
|
ConfigureDb.configure();
|
||||||
|
@ -0,0 +1,95 @@
|
|||||||
|
package test.kar.archidata.hybernateValidator;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.MethodOrderer;
|
||||||
|
import org.junit.jupiter.api.Order;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.TestMethodOrder;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.kar.archidata.exception.RESTErrorResponseException;
|
||||||
|
import org.kar.archidata.tools.ConfigBaseVariable;
|
||||||
|
import org.kar.archidata.tools.RESTApi;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import test.kar.archidata.ConfigureDb;
|
||||||
|
import test.kar.archidata.StepwiseExtension;
|
||||||
|
import test.kar.archidata.apiExtern.Common;
|
||||||
|
import test.kar.archidata.hybernateValidator.model.ValidatorModel;
|
||||||
|
import test.kar.archidata.hybernateValidator.model.ValidatorSubModel;
|
||||||
|
|
||||||
|
@ExtendWith(StepwiseExtension.class)
|
||||||
|
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||||
|
public class TestValidator {
|
||||||
|
private final static Logger LOGGER = LoggerFactory.getLogger(TestValidator.class);
|
||||||
|
public final static String ENDPOINT_NAME = "TestResourceValidator";
|
||||||
|
|
||||||
|
static WebLauncherTest webInterface = null;
|
||||||
|
static RESTApi api = null;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
public static void configureWebServer() throws Exception {
|
||||||
|
ConfigureDb.configure();
|
||||||
|
LOGGER.info("configure server ...");
|
||||||
|
webInterface = new WebLauncherTest();
|
||||||
|
LOGGER.info("Clean previous table");
|
||||||
|
|
||||||
|
LOGGER.info("Start REST (BEGIN)");
|
||||||
|
webInterface.process();
|
||||||
|
LOGGER.info("Start REST (DONE)");
|
||||||
|
api = new RESTApi(ConfigBaseVariable.apiAdress);
|
||||||
|
api.setToken(Common.ADMIN_TOKEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public static void stopWebServer() throws Exception {
|
||||||
|
LOGGER.info("Kill the web server");
|
||||||
|
webInterface.stop();
|
||||||
|
webInterface = null;
|
||||||
|
ConfigureDb.clear();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Order(2)
|
||||||
|
@Test
|
||||||
|
public void DetectGenericError() throws Exception {
|
||||||
|
final ValidatorModel data = new ValidatorModel();
|
||||||
|
data.value = "plop";
|
||||||
|
data.data = "klsdfsdfsdfsdfj";
|
||||||
|
data.multipleElement = new ArrayList<>();
|
||||||
|
ValidatorSubModel tmp = new ValidatorSubModel();
|
||||||
|
tmp.data = "lkmkmlkmlklm";
|
||||||
|
data.multipleElement.add(tmp);
|
||||||
|
tmp = new ValidatorSubModel();
|
||||||
|
tmp.data = "1";
|
||||||
|
data.multipleElement.add(tmp);
|
||||||
|
data.subElement = new ValidatorSubModel();
|
||||||
|
data.subElement.data = "k";
|
||||||
|
final RESTErrorResponseException exception = Assertions.assertThrows(RESTErrorResponseException.class,
|
||||||
|
() -> api.post(void.class, TestValidator.ENDPOINT_NAME + "?queryParametersName=2", data));
|
||||||
|
Assertions.assertNotNull(exception);
|
||||||
|
LOGGER.debug("error on input:{}", exception);
|
||||||
|
Assertions.assertNull(exception.getMessage());
|
||||||
|
Assertions.assertNotNull(exception.inputError);
|
||||||
|
Assertions.assertEquals(5, exception.inputError.size());
|
||||||
|
Assertions.assertEquals("arg0", exception.inputError.get(0).argument);
|
||||||
|
Assertions.assertEquals(null, exception.inputError.get(0).path);
|
||||||
|
Assertions.assertEquals("must be greater than or equal to 5", exception.inputError.get(0).message);
|
||||||
|
Assertions.assertEquals("arg1", exception.inputError.get(1).argument);
|
||||||
|
Assertions.assertEquals("data", exception.inputError.get(1).path);
|
||||||
|
Assertions.assertEquals("size must be between 0 and 5", exception.inputError.get(1).message);
|
||||||
|
Assertions.assertEquals("arg1", exception.inputError.get(2).argument);
|
||||||
|
Assertions.assertEquals("multipleElement[1].data", exception.inputError.get(2).path);
|
||||||
|
Assertions.assertEquals("size must be between 2 and 2147483647", exception.inputError.get(2).message);
|
||||||
|
Assertions.assertEquals("arg1", exception.inputError.get(3).argument);
|
||||||
|
Assertions.assertEquals("subElement.data", exception.inputError.get(3).path);
|
||||||
|
Assertions.assertEquals("size must be between 2 and 2147483647", exception.inputError.get(3).message);
|
||||||
|
Assertions.assertEquals("arg1", exception.inputError.get(4).argument);
|
||||||
|
Assertions.assertEquals("value", exception.inputError.get(4).path);
|
||||||
|
Assertions.assertEquals("Field can not be set, it is a read-only field.", exception.inputError.get(4).message);
|
||||||
|
}
|
||||||
|
}
|
163
test/src/test/kar/archidata/hybernateValidator/WebLauncher.java
Executable file
163
test/src/test/kar/archidata/hybernateValidator/WebLauncher.java
Executable file
@ -0,0 +1,163 @@
|
|||||||
|
package test.kar.archidata.hybernateValidator;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.imageio.ImageReader;
|
||||||
|
import javax.imageio.ImageWriter;
|
||||||
|
|
||||||
|
import org.glassfish.grizzly.http.server.HttpServer;
|
||||||
|
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
|
||||||
|
import org.glassfish.jersey.jackson.JacksonFeature;
|
||||||
|
import org.glassfish.jersey.media.multipart.MultiPartFeature;
|
||||||
|
import org.glassfish.jersey.server.ResourceConfig;
|
||||||
|
import org.glassfish.jersey.server.validation.ValidationFeature;
|
||||||
|
import org.kar.archidata.UpdateJwtPublicKey;
|
||||||
|
import org.kar.archidata.catcher.GenericCatcher;
|
||||||
|
import org.kar.archidata.db.DbConfig;
|
||||||
|
import org.kar.archidata.exception.DataAccessException;
|
||||||
|
import org.kar.archidata.filter.CORSFilter;
|
||||||
|
import org.kar.archidata.filter.OptionFilter;
|
||||||
|
import org.kar.archidata.migration.MigrationEngine;
|
||||||
|
import org.kar.archidata.tools.ConfigBaseVariable;
|
||||||
|
import org.kar.archidata.tools.ContextGenericTools;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import jakarta.ws.rs.core.UriBuilder;
|
||||||
|
import test.kar.archidata.hybernateValidator.resource.TestResourceValidator;
|
||||||
|
|
||||||
|
public class WebLauncher {
|
||||||
|
final static Logger LOGGER = LoggerFactory.getLogger(WebLauncher.class);
|
||||||
|
protected UpdateJwtPublicKey keyUpdater = null;
|
||||||
|
protected HttpServer server = null;
|
||||||
|
|
||||||
|
public WebLauncher() {}
|
||||||
|
|
||||||
|
private static URI getBaseURI() {
|
||||||
|
return UriBuilder.fromUri(ConfigBaseVariable.getlocalAddress()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void migrateDB() throws Exception {
|
||||||
|
WebLauncher.LOGGER.info("Create migration engine");
|
||||||
|
final MigrationEngine migrationEngine = new MigrationEngine();
|
||||||
|
WebLauncher.LOGGER.info("Add initialization");
|
||||||
|
//migrationEngine.setInit(new Initialization());
|
||||||
|
WebLauncher.LOGGER.info("Add migration since last version");
|
||||||
|
//migrationEngine.add(new Migration20231126());
|
||||||
|
WebLauncher.LOGGER.info("Migrate the DB [START]");
|
||||||
|
migrationEngine.migrateWaitAdmin(new DbConfig());
|
||||||
|
WebLauncher.LOGGER.info("Migrate the DB [STOP]");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(final String[] args) throws Exception {
|
||||||
|
WebLauncher.LOGGER.info("[START] application wake UP");
|
||||||
|
final WebLauncher launcher = new WebLauncher();
|
||||||
|
launcher.migrateDB();
|
||||||
|
|
||||||
|
launcher.process();
|
||||||
|
WebLauncher.LOGGER.info("end-configure the server & wait finish process:");
|
||||||
|
Thread.currentThread().join();
|
||||||
|
WebLauncher.LOGGER.info("STOP Key updater");
|
||||||
|
launcher.stopOther();
|
||||||
|
WebLauncher.LOGGER.info("STOP the REST server:");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void plop(final String aaa) {
|
||||||
|
// List available Image Readers
|
||||||
|
WebLauncher.LOGGER.trace("Available Image Readers:");
|
||||||
|
final Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(aaa);
|
||||||
|
while (readers.hasNext()) {
|
||||||
|
final ImageReader reader = readers.next();
|
||||||
|
WebLauncher.LOGGER.trace("Reader: " + reader.getOriginatingProvider().getDescription(null));
|
||||||
|
WebLauncher.LOGGER.trace("Reader CN: " + reader.getOriginatingProvider().getPluginClassName());
|
||||||
|
// ImageIO.deregisterServiceProvider(reader.getOriginatingProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
// List available Image Writers
|
||||||
|
WebLauncher.LOGGER.trace("\nAvailable Image Writers:");
|
||||||
|
final Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(aaa);
|
||||||
|
while (writers.hasNext()) {
|
||||||
|
final ImageWriter writer = writers.next();
|
||||||
|
WebLauncher.LOGGER.trace("Writer: " + writer.getOriginatingProvider().getDescription(null));
|
||||||
|
WebLauncher.LOGGER.trace("Writer CN: " + writer.getOriginatingProvider().getPluginClassName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void process() throws InterruptedException, DataAccessException {
|
||||||
|
|
||||||
|
ImageIO.scanForPlugins();
|
||||||
|
plop("jpeg");
|
||||||
|
plop("png");
|
||||||
|
plop("webmp");
|
||||||
|
plop("webp");
|
||||||
|
// ===================================================================
|
||||||
|
// Configure resources
|
||||||
|
// ===================================================================
|
||||||
|
final ResourceConfig rc = new ResourceConfig();
|
||||||
|
|
||||||
|
// add multipart models ..
|
||||||
|
rc.register(MultiPartFeature.class);
|
||||||
|
// global authentication system
|
||||||
|
rc.register(OptionFilter.class);
|
||||||
|
// remove cors ==> all time called by an other system...
|
||||||
|
rc.register(CORSFilter.class);
|
||||||
|
// register exception catcher
|
||||||
|
GenericCatcher.addAll(rc);
|
||||||
|
// add default resource:
|
||||||
|
rc.register(TestResourceValidator.class);
|
||||||
|
// enable jersey specific validations (@Valid
|
||||||
|
rc.register(ValidationFeature.class);
|
||||||
|
|
||||||
|
ContextGenericTools.addJsr310(rc);
|
||||||
|
|
||||||
|
// add jackson to be discover when we are ins standalone server
|
||||||
|
rc.register(JacksonFeature.class);
|
||||||
|
|
||||||
|
LOGGER.info(" ==> {}", new DbConfig());
|
||||||
|
LOGGER.info("OAuth service {}", getBaseURI());
|
||||||
|
this.server = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), rc);
|
||||||
|
final HttpServer serverLink = this.server;
|
||||||
|
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
LOGGER.warn("Stopping server..");
|
||||||
|
serverLink.shutdownNow();
|
||||||
|
}
|
||||||
|
}, "shutdownHook"));
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// start periodic update of the token ...
|
||||||
|
// ===================================================================
|
||||||
|
this.keyUpdater = new UpdateJwtPublicKey();
|
||||||
|
this.keyUpdater.start();
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// run JERSEY
|
||||||
|
// ===================================================================
|
||||||
|
try {
|
||||||
|
this.server.start();
|
||||||
|
LOGGER.info("Jersey app started at {}", getBaseURI());
|
||||||
|
} catch (final Exception e) {
|
||||||
|
LOGGER.error("There was an error while starting Grizzly HTTP server.");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
if (this.server != null) {
|
||||||
|
this.server.shutdownNow();
|
||||||
|
this.server = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopOther() {
|
||||||
|
this.keyUpdater.kill();
|
||||||
|
try {
|
||||||
|
this.keyUpdater.join(4000, 0);
|
||||||
|
} catch (final InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
test/src/test/kar/archidata/hybernateValidator/WebLauncherTest.java
Executable file
19
test/src/test/kar/archidata/hybernateValidator/WebLauncherTest.java
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
package test.kar.archidata.hybernateValidator;
|
||||||
|
|
||||||
|
import org.kar.archidata.tools.ConfigBaseVariable;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class WebLauncherTest extends WebLauncher {
|
||||||
|
final private static Logger LOGGER = LoggerFactory.getLogger(WebLauncherTest.class);
|
||||||
|
|
||||||
|
public WebLauncherTest() {
|
||||||
|
LOGGER.debug("Configure REST system");
|
||||||
|
// for local test:
|
||||||
|
ConfigBaseVariable.apiAdress = "http://127.0.0.1:12345/test/api/";
|
||||||
|
// Enable the test mode permit to access to the test token (never use it in production).
|
||||||
|
ConfigBaseVariable.testMode = "true";
|
||||||
|
// ConfigBaseVariable.dbPort = "3306";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package test.kar.archidata.hybernateValidator.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.kar.archidata.annotation.checker.ReadOnlyField;
|
||||||
|
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
|
||||||
|
public class ValidatorModel {
|
||||||
|
@ReadOnlyField
|
||||||
|
public String value;
|
||||||
|
@Size(max = 5)
|
||||||
|
public String data;
|
||||||
|
|
||||||
|
@Valid
|
||||||
|
public List<ValidatorSubModel> multipleElement;
|
||||||
|
|
||||||
|
@Valid
|
||||||
|
public ValidatorSubModel subElement;
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package test.kar.archidata.hybernateValidator.model;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
|
||||||
|
public class ValidatorSubModel {
|
||||||
|
@Size(min = 2)
|
||||||
|
public String data;
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package test.kar.archidata.hybernateValidator.resource;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import jakarta.annotation.security.PermitAll;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import jakarta.validation.constraints.Min;
|
||||||
|
import jakarta.ws.rs.Consumes;
|
||||||
|
import jakarta.ws.rs.POST;
|
||||||
|
import jakarta.ws.rs.Path;
|
||||||
|
import jakarta.ws.rs.Produces;
|
||||||
|
import jakarta.ws.rs.QueryParam;
|
||||||
|
import jakarta.ws.rs.core.MediaType;
|
||||||
|
import test.kar.archidata.apiExtern.resource.TestResource;
|
||||||
|
import test.kar.archidata.hybernateValidator.model.ValidatorModel;
|
||||||
|
|
||||||
|
@Path("/TestResourceValidator")
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
|
public class TestResourceValidator {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(TestResource.class);
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@PermitAll
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public void post(final @QueryParam("queryParametersName") @Min(5) Long value, final @Valid ValidatorModel data)
|
||||||
|
throws Exception {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user