Spring Integration
July 22, 2026 · View on GitHub
OfficeFloor handler classes are plain Java. They obtain Spring beans and HTTP data using standard Spring dependency injection and Spring MVC parameter annotations. OfficeFloor enriches Spring; it does not replace it.
Bean injection — parameters injected by type
OfficeFloor registers every bean in the Spring application context as a managed object. Any parameter of a service method whose type matches a Spring bean is injected automatically — no annotation is needed on that parameter.
@Service
public class GreetingService {
public String greet(String name) {
return "Hello, " + name + "!";
}
}
public class GetGreetingLogic {
public void service(GreetingService greetingService, ObjectResponse<GreetingResponse> response) {
response.send(new GreetingResponse(greetingService.greet("World")));
}
}
The class carries no @RestController, @RequestMapping or @ResponseBody. The YAML file wires
the class to a URL and HTTP method (see
YAML Endpoint Configuration).
Spring MVC parameter annotations
Service methods can use all the standard Spring MVC parameter annotations, plus OfficeFloor's own web annotations:
- Spring:
@PathVariable,@RequestParam,@RequestHeader,@CookieValue,@RequestBody,@ModelAttribute,@RequestPart - OfficeFloor:
@HttpPathParameter,@HttpQueryParameter,@HttpHeaderParameter,@HttpObject
public class GetNamedGreetingLogic {
public void service(
@PathVariable(name = "name") String name,
GreetingService greetingService,
ObjectResponse<GreetingResponse> response) {
response.send(new GreetingResponse(greetingService.greet(name)));
}
}
Always use the name = attribute form
Use @PathVariable(name = "name") and @RequestParam(name = "name"). The shorthand
@PathVariable("name") sets the value attribute, which requires @AliasFor annotation
synthesis to alias to name. OfficeFloor resolves arguments from raw Java reflection where that
synthesis is not applied, so the shorthand silently produces an empty value and the binding
fails.
Responses — ObjectResponse<T>
ObjectResponse<T> serialises the object to JSON and writes it to the HTTP response. Declare it
as a method parameter and call send(...):
response.send(new GreetingResponse(...));
Custom headers and status — ObjectResponse<ResponseEntity<T>>
For full Spring compatibility, ObjectResponse also accepts a ResponseEntity<T> as its type
parameter. This lets you set custom response headers or a non-200 status code while keeping the
same dependency-injected style:
public void service(ObjectResponse<ResponseEntity<GreetingResponse>> response) {
HttpHeaders headers = new HttpHeaders();
headers.add("X-Greeting", "custom");
response.send(new ResponseEntity<>(new GreetingResponse("Hello"), headers, HttpStatus.OK));
}
When you only need the body and a 200 status, ObjectResponse<T> is simpler; reach for the
ResponseEntity form when you need headers or a specific status code.
What stays exactly the same as any Spring Boot app
@SpringBootApplicationentry point- Spring Security, Spring Data JPA, Bean Validation, Actuator, Thymeleaf and other Spring Boot starters
@Service,@Component,@Repository,@Configurationbeans and@Qualifierinjection- Testing with
MockMvcand@SpringBootTest(webEnvironment = RANDOM_PORT)+TestRestTemplate
Spring Security is configured as normal, and the usual method annotations still work on handler
classes. An endpoint can instead declare its SpEL expression in YAML with authorize:, which keeps
the endpoint's security visible in the same file as its steps and lets one path config file secure a
whole subtree — see authorize:.
Transactions are the one Spring habit to drop: use govern: [ transaction ] on the functions rather
than @Transactional, so the transaction spans the pipeline — see
govern:.
See the Tutorials for worked examples of each of these integrations.