Haft uses Go templates to generate code. This page explains how templates work and how to customize them.
Built-in Templates
Haft includes embedded templates for all generated files:
Project Templates
| Template | Output |
|---|
Application.java.tmpl | Main application class |
ApplicationTests.java.tmpl | Application test class |
pom.xml.tmpl | Maven POM file |
application.yml.tmpl | YAML configuration |
application.properties.tmpl | Properties configuration |
gitignore.tmpl | Git ignore file |
Resource Templates
| Template | Output |
|---|
Entity.java.tmpl | JPA entity |
Repository.java.tmpl | Spring Data repository |
Service.java.tmpl | Service interface |
ServiceImpl.java.tmpl | Service implementation |
Controller.java.tmpl | REST controller |
Request.java.tmpl | Request DTO |
Response.java.tmpl | Response DTO |
Mapper.java.tmpl | MapStruct mapper |
ResourceNotFoundException.java.tmpl | Exception class |
Config Templates
Generated by haft generate config:
| Template | Output |
|---|
AsyncConfig.java.tmpl | Async task executor configuration |
AuditingConfig.java.tmpl | JPA Auditing configuration |
CacheConfig.java.tmpl | Cache manager configuration |
CorsConfig.java.tmpl | CORS configuration |
JacksonConfig.java.tmpl | Jackson ObjectMapper configuration |
OpenApiConfig.java.tmpl | OpenAPI/Swagger configuration |
WebMvcConfig.java.tmpl | Web MVC configuration |
Exception Templates
Generated by haft generate exception:
| Template | Output |
|---|
GlobalExceptionHandler.java.tmpl | @ControllerAdvice exception handler |
ErrorResponse.java.tmpl | Standard error response DTO |
ResourceNotFoundException.java.tmpl | 404 Not Found exception |
BadRequestException.java.tmpl | 400 Bad Request exception |
UnauthorizedException.java.tmpl | 401 Unauthorized exception |
ForbiddenException.java.tmpl | 403 Forbidden exception |
ConflictException.java.tmpl | 409 Conflict exception |
ValidationException.java.tmpl | Validation error exception |
BusinessException.java.tmpl | Business logic exception |
DataIntegrityException.java.tmpl | Data integrity violation exception |
ServiceUnavailableException.java.tmpl | 503 Service unavailable exception |
RateLimitException.java.tmpl | 429 Rate limit exceeded exception |
FileUploadException.java.tmpl | File upload error exception |
ExternalServiceException.java.tmpl | External service error exception |
InternalServerException.java.tmpl | 500 Internal server error exception |
Test Templates
| Template | Output |
|---|
ControllerTest.java.tmpl | Controller integration test |
ServiceTest.java.tmpl | Service unit test |
Wrapper Templates
Generated during haft init for Maven/Gradle wrapper:
| Template | Output |
|---|
mvnw.tmpl | Maven wrapper script (Unix) |
mvnw.cmd.tmpl | Maven wrapper script (Windows) |
MavenWrapperDownloader.java.tmpl | Maven wrapper downloader |
maven-wrapper.properties.tmpl | Maven wrapper properties |
gradlew.tmpl | Gradle wrapper script (Unix) |
gradlew.bat.tmpl | Gradle wrapper script (Windows) |
Security Templates (JWT)
| Template | Output |
|---|
SecurityConfig.java.tmpl | Spring Security configuration |
JwtUtil.java.tmpl | JWT token utility |
JwtAuthenticationFilter.java.tmpl | JWT request filter |
AuthenticationController.java.tmpl | Auth endpoints |
AuthRequest.java.tmpl | Login request DTO |
AuthResponse.java.tmpl | Token response DTO |
RegisterRequest.java.tmpl | Registration DTO |
RefreshTokenRequest.java.tmpl | Refresh token DTO |
CustomUserDetailsService.java.tmpl | User loading service |
User.java.tmpl | User entity |
Role.java.tmpl | Role entity |
UserRepository.java.tmpl | User repository |
RoleRepository.java.tmpl | Role repository |
Security Templates (Session)
| Template | Output |
|---|
SecurityConfig.java.tmpl | Form login configuration |
CustomUserDetailsService.java.tmpl | User loading service |
AuthController.java.tmpl | MVC auth controller |
RegisterRequest.java.tmpl | Registration DTO |
Security Templates (OAuth2)
| Template | Output |
|---|
SecurityConfig.java.tmpl | OAuth2 login configuration |
OAuth2UserService.java.tmpl | Custom OAuth2 user handling |
OAuth2SuccessHandler.java.tmpl | Post-login handler |
OAuth2UserPrincipal.java.tmpl | OAuth2User implementation |
Template Variables
Templates have access to these variables:
Project Variables
| Variable | Description | Example |
|---|
{{.Name}} | Project name | MyApp |
{{.GroupId}} | Maven group ID | com.example |
{{.ArtifactId}} | Maven artifact ID | my-app |
{{.Version}} | Project version | 0.0.1-SNAPSHOT |
{{.Description}} | Project description | My Spring Boot App |
{{.BasePackage}} | Base package | com.example.myapp |
{{.JavaVersion}} | Java version | 21 |
{{.SpringBootVersion}} | Spring Boot version | 3.4.0 |
Resource Variables
| Variable | Description | Example |
|---|
{{.Name}} | Resource name (PascalCase) | User |
{{.NameLower}} | Resource name (lowercase) | user |
{{.NameCamel}} | Resource name (camelCase) | user |
{{.BasePackage}} | Base package | com.example.myapp |
Boolean Flags
| Variable | Description |
|---|
{{.HasLombok}} | Lombok is available |
{{.HasMapStruct}} | MapStruct is available |
{{.HasValidation}} | Validation is available |
Security Variables
| Variable | Description |
|---|
{{.SecurityPackage}} | Security package path |
{{.UserEntityPackage}} | User entity package |
{{.UserRepositoryPackage}} | User repository package |
{{.UserEntityName}} | Name of User entity |
{{.DefaultJwtSecret}} | Generated JWT secret |
{{.GenerateEntities}} | Whether to generate User/Role entities |
Template Functions
| Function | Description | Example |
|---|
plural | Pluralize a word | {{plural .NameLower}} → users |
Example: Entity Template
package {{.BasePackage}}.entity;
import jakarta.persistence.*;
{{if .HasLombok}}
import lombok.*;
{{end}}
@Entity
@Table(name = "{{plural .NameLower}}")
{{if .HasLombok}}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
{{end}}
public class {{.Name}} {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
{{if not .HasLombok}}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
{{end}}
}
Example: Controller Template
package {{.BasePackage}}.controller;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
{{if .HasValidation}}
import jakarta.validation.Valid;
{{end}}
import {{.BasePackage}}.service.{{.Name}}Service;
import {{.BasePackage}}.dto.{{.Name}}Request;
import {{.BasePackage}}.dto.{{.Name}}Response;
import java.util.List;
@RestController
@RequestMapping("/api/{{plural .NameLower}}")
public class {{.Name}}Controller {
private final {{.Name}}Service {{.NameCamel}}Service;
public {{.Name}}Controller({{.Name}}Service {{.NameCamel}}Service) {
this.{{.NameCamel}}Service = {{.NameCamel}}Service;
}
@GetMapping
public ResponseEntity<List<{{.Name}}Response>> getAll() {
return ResponseEntity.ok({{.NameCamel}}Service.findAll());
}
@PostMapping
public ResponseEntity<{{.Name}}Response> create(
{{if .HasValidation}}@Valid {{end}}@RequestBody {{.Name}}Request request) {
return ResponseEntity.ok({{.NameCamel}}Service.create(request));
}
}
Custom Templates
Haft supports custom templates at two levels:
| Location | Priority | Scope |
|---|
.haft/templates/ | Highest | Project-specific |
~/.haft/templates/ | Medium | User-global |
| Built-in (embedded) | Lowest | Default fallback |
When generating code, Haft checks each location in priority order and uses the first template found.
Setting Up Custom Templates
haft template init
haft template init --category resource
haft template init --global
haft template init --force
Listing Templates
haft template list
haft template list --custom
haft template list --category resource
haft template list --paths
User-Friendly Syntax
Haft supports a simplified template syntax alongside standard Go templates:
Simple Placeholders
| Placeholder | Go Template Equivalent | Example Output |
|---|
${Name} | {{.Name}} | User |
${name} | {{.NameLower}} | user |
${nameCamel} | {{.NameCamel}} | user |
${nameSnake} | {{.NameSnake}} | user |
${nameKebab} | {{.NameKebab}} | user |
${namePlural} | {{plural .NameLower}} | users |
${NamePlural} | {{plural .Name}} | Users |
${BasePackage} | {{.BasePackage}} | com.example.app |
${Package} | {{.Package}} | com.example.app.user |
${IDType} | {{.IDType}} | Long or UUID |
${TableName} | {{.TableName}} | users |
Available conditions: HasLombok, HasJpa, HasValidation, HasMapStruct, HasSwagger, HasBaseEntity, UsesUUID, UsesLong
Validating Templates
haft template validate
haft template validate --vars
haft template validate --conditions
Example Custom Template
package ${BasePackage}.controller;
import org.springframework.web.bind.annotation.*;
import io.swagger.v3.oas.annotations.tags.Tag;
@Tag(name = "${Name}", description = "${Name} management endpoints")
@RestController
@RequestMapping("/api/${namePlural}")
public class ${Name}Controller {
private final ${Name}Service ${nameCamel}Service;
public ${Name}Controller(${Name}Service ${nameCamel}Service) {
this.${nameCamel}Service = ${nameCamel}Service;
}
}
For complete command documentation, see haft template.
See Also