Service Layer
📝 Note: This guide uses generic placeholder names to be reusable across any Spring Boot microservice. Replace with your actual implementation:
{YourService}→ Your service name (e.g.,OrderService,PaymentService)BusinessService→ Your core service (e.g.,OrderService,UserService)DataService→ Your data processing service (e.g.,PaymentService,InventoryService)IntegrationService→ Your external integration (e.g.,PaymentGatewayService){RequestType}→ Your request DTO (e.g.,CreateOrderRequest){ResponseType}→ Your response DTO (e.g.,OrderResponse)
Overview
The service layer contains business logic and orchestration for authentication, authorization, and data processing operations. It acts as the intermediary between controllers and external API clients.
Key Principles
- Interface-Driven Design: Define contracts in
skeleton/, implement inimpl/ - Constructor Injection: Use final fields and constructor injection for all dependencies
- Single Responsibility: Each service has one clear, well-defined purpose
- Comprehensive JavaDoc: Document all public methods with parameters, returns, and exceptions
- Proper Exception Handling: Log with context, wrap technical exceptions, let controllers handle HTTP mapping
Package Structure
service/
├── skeleton/ # Service interfaces (contracts)
│ ├── BusinessService.java
│ ├── DataService.java
│ └── ...
└── impl/ # Service implementations
├── BusinessServiceImpl.java
├── DataServiceImpl.java
└── ...
Guides
Design & Architecture
- Design Patterns - Service Layer, Interface-Implementation, Facade, Strategy, Dependency Injection, Wrapper, and Template Method patterns
- Best Practices - Interface-driven design, constructor injection, exception handling, JavaDoc standards, logging, naming conventions, security, and code formatting
Testing & Quality
- Testing Guidelines - Unit testing with JUnit 5 and Mockito, integration testing, test coverage goals, and best practices
- Anti-Patterns - Common mistakes to avoid including business logic in controllers, circular dependencies, field injection, and god services
Code Examples
All examples use proper package structure, comprehensive JavaDoc, and follow best practices:
Core Patterns
- InterfaceExample.java - Interface-Implementation pattern with skeleton and impl separation
- ConstructorInjectionExample.java - Constructor injection with final fields and immutability
- StrategyExample.java - Strategy pattern for different authentication mechanisms (MVPD, regular, passwordless)
Best Practices
- JavaDocExample.java - Comprehensive JavaDoc with all required elements
- ExceptionHandlingExample.java - Proper exception handling, logging, and domain exception wrapping
- LoggingExample.java - SLF4J logging with proper levels, parameterization, and security
- WrapperPatternExample.java - Parameter wrapper pattern for reducing method parameters
Testing
- UnitTestExample.java - JUnit 5 with Mockito, AAA pattern, and comprehensive test scenarios
Quick Reference
Service Implementation Template
@Service
public class ExampleServiceImpl implements ExampleService {
private final DependencyService dependencyService;
public ExampleServiceImpl(DependencyService dependencyService) {
this.dependencyService = dependencyService;
}
/**
* Business method with full JavaDoc.
*
* @param param description
* @return description
* @throws Exception description
*/
@Override
public Result processOperation(String param) throws Exception {
// Business logic here
}
}
Logging Template
private static final Logger logger = LoggerFactory.getLogger(ServiceImpl.class);
logger.info("Business event with context: {}", contextValue);
logger.warn("Recoverable issue: {}", issue);
logger.error("Error with context: {}", context, exception);
Exception Handling Template
try {
// Business logic
} catch (SpecificException e) {
logger.error("Context: {}", contextInfo, e);
throw new DomainException("User-friendly message", e);
}
Test Template
@ExtendWith(MockitoExtension.class)
class ServiceImplTest {
@Mock private DependencyService dependencyService;
@InjectMocks private ServiceImpl service;
@Test
void testOperation_Success() {
// Arrange
when(dependencyService.method(any())).thenReturn(result);
// Act
var result = service.operation(input);
// Assert
assertNotNull(result);
verify(dependencyService, times(1)).method(any());
}
}
Key Services
| Service | Responsibility |
|---|---|
BusinessService |
Business operations and login orchestration |
ExampleService |
MVPD-specific authentication flows |
DataService |
data token generation and validation |
ProcessingService |
Token refresh operations |
LogoutService |
Logout and session cleanup |
IntegrationService |
Entitlement fetching and validation |
AccountService |
MVPD temporary account management |
ConfigService |
Configuration data retrieval |
FeatureFlagService |
Feature flag evaluation |
Code Formatting
All Java code uses Spotless with Google Java Format (AOSP style):
./gradlew spotlessCheck # Verify formatting
./gradlew spotlessApply # Fix formatting issues
Auto-applied:
- ✅ License header on every file
- ✅ Unused imports removed
- ✅ 4-space indentation
- ✅ Google Java Format (AOSP)
- ✅ Trailing whitespace removed
- ✅ Files end with newline
Integration with Other Layers
Controllers → Services:
- Controllers receive HTTP requests and validate basic input
- Controllers call service methods for business logic
- Controllers map service results to HTTP responses
Services → Clients:
- Services orchestrate business logic
- Services call client decorators for external API calls
- Services aggregate data from multiple sources
- Services handle business-level errors
Naming Conventions
Interfaces: Noun/noun phrase + "Service" suffix (e.g., BusinessService, DataService)
Implementations: Interface name + "Impl" suffix (e.g., BusinessServiceImpl, DataServiceImpl)
Methods: Verb/verb phrase, descriptive (e.g., loginUser(), buildAmcnAuthTokens(), authenticateAccountId())
Packages: skeleton for interfaces, impl for implementations
Summary
Services in this package provide:
- ✅ Clean, testable architecture using established design patterns
- ✅ Interface-driven design for flexibility and testability
- ✅ Constructor injection for immutability and safety
- ✅ Comprehensive documentation and logging
- ✅ Proper exception handling and security
- ✅ Clear separation of concerns
- ✅ Consistent naming and formatting
- ✅ Automated code formatting with Spotless
This ensures maintainable, reliable, and scalable business logic.