Sanitizer-Lib is an enterprise-grade input sanitization framework for Java applications that provides comprehensive integration with Spring Boot and JPA. The library enforces data integrity and consistency by implementing automatic field sanitization on DTOs and entities prior to processing or persistence.
@Sanitize(using = Class<? extends FieldSanitizer>[]): Declarative annotation for field-level sanitizationFieldSanitizer<T>: Core interface for implementing custom sanitization logic
| Sanitizer | Purpose |
|---|---|
TrimSanitizer |
Eliminates leading and trailing whitespace |
LowerCaseSanitizer |
Normalizes text to lowercase |
UpperCaseSanitizer |
Normalizes text to uppercase |
TitleCaseSanitizer |
Capitalizes the first character of each word |
SentenceCaseSanitizer |
Capitalizes only the first character, lowercases the rest |
CollapseWhitespaceSanitizer |
Trims and collapses internal whitespace to a single space |
CreditCardMaskSanitizer |
Secures card numbers by displaying only the last four digits |
SSNMaskSanitizer |
Masks U.S. SSN, revealing only the last four digits |
IBANMaskSanitizer |
Masks IBAN except the last four characters |
EmailAliasStripSanitizer |
Removes +alias from email addresses and lowercases |
HtmlEscapeSanitizer |
Escapes HTML special characters |
SlugifySanitizer |
Converts text to a URL-friendly slug |
SafeFilenameSanitizer |
Replaces filesystem-reserved characters with underscores |
PhoneE164Sanitizer |
Normalizes phone numbers to E.164 format |
UuidNormalizeSanitizer |
Lowercases and validates UUID strings |
NullIfBlankSanitizer |
Returns null if the string is blank |
RemoveNonPrintableSanitizer |
Filters out non-printable control characters |
TruncateSanitizer |
Configurable truncation with optional suffix (new in 1.1.0) |
-
Spring Boot (
sanitizer-spring)- Jackson
SanitizerModulefor automatic sanitization during deserialization - Spring-managed
SanitizerRegistryfor programmatic sanitizer resolution - Zero-configuration setup via Spring Boot autoconfiguration
- Jackson
-
JPA (
sanitizer-jpa)SanitizationEntityListenerautomatically invoked during@PrePersistand@PreUpdatelifecycle events- Seamless integration with existing entity models
The library follows a modular design with clear separation of concerns:
| Module | Responsibility |
|---|---|
| sanitizer-core | Core API, annotations, utilities, and standard sanitizers |
| sanitizer-spring | Spring Boot integration with autoconfiguration support |
| sanitizer-jpa | JPA entity lifecycle integration |
- Java 21 (LTS)
- Gradle 8.x+
- Spring Boot 3.4.x (for Spring integration)
Sanitization works by mutating annotated fields via reflection. Java records
have final components that cannot be reassigned this way, so records are not
sanitized — they are skipped. This applies both to top-level records and to
records embedded inside a sanitized bean graph, so mixing records and POJOs is
safe and never throws. If a record carries @Sanitize annotations, a one-time
warning is logged (via System.Logger) to make the misconfiguration visible.
If you need record values sanitized, sanitize a mutable DTO/POJO first and copy
the cleaned values into the record.
<dependency>
<groupId>io.github.rabinarayanpatra.sanitizer</groupId>
<artifactId>sanitizer-spring</artifactId>
<version>1.1.1</version>
</dependency>Gradle (Kotlin DSL):
implementation("io.github.rabinarayanpatra.sanitizer:sanitizer-spring:1.1.1")<dependency>
<groupId>io.github.rabinarayanpatra.sanitizer</groupId>
<artifactId>sanitizer-jpa</artifactId>
<version>1.1.1</version>
</dependency>Gradle (Kotlin DSL):
implementation("io.github.rabinarayanpatra.sanitizer:sanitizer-jpa:1.1.1")package com.example.dto;
import io.github.rabinarayanpatra.sanitizer.annotation.Sanitize;
import io.github.rabinarayanpatra.sanitizer.builtin.TrimSanitizer;
import io.github.rabinarayanpatra.sanitizer.builtin.LowerCaseSanitizer;
public class UserDto {
@Sanitize(using = {TrimSanitizer.class, LowerCaseSanitizer.class})
private String email;
// Standard getters and setters
}The framework automatically applies the sanitization chain (trim, then lowercase) when Spring deserializes JSON payloads into the UserDto object.
package com.example.entity;
import io.github.rabinarayanpatra.sanitizer.annotation.Sanitize;
import io.github.rabinarayanpatra.sanitizer.builtin.CreditCardMaskSanitizer;
import io.github.rabinarayanpatra.sanitizer.jpa.SanitizationEntityListener;
import jakarta.persistence.*;
@Entity
@EntityListeners(SanitizationEntityListener.class)
public class Payment {
@Id
@GeneratedValue
private Long id;
@Sanitize(using = CreditCardMaskSanitizer.class)
private String cardNumber;
// Standard getters and setters
}When the entity is persisted or updated, the framework automatically masks the credit card number, enhancing security compliance.
Sanitizers can accept parameters via the params attribute. Extend ConfigurableFieldSanitizer to create parameterized sanitizers:
@Sanitize(using = TruncateSanitizer.class, params = "maxLength=100,suffix=...")
private String description;Create your own configurable sanitizer:
public class MaskSanitizer extends ConfigurableFieldSanitizer<String> {
@Override
public String sanitize(final String input) {
if (input == null) return null;
int reveal = getIntParam("reveal", 4);
String ch = getParam("character", "*");
if (input.length() <= reveal) return input;
return ch.repeat(input.length() - reveal) + input.substring(input.length() - reveal);
}
}Usage: @Sanitize(using = MaskSanitizer.class, params = "reveal=6,character=X")
- Create a Sanitizer Implementation:
package com.yourorg.sanitizer;
import io.github.rabinarayanpatra.sanitizer.core.FieldSanitizer;
import org.springframework.stereotype.Component;
@Component
public class NumericOnlySanitizer implements FieldSanitizer<String> {
@Override
public String sanitize(final String input) {
return input == null ? null : input.replaceAll("[^0-9]", "");
}
}- Apply to Domain Fields:
@Sanitize(using = NumericOnlySanitizer.class)
private String phoneNumber;- Programmatic Usage (when needed):
@Autowired
private SanitizerRegistry registry;
public String processInput(String rawPhoneNumber) {
return registry.get(NumericOnlySanitizer.class).sanitize(rawPhoneNumber);
}sanitizer-lib/ ← Parent project (packaging=pom)
├── sanitizer-core/ ← Core API and standard implementations
├── sanitizer-spring/ ← Spring Boot integration components
└── sanitizer-jpa/ ← JPA persistence integration
Each module maintains its own dependency set while inheriting common configuration from the parent build script.
- API Javadoc: https://rabinarayanpatra.github.io/sanitizer-lib/javadoc/
- Changelog: See CHANGELOG.md
- Version Strategy: Adheres to Semantic Versioning principles
- Artifact Publishing: Automated deployment to Maven Central via GitHub Actions
- Javadoc Publishing: Automated deployment to GitHub Pages on release
- CI/CD Pipeline: See
.github/workflows/release.ymlfor implementation details
- Fork the repository
- Create a feature branch (
git checkout -b feature/enhancement-name) - Implement changes with appropriate test coverage
- Commit using conventional commits (
git commit -m 'feat: enhancement description') - Push changes (
git push origin feature/enhancement-name) - Submit a pull request
All contributions must adhere to the established code style and include suitable test coverage.
This project is licensed under the MIT License - see the LICENSE file for details.