Skip to content

Commit b81ac60

Browse files
committed
Merge branch 'develop'
2 parents db5d350 + 0f664b8 commit b81ac60

22 files changed

+632
-375
lines changed

README.md

Lines changed: 350 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,356 @@
11
# Java Validator
22
A rule based validator developed for easy use with the Spring Boot framework.
33

4-
- *Extendable*: You can always add custom rules
4+
- *Extendable* ✨: You can always add custom rules
5+
- *Error format* ✅: You can directly return the result of the failed validation
6+
- *Well documented* 📑: Always know what you are doing
7+
8+
## Table of contents
9+
- [Adding dependency](#adding-dependency)
10+
- [Usage](#usage)
11+
- [Internationalization](#internationalization)
12+
- [Builders and Methods](#builders-and-methods)
13+
- [`string` rules](#string-rules)
14+
- [`number` rules](#number-rules)
15+
- [`object` rules](#object-rules)
16+
- [`array` rules](#array-rules)
17+
- [Use with Spring Boot](#use-with-spring-boot)
18+
- [Custom rules](#custom-rules)
19+
20+
21+
---
22+
23+
24+
## Adding dependency
25+
To use the validator add the following dependency to your `pom.xml`.
26+
```xml
27+
<dependency>
28+
<groupId>dev.ditsche</groupId>
29+
<artifactId>validator</artifactId>
30+
<version>2.2.0</version>
31+
</dependency>
32+
```
33+
34+
35+
---
36+
537

638
## Usage
7-
The Validator is generic and can be used to validate multiple objects.
39+
40+
Easiest way to use the validator in a Spring Boot project is to setup a `ValidatorConfig` class. There you can
41+
define a bean for each validator you need. Or you can create a validator in the controller method, do it, as you like.
42+
43+
A validator ist built using static helper methods. Here is a working example:
44+
45+
```java
46+
Validator validator = Validator.fromRules(
47+
string("name").required().trim().alphanum().max(50),
48+
string("gender").optional().defaultValue("m").max(1),
49+
number("age").required().min(18),
50+
object("tickets").fields(
51+
string("event").required().trim()
52+
)
53+
);
54+
```
55+
56+
This snippet validates an incoming DTO for the given fields and the nested object `tickets`.
57+
58+
To validate an object, just call the validate method of the validator. Pass in the object and the optional `abortEarly`
59+
parameter. This is a boolean indicating, if the `ValidationException` should be thrown after the first validation error
60+
or at the end if there are any.
61+
62+
Make sure, that if you use altering rules like `defaul()` or `trim()` you reassign the input object with the result of
63+
the validate method. That way you get the validated and updated input DTO for further operations.
64+
65+
```java
66+
dto = validator.validate(dto);
67+
```
68+
69+
70+
---
71+
72+
73+
## Internationalization
74+
Unfortunately it is not possible to change the outputted language to something different than english.
75+
76+
If you need to provide other languages as well, you can make use of the error type. When
77+
you return the result of the `getErrors()` method of the ErrorBag that you got from the thrown
78+
`ValidationException` you have the error type available and can show messages based on this
79+
unique key.
80+
81+
82+
---
83+
84+
85+
## Builders and Methods
86+
As said, to generate a validator you should make use of the static helper methods.
87+
The following types are supported at the moment:
88+
- string
89+
- number (int, long, float, ...)
90+
- object
91+
- array
92+
93+
In the following sections you learn which methods and rules are available by default and how
94+
to use them. Each `Builder` has a `build()` method which returns a `Validateable`, if you need
95+
to have one of those.
96+
97+
### `string` rules
98+
99+
#### Usage
100+
The following snippet returns an instance of the `StringRuleBuilder` class.
101+
```java
102+
string(field)
103+
```
104+
105+
#### Available rules
106+
107+
- ##### `required()`
108+
Marks the field as *required* meaning it cannot be null or empty.
109+
110+
- ##### `optional()`
111+
Marks the field as *optional*. All rules behind this rule can fail.
112+
113+
- ##### `trim()`
114+
*Trims the input and alters* the value to the trimmed string.
115+
116+
- ##### `length(int)`
117+
Checks if the provided string has the *exact same length* as the provided parameter `length`.
118+
119+
- ##### `between(int, int)`
120+
Checks if the *length of the string is between* the first and second parameter integers.
121+
122+
- ##### `min(int)`
123+
Checks if the length of the string is *greater or equal* to the given parameter.
124+
125+
- ##### `max(int)`
126+
Checks if the length of the string is *smaller or equal* to the given parameter.
127+
128+
- ##### `email()`
129+
Checks if the fields value is a *valid email address*.
130+
131+
- ##### `url()`
132+
Checks if the fields value is a *valid url*.
133+
134+
- ##### `pattern(String)`
135+
Checks if the fields value *matches the given Regex* pattern. The
136+
`pattern` parameter should be the `String` representation of a Regex.
137+
138+
- ##### `alphanum()`
139+
Checks if the fields value is *alphanumeric*.
140+
141+
- ##### `ip()`
142+
Checks if the fields value is a *valid ipv4 address*.
143+
144+
- ##### `creditCard()`
145+
Checks if the fields value is a *valid credit card number*.
146+
147+
- ##### `defaultValue(String)`
148+
*Sets the fields value to the given string*, if the fields value is null or empty.
149+
Rejects if the given parameter is not assignable to the fields value.
150+
151+
- ##### `custom(Rule)`
152+
Registers a custom defined rule.
153+
154+
---
155+
156+
### `number` rules
157+
158+
#### Usage
159+
The following snippet returns an instance of the `NumberRuleBuilder` class.
160+
```java
161+
number(field)
162+
```
163+
164+
#### Available rules
165+
166+
- ##### `required()`
167+
Marks the field as *required* meaning it cannot be null.
168+
169+
- ##### `optional()`
170+
Marks the field as *optional*. All rules behind this rule can fail.
171+
172+
- ##### `length(int)`
173+
Checks if the *fields value is the same* as the provided parameter `length`.
174+
175+
- ##### `size(int, int)`
176+
Checks if the *value is between* the first and second parameter integers.
177+
178+
- ##### `min(int)`
179+
Checks if the fields value is *greater or equal* to the given parameter.
180+
181+
- ##### `max(int)`
182+
Checks if the fields value of the string is *smaller or equal* to the given parameter.
183+
184+
- ##### `defaultValue(int)`
185+
*Sets the fields value to the given number*, if the fields value is null or 0.
186+
Rejects if the given parameter is not assignable to the fields value.
187+
188+
- ##### `custom(Rule)`
189+
Registers a custom defined rule.
190+
191+
---
192+
193+
### `object` rules
194+
195+
#### Usage
196+
The following snippet returns an instance of the `ObjectRuleBuilder` class.
197+
```java
198+
object(field)
199+
```
200+
201+
#### Available rules
202+
203+
- ##### `optional()`
204+
Marks the field as *optional*. All rules behind this rule can fail.
205+
206+
- ##### `child(Builder)`
207+
Adds a check for *one child property* using a `Builder`.
208+
209+
- ##### `child(Validatable)`
210+
Adds a check for *one child property* using a `Validatable`.
211+
212+
- ##### `fields(Builder[])`
213+
Adds a check for *one or more child properties* using the given `Builder`.
214+
215+
---
216+
217+
### `array` rules
218+
219+
#### Usage
220+
The following snippet returns an instance of the `ArrayRuleBuilder` class.
221+
```java
222+
array(field)
223+
```
224+
225+
#### Available rules
226+
227+
- ##### `required()`
228+
Marks the field as *required* meaning it cannot be null or empty.
229+
230+
- ##### `optional()`
231+
Marks the field as *optional*. All rules behind this rule can fail.
232+
233+
- ##### `length(int)`
234+
Checks if the *length of the array is the same* as the provided parameter `length`.
235+
236+
- ##### `size(int, int)`
237+
Checks if the *length of the array is between* the first and second parameter integers.
238+
239+
- ##### `min(int)`
240+
Checks if the length of the array is *greater or equal* to the given parameter.
241+
242+
- ##### `max(int)`
243+
Checks if the length of the array is *smaller or equal* to the given parameter.
244+
245+
- ##### `objects(Builder[])`
246+
*Used for object arrays only!* Gets an array of `Builder` instances, which are validated for every object in the array.
247+
248+
- ##### `custom(Rule)`
249+
Registers a custom defined rule.
250+
251+
#### Additional methods
252+
253+
Arrays are handled differently as they can have elements or objects as children. To handle
254+
an array of elements you have to use the `elements` method which returns an `ArrayElementRuleBuilder`.
255+
256+
- ##### `elements()`
257+
Returns an `ArrayElementRuleBuilder` which has access to nearly every rule from above as
258+
the type of the arrays elements is unknown.
259+
260+
261+
---
262+
263+
264+
## Use with Spring Boot
265+
To make use of the functionalities of Spring Boot and the structure of the errors returned by
266+
the `ErrorBag` instance of the thrown `ValidationException` you'd need to define a custom exception
267+
handler. Spring Boot makes it easy to create one.
268+
269+
The following advice generates a well-structured json response that the frontend can use
270+
to display the errors in the UI. It returns with the `422 Unprocessable Entity` status code
271+
of http which indicates a validation problem.
272+
273+
```java
274+
@ControllerAdvice
275+
public class ValidationAdvice {
276+
277+
@ExceptionHandler(ValidationException.class)
278+
@ResponseBody
279+
public ResponseEntity<?> handleValidationErrors(ValidationException ex) {
280+
return ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY).body(
281+
ex.getErrors()
282+
);
283+
}
284+
285+
}
286+
```
287+
288+
The resulting json would look like this:
289+
290+
```json
291+
[
292+
{
293+
"field": "email",
294+
"errors": [
295+
{
296+
"message": "The field \"email\" is required",
297+
"errorType": "validation.error.format.required"
298+
},
299+
{
300+
"message": "The field \"email\" needs to be a valid email address",
301+
"errorType": "validation.error.format.email"
302+
}
303+
]
304+
},
305+
...
306+
]
307+
```
308+
309+
310+
---
311+
312+
313+
## Custom rules
314+
You can easily extend the functionality of the validator by defining custom rules. If you need a specific Regex and don't
315+
want to use the `PatternRule` over and over again you can create your own rule.
316+
317+
To do this, implement the `Rule` interface and add an instance of your rule to the validator like shown below:
318+
319+
```java
320+
public class MyRule implements Rule {
321+
@Override
322+
public RuleResult test(Object value) {
323+
324+
// Your validation logic
325+
326+
327+
// You have the following methods to generate a result:
328+
// RuleResult.reject() -> Rejects the rule and marks it as not passed.
329+
// RuleResult.resolve() -> Resolve the rule and mark it passed.
330+
// RuleResult.resolve(Object) -> Resolve the rule and update the value of the field.
331+
// RuleResult.passes(boolean) -> Resolves or rejects based on the given boolean or expression.
332+
return RuleResult.resolve();
333+
}
334+
335+
@Override
336+
public String message(String field) {
337+
// The error message
338+
return String.format("The field \"%s\" is a custom error", field);
339+
}
340+
341+
@Override
342+
public String getType() {
343+
// The error type, to make internationalization possible
344+
return RULE_TYPE_PREFIX + "my.rule";
345+
}
346+
}
347+
```
348+
349+
And use that rule in a validator:
350+
8351
```java
9-
Validator<User> validator = new Validator<>();
10-
validator.addRule()
11-
```
352+
Validator.fromRules(
353+
...,
354+
string("myfield").custom(new MyRule())
355+
);
356+
```

pom.xml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<project xmlns="http://maven.apache.org/POM/4.0.0"
3-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4-
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2+
<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">
53
<modelVersion>4.0.0</modelVersion>
64

75
<groupId>dev.ditsche</groupId>
86
<artifactId>validator</artifactId>
9-
<version>2.1.0</version>
7+
<version>2.2.1-SNAPSHOT</version>
108

119
<packaging>jar</packaging>
1210

1311
<name>Java Validator</name>
14-
<description>This is a simple Validator that can be used
12+
<description>This is a simple validator that can be used
1513
to validate incoming http requests in Spring Boot.
1614
</description>
1715
<url>https://github.com/ditschedev/validator</url>

0 commit comments

Comments
 (0)