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.4</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