Skip to main content

Templates

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

TemplateOutput
Application.java.tmplMain application class
ApplicationTests.java.tmplApplication test class
pom.xml.tmplMaven POM file
application.yml.tmplYAML configuration
application.properties.tmplProperties configuration
gitignore.tmplGit ignore file

Resource Templates

TemplateOutput
Entity.java.tmplJPA entity
Repository.java.tmplSpring Data repository
Service.java.tmplService interface
ServiceImpl.java.tmplService implementation
Controller.java.tmplREST controller
Request.java.tmplRequest DTO
Response.java.tmplResponse DTO
Mapper.java.tmplMapStruct mapper
ResourceNotFoundException.java.tmplException class

Config Templates

Generated by haft generate config:

TemplateOutput
AsyncConfig.java.tmplAsync task executor configuration
AuditingConfig.java.tmplJPA Auditing configuration
CacheConfig.java.tmplCache manager configuration
CorsConfig.java.tmplCORS configuration
JacksonConfig.java.tmplJackson ObjectMapper configuration
OpenApiConfig.java.tmplOpenAPI/Swagger configuration
WebMvcConfig.java.tmplWeb MVC configuration

Exception Templates

Generated by haft generate exception:

TemplateOutput
GlobalExceptionHandler.java.tmpl@ControllerAdvice exception handler
ErrorResponse.java.tmplStandard error response DTO
ResourceNotFoundException.java.tmpl404 Not Found exception
BadRequestException.java.tmpl400 Bad Request exception
UnauthorizedException.java.tmpl401 Unauthorized exception
ForbiddenException.java.tmpl403 Forbidden exception
ConflictException.java.tmpl409 Conflict exception
ValidationException.java.tmplValidation error exception
BusinessException.java.tmplBusiness logic exception
DataIntegrityException.java.tmplData integrity violation exception
ServiceUnavailableException.java.tmpl503 Service unavailable exception
RateLimitException.java.tmpl429 Rate limit exceeded exception
FileUploadException.java.tmplFile upload error exception
ExternalServiceException.java.tmplExternal service error exception
InternalServerException.java.tmpl500 Internal server error exception

Test Templates

TemplateOutput
ControllerTest.java.tmplController integration test
ServiceTest.java.tmplService unit test

Wrapper Templates

Generated during haft init for Maven/Gradle wrapper:

TemplateOutput
mvnw.tmplMaven wrapper script (Unix)
mvnw.cmd.tmplMaven wrapper script (Windows)
MavenWrapperDownloader.java.tmplMaven wrapper downloader
maven-wrapper.properties.tmplMaven wrapper properties
gradlew.tmplGradle wrapper script (Unix)
gradlew.bat.tmplGradle wrapper script (Windows)

Security Templates (JWT)

TemplateOutput
SecurityConfig.java.tmplSpring Security configuration
JwtUtil.java.tmplJWT token utility
JwtAuthenticationFilter.java.tmplJWT request filter
AuthenticationController.java.tmplAuth endpoints
AuthRequest.java.tmplLogin request DTO
AuthResponse.java.tmplToken response DTO
RegisterRequest.java.tmplRegistration DTO
RefreshTokenRequest.java.tmplRefresh token DTO
CustomUserDetailsService.java.tmplUser loading service
User.java.tmplUser entity
Role.java.tmplRole entity
UserRepository.java.tmplUser repository
RoleRepository.java.tmplRole repository

Security Templates (Session)

TemplateOutput
SecurityConfig.java.tmplForm login configuration
CustomUserDetailsService.java.tmplUser loading service
AuthController.java.tmplMVC auth controller
RegisterRequest.java.tmplRegistration DTO

Security Templates (OAuth2)

TemplateOutput
SecurityConfig.java.tmplOAuth2 login configuration
OAuth2UserService.java.tmplCustom OAuth2 user handling
OAuth2SuccessHandler.java.tmplPost-login handler
OAuth2UserPrincipal.java.tmplOAuth2User implementation

Template Variables

Templates have access to these variables:

Project Variables

VariableDescriptionExample
{{.Name}}Project nameMyApp
{{.GroupId}}Maven group IDcom.example
{{.ArtifactId}}Maven artifact IDmy-app
{{.Version}}Project version0.0.1-SNAPSHOT
{{.Description}}Project descriptionMy Spring Boot App
{{.BasePackage}}Base packagecom.example.myapp
{{.JavaVersion}}Java version21
{{.SpringBootVersion}}Spring Boot version3.4.0

Resource Variables

VariableDescriptionExample
{{.Name}}Resource name (PascalCase)User
{{.NameLower}}Resource name (lowercase)user
{{.NameCamel}}Resource name (camelCase)user
{{.BasePackage}}Base packagecom.example.myapp

Boolean Flags

VariableDescription
{{.HasLombok}}Lombok is available
{{.HasMapStruct}}MapStruct is available
{{.HasValidation}}Validation is available

Security Variables

VariableDescription
{{.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

FunctionDescriptionExample
pluralPluralize 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:

LocationPriorityScope
.haft/templates/HighestProject-specific
~/.haft/templates/MediumUser-global
Built-in (embedded)LowestDefault fallback

When generating code, Haft checks each location in priority order and uses the first template found.

Setting Up Custom Templates

# Copy all embedded templates to your project
haft template init

# Copy only resource templates
haft template init --category resource

# Copy to global location (~/.haft/templates/)
haft template init --global

# Overwrite existing templates
haft template init --force

Listing Templates

# List all templates with their sources
haft template list

# Show only custom (non-embedded) templates
haft template list --custom

# Filter by category
haft template list --category resource

# Show full file paths
haft template list --paths

User-Friendly Syntax

Haft supports a simplified template syntax alongside standard Go templates:

Simple Placeholders

PlaceholderGo Template EquivalentExample 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

Comment-Based Conditionals

// @if HasLombok
@Data
@Builder
// @else
// Manual getters/setters here
// @endif

Available conditions: HasLombok, HasJpa, HasValidation, HasMapStruct, HasSwagger, HasBaseEntity, UsesUUID, UsesLong

Validating Templates

# Validate all project templates
haft template validate

# Show available placeholder variables
haft template validate --vars

# Show available conditions
haft template validate --conditions

Example Custom Template

package ${BasePackage}.controller;

import org.springframework.web.bind.annotation.*;
// @if HasSwagger
import io.swagger.v3.oas.annotations.tags.Tag;
// @endif

// @if HasSwagger
@Tag(name = "${Name}", description = "${Name} management endpoints")
// @endif
@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