Common Infrastructure Utilities for Spring Boot Applications
Tapsi Utilities Starter is a comprehensive Kotlin library that provides essential utilities and extensions for Spring Boot applications. It offers a collection of commonly used functions, security services, reactive programming utilities, and formatting tools to accelerate development and maintain consistency across projects.
- Type casting utilities with safe casting operations
- Collection extensions for enhanced data manipulation
- String utilities including Persian/English number conversion
- Method reflection utilities for reactive type detection
- Encryption/Decryption services with salt support
- Hash services for secure password handling
- JWT token utilities for authentication
- Security properties for configuration management
- Reactor extensions for Mono and Flux operations
- Context utilities for reactive context management
- CompletableFuture integration with reactive streams
- Tuple extensions for reactive data handling
- Time operations for date/time manipulation
- Time value objects for type-safe time handling
- Time extensions for common time operations
- Random code generators for unique identifiers
- Format utilities for data presentation
- Custom formatters for specialized formatting needs
- Validator interface for reactive validation patterns
- CompositeValidator for combining multiple validators
- ValidatorFactory for Spring context-based validator management
- Auto-configuration for seamless validator integration
- Auto-configuration for seamless integration
- Spring context utilities for dependency injection
- Bean management utilities
<dependency>
<groupId>box.tapsi.libs</groupId>
<artifactId>utilities-starter</artifactId>
<version>0.9.5</version>
</dependency>Include the library in your Spring Boot project's dependencies.
The library automatically configures necessary beans when included in your classpath.
import box.tapsi.libs.utilities.*
import box.tapsi.libs.utilities.validator.*
// Common extensions
val castedValue: String = anyObject.castOrThrow<String>()
val persianNumbers = "12345".toPersianNumber() // "۱۲۳۴۵"
// Security services
@Autowired
lateinit var encryptionService: EncryptionService
val encrypted = encryptionService.encrypt("sensitive data", "salt")
val decrypted = encryptionService.decrypt(encrypted, "salt")
// Random code generation
@Autowired
lateinit var codeGenerator: CodeGenerator
val uniqueCode = codeGenerator.generate(8, "ORDER") // "ORDER-12345678"
// Time operations
@Autowired
lateinit var timeOperator: TimeOperator
val now = timeOperator.now()
val formattedDate = timeOperator.format(now, "yyyy-MM-dd")
// Validation framework
@Autowired
lateinit var validatorFactory: ValidatorFactory
val validator = validatorFactory.getValidator<User>("userValidator", "emailValidator")
validator.validate(user).subscribe()// Safe type casting
val result: String = someObject.castOrThrow<String>()
// Collection utilities
val items = listOf("a", "b", "a", "c")
val distinctLast = items.distinctLastBy { it } // ["b", "a", "c"]
// Number conversion
val persian = "123".toPersianNumber() // "۱۲۳"
val english = "۱۲۳".toEnglishNumber() // "123"
// Method reflection
val method = MyClass::class.java.getMethod("getData")
val isReactive = method.isReturningPublisher() // true if returns Mono/Flux@Service
class UserService(
private val encryptionService: EncryptionService,
private val hashService: HashService
) {
fun createUser(password: String): User {
val salt = encryptionService.generateSalt()
val hashedPassword = hashService.hash(password, salt)
return User(
passwordHash = hashedPassword,
salt = salt
)
}
fun verifyPassword(password: String, user: User): Boolean {
return hashService.verify(password, user.passwordHash, user.salt)
}
}// Mono extensions
Mono.just("data")
.withContext("key", "value")
.subscribe()
// Context utilities
Mono.deferContextual { ctx ->
val userId = ctx.get<String>("userId")
getUserById(userId)
}@Service
class SchedulingService(
private val timeOperator: TimeOperator
) {
fun scheduleTask() {
val now = timeOperator.now()
val tomorrow = timeOperator.addDays(now, 1)
val formatted = timeOperator.format(tomorrow, "yyyy-MM-dd HH:mm:ss")
// Schedule logic here
}
}// Define custom validators
@Component("emailValidator")
class EmailValidator : Validator<User> {
override fun validate(input: User): Mono<Void> {
return if (input.email.isValidEmail()) {
Mono.empty()
} else {
Mono.error(ValidationException("Invalid email format"))
}
}
}
@Component("ageValidator")
class AgeValidator : Validator<User> {
override fun validate(input: User): Mono<Void> {
return if (input.age >= 18) {
Mono.empty()
} else {
Mono.error(ValidationException("User must be at least 18 years old"))
}
}
}
// Use ValidatorFactory to combine validators
@Service
class UserService(
private val validatorFactory: ValidatorFactory
) {
fun createUser(user: User): Mono<User> {
val validator = validatorFactory.getValidator<User>("emailValidator", "ageValidator")
return validator.validate(user)
.then(Mono.just(user))
.doOnNext { saveUser(it) }
}
}
// Manual composite validator usage
@Service
class OrderService {
fun validateOrder(order: Order): Mono<Void> {
val validators = listOf(
OrderAmountValidator(),
OrderItemValidator(),
OrderStatusValidator()
)
val compositeValidator = CompositeValidator(validators)
return compositeValidator.validate(order)
}
}tapsi:
security:
crypto:
algorithm: AES
key-size: 256
hash:
algorithm: SHA-256
iterations: 10000The library provides Spring Boot auto-configuration. You can customize behavior by:
- Excluding auto-configuration classes if needed
- Overriding bean definitions in your configuration
- Using conditional beans for specific scenarios
The validator framework is automatically configured when the library is included:
// Validator beans are automatically discovered and registered
@Component("userValidator")
class UserValidator : Validator<User> { ... }
@Component("orderValidator")
class OrderValidator : Validator<Order> { ... }
// ValidatorFactory is automatically available for injection
@Service
class MyService(
private val validatorFactory: ValidatorFactory
) {
fun validateUser(user: User) {
val validator = validatorFactory.getValidator<User>("userValidator")
// Use validator...
}
}The ValidatorAutoConfiguration class automatically:
- Scans for
Validatorimplementations - Registers them as Spring beans
- Provides
ValidatorFactoryfor validator management - Enables composite validation patterns
The library includes comprehensive test coverage and provides test utilities:
@SpringBootTest
class MyServiceTest {
@Test
fun `should encrypt and decrypt data`() {
val encryptionService = EncryptionServiceImpl()
val original = "test data"
val salt = encryptionService.generateSalt()
val encrypted = encryptionService.encrypt(original, salt)
val decrypted = encryptionService.decrypt(encrypted, salt)
assertEquals(original, decrypted)
}
@Test
fun `should validate user with composite validator`() {
val emailValidator = EmailValidator()
val ageValidator = AgeValidator()
val validators = listOf(emailValidator, ageValidator)
val compositeValidator = CompositeValidator(validators)
val validUser = User(email = "test@example.com", age = 25)
compositeValidator.validate(validUser)
.test()
.verifyComplete()
}
@Test
fun `should fail validation for invalid user`() {
val emailValidator = EmailValidator()
val ageValidator = AgeValidator()
val validators = listOf(emailValidator, ageValidator)
val compositeValidator = CompositeValidator(validators)
val invalidUser = User(email = "invalid-email", age = 16)
compositeValidator.validate(invalidUser)
.test()
.verifyError()
}
}We welcome contributions! Please see our contributing guidelines:
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
# Clone the repository
git clone https://github.com/tapsi-box/utilities-starter.git
# Navigate to project directory
cd utilities-starter
# Build the project
./gradlew build
# Run tests
./gradlew test
# Run code quality checks
./gradlew detekt
./gradlew spotlessCheckThis project maintains high code quality standards:
- Kotlin with strict compiler options
- Detekt for static code analysis
- Spotless for code formatting
- Comprehensive testing with JUnit 5
- Spring Boot Test integration
- Spring Framework 6.2.10 - Core Spring functionality
- Spring Boot 3.5.5 - Auto-configuration support
- Reactor Core 3.7.9 - Reactive programming support
- Spring Security Crypto 6.5.3 - Security utilities
- JJWT 0.12.5 - JWT handling
- Jackson 2.17.0 - JSON processing
- Micrometer 1.15.3 - Metrics support
- JUnit 5 - Testing framework
- Spring Boot Test - Integration testing
- Reactor Test - Reactive testing utilities
- Mockito Kotlin - Mocking framework
| Library Version | Spring Boot | Kotlin | Java |
|---|---|---|---|
| 0.0.9 | 3.5.x | 1.9.23 | 17+ |
This project is licensed under the MIT License - see the LICENSE file for details.
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: Project Wiki
- Mahdi Bohloul - @mahdibohloul
- Spring Boot team for the excellent framework
- Kotlin team for the amazing language
- Reactor team for reactive programming support
- All contributors and users of this library
Made with ❤️ by the Tapsi team