Skip to content
This repository has been archived by the owner on Oct 2, 2024. It is now read-only.

Commit

Permalink
Update Jakarta documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Rollczi committed May 20, 2024
1 parent e13a050 commit 06cf3c8
Show file tree
Hide file tree
Showing 4 changed files with 243 additions and 23 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/ build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ env:
ARTIFACT: webHelpLITECOMMANDS2-all.zip
# Docker image version
DOCKER_VERSION: 241.15989
ALGOLIA_ARTIFACT: 'algolia-indexes-HI.zip'
ALGOLIA_ARTIFACT: 'algolia-indexes-LITECOMMANDS.zip'
ALGOLIA_APP_NAME: 'AA5N7A7U42'
ALGOLIA_INDEX_NAME: 'litecommands'
ALGOLIA_KEY: '${{ secrets.ALGOLIA_KEY }}'
Expand Down Expand Up @@ -48,6 +48,7 @@ jobs:
path: |
artifacts/${{ env.ARTIFACT }}
artifacts/report.json
artifacts/${{ env.ALGOLIA_ARTIFACT }}
retention-days: 7

test:
Expand Down
1 change: 1 addition & 0 deletions Writerside/cfg/buildprofiles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<algolia-id>AA5N7A7U42</algolia-id>
<algolia-index>litecommands</algolia-index>
<algolia-api-key>b36a06ddbc4e036fb9dffc0ed94e22ac</algolia-api-key>
<web-root>docs.rollczi.dev</web-root>
</variables>
</build-profile>

Expand Down
Binary file added Writerside/images/litecommands-jakarta.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
262 changes: 240 additions & 22 deletions Writerside/topics/Jakarta-Extension.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
# Jakarta Extension

The `litecommands-jakarta` is a extension for supporting Jakarta EE annotation validation.
The `litecommands-jakarta` is a extension for supporting Jakarta EE annotation validation.
It allows you to use Jakarta EE Bean Validation annotations in the command arguments:

```Java
@Execute
void ban(@Arg @Pattern(regexp = "[a-zA-Z_]+") String name)
void ban(@Arg @Size(min = 3, max = 16) String nick) {
// Command implementation
}
```

## Dependency
## 0. Dependency
Add the following dependency to your project:

<tabs>
Expand All @@ -30,15 +33,217 @@ implementation("dev.rollczi:litecommands-adventure:%latest_version%")
</tabs>


## Registering the extension
## 1. Register Jakarta extension

Register the extension in the `LiteCommands` builder:

<tabs>

<tab title="Jakarta Extension">

```java
.extension(new LiteJakartaExtension<>(), config -> config
// jakarta config ...
)
```
</tab>

<tab title="Jakarta Extension (without config)">

```java
.extension(new LiteJakartaExtension<>())
```
</tab>

</tabs>

Before configuration, it is worth knowing how the Jakarta Validation works in LiteCommands.

Suppose we have a command with a `nick` argument annotated with `@Size` and `@Pattern` annotations.

<img src="litecommands-jakarta.png" alt="litecommands jakarta" width="700"/>

**1*** - Argument `nick` (String)
**2*** - `@Size` jakarta annotation (between 3 and 16 characters)
**3*** - `@Pattern` jakarta annotation (only letters)
**4*** - Jakarta Validation (`org.hibernate.validator:hibernate-validator` implementation)
**5*** - Result of the validation (contains all violations)
**6*** - Constraint violations message (joined header with all violation messages)
**7*** - Violation message (specific message for each violation type)

See documentation for [Jakarta EE Bean Validation](https://jakarta.ee/specifications/bean-validation/3.0/apidocs/jakarta/validation/constraints/package-summary) to learn more about jakarta validation annotations.

## 2. Configure Jakarta messages

### 2.1. Constraint violations message

The `.constraintViolationsMessage()` method allows you to define a message for all constraint violations.

For example, we can define a message for all violations, which will contain the header and all violation messages.
The `result.asJoinedString()` method joins all violation messages into one string.

```Java
.constraintViolationsMessage((invocation, result) ->
"[!] Custom constraint violations: \n" + result.asJoinedString("\n")
)
```

## Example
Result of the method will be:

```Java
[!] Custom constraint violations:
<nick> - size must be between 3 and 16
<nick> - must match "[a-zA-Z]*"
```

### 2.2. Global violation message

The `.violationMessage()` method allows you to define a message for all violations.

For example, we can define a message for all violations, which will contain the parameter name and the violation message.

```Java
.violationMessage((invocation, violation) ->
" - " + violation.getParameterName() + ": " + violation.getMessage()
)
```

Result of the method will be:

```Java
[!] Custom constraint violations:
- nick: size must be between 3 and 16
- nick: must match "[a-zA-Z]*"
```

### 2.3. Violation messages for specific annotations

The `.violationMessage()` method allows you to define a message for specific annotations.

For example, we can define a message for the `@Size` annotation.
The `violation.getAnnotation()` returns `@Size` annotation instance and allows you to get the annotation values.

```Java
.violationMessage(Size.class, (invocation, violation) -> {
Size size = violation.getAnnotation();
int min = size.min();
int max = size.max();
String name = violation.getParameterName();

return " - " + name + ": between " + min + " and " + max;
})
```

Result of the method will be:

```Java
[!] Custom constraint violations:
- nick: between 3 and 16
- nick: must match "[a-zA-Z]*"
```

### 2.4. Violation messages for specific annotations in specific locale

First, we need to define how to get the locale for a command invocation.

```Java
.locale(invocation -> {
Locale locale = invocation.sender().getLocale();

return locale != null ? locale : Locale.ENGLISH;
})
```

The `.violationMessage()` method allows you to define a message for specific annotations in specific locale.

For example, we can define a message for the `@Pattern` annotation in the English locale.

```Java
.violationMessage(Pattern.class, (invocation, violation) -> {
Pattern pattern = violation.getAnnotation();
String name = violation.getParameterName();

return Locale.ENGLISH.equals(violation.getLocale())
? " - " + name + ": [English] must match " + pattern.regexp()
: " - " + name + ": [Polish] musi pasować do " + pattern.regexp();
})
```

Result for the English locale will be:

```Java
[!] Custom constraint violations:
- nick: [English] must match "[a-zA-Z]*"
- nick: size must be between 3 and 16
```

Result for the other locale will be:

```Java
[!] Custom constraint violations:
- nick: [Polish] musi pasować do "[a-zA-Z]*"
- nick: size must be between 3 and 16
```

## 3. Full configuration

```Java
.extension(new LiteJakartaExtension<>(), config -> config
// locale
.locale(invocation -> {
Locale locale = invocation.sender().getLocale();

return locale != null ? locale : Locale.ENGLISH;
})

// constraint violations message
.constraintViolationsMessage((invocation, result) ->
"[!] Custom constraint violations: \n" + result.asJoinedString("\n")
)

// global violation message
.violationMessage((invocation, violation) ->
" - " + violation.getParameterName() + ": " + violation.getMessage()
)

// violation message for specific annotations
.violationMessage(Size.class, (invocation, violation) -> {
Size size = violation.getAnnotation();
int min = size.min();
int max = size.max();
String name = violation.getParameterName();

return " - " + name + ": between " + min + " and " + max;
})

.violationMessage(Pattern.class, (invocation, violation) -> {
Pattern pattern = violation.getAnnotation();
String name = violation.getParameterName();

return Locale.ENGLISH.equals(violation.getLocale())
? " - " + name + ": [English] must match " + pattern.regexp()
: " - " + name + ": [Polish] musi pasować do " + pattern.regexp();
})
)
```

## 4. Advanced configuration

### 4.1. Custom validation factory

The `.validationFactory()` method allows you to define a custom validation factory.

For example, we can define a custom validation factory that will use the `org.hibernate.validator:hibernate-validator` implementation.

```Java
.validationFactory(Validation.byProvider(HibernateValidator.class)
.configure()
// hibernate validator config ...
.buildValidatorFactory()
)
```

## Other examples

```Java
@Command(name = "ban")
Expand All @@ -47,38 +252,51 @@ public class BanCommand {
@Execute
void ban(
@Arg @Pattern(regexp = "[a-zA-Z_]+") String name,
@Arg @Future Instant date,
@Arg @Future Instant date
) {
// Command implementation
}

}
```

See documentation for [Jakarta EE Bean Validation](https://jakarta.ee/specifications/bean-validation/3.0/apidocs/jakarta/validation/constraints/package-summary) to learn more about validation annotations.
```Java
@Command(name = "login")
public class LoginCommand {

## Handling validation errors
@Execute
void login(@Arg @Size(min = 8) String password) {
// Command implementation
}

If the validation fails, then the handler for `JakartaResult` will be called.
}
```

```Java
public class JakartaResultHandler implements ResultHandler<SENDER, JakartaResult> {
@Command(name = "email")
public class EmailCommand {

@Override
public void handle(Invocation<SENDER> invocation, JakartaResult result, ResultHandlerChain<SENDER> chain) {
for (ConstraintViolation<Object> violation : result.getViolations()) {
String message = violation.getMessage();
String messageKey = violation.getMessageTemplate();

// ... (send message to the sender)
}
@Execute
void email(@Arg @Email String email) {
// Command implementation
}

}
```

And register it in the `LiteCommands` builder:

```Java
.result(new JakartaResultHandler())
```
@Command(name = "credit-card")

public class CreditCommand {

@Execute
void credit(@Arg @CreditCardNumber String cardNumber) {
// Command implementation
}

}
```

See also:
- [Jakarta EE Bean Validation annotations](https://jakarta.ee/specifications/bean-validation/3.0/apidocs/jakarta/validation/constraints/package-summary)
- [Hibernate Validator](https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/)

0 comments on commit 06cf3c8

Please sign in to comment.