Java Backend Interview Q&A← All stacks

Spring Boot — Interview Q&A Matrix

Parent stack: Spring Ecosystem Technology: Spring Boot Levels: Junior · Senior · Architect Questions: 5

Each entry contains a Question, the Expected Depth, an Ideal Answer, and Red Flags.

Junior

Q1 — Dependency injection and bean scopes

Question: What is dependency injection in Spring, why is constructor injection preferred, and what is the default bean scope?

Expected Depth:

Ideal Answer:

java
@Service
public class OrderService {
    private final PaymentClient paymentClient;

    public OrderService(PaymentClient paymentClient) {
        this.paymentClient = paymentClient;
    }
}
java
@Service
class PricingService {
    Price calculate(Order order) {
        BigDecimal total = order.lines().stream()
                .map(OrderLine::subtotal)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        return new Price(total);
    }
}
java
@Service
class ReportService {
    private final ObjectProvider<ReportContext> contexts;

    ReportService(ObjectProvider<ReportContext> contexts) {
        this.contexts = contexts;
    }

    Report create(ReportRequest request) {
        ReportContext context = contexts.getObject();
        return context.create(request);
    }
}
java
OrderService(@Qualifier("stripePaymentClient") PaymentClient paymentClient) {
    this.paymentClient = paymentClient;
}

Red Flags:


Q2 — @RestController request flow and validation

Question: Trace what happens when a JSON POST hits a @RestController method, and how do you validate the request body?

Expected Depth:

Ideal Answer:

java
public record CreateOrder(
        @NotBlank String sku,
        @Min(1) int quantity) {}

@PostMapping("/orders")
public ResponseEntity<OrderResponse> create(
        @Valid @RequestBody CreateOrder request) {
    OrderResponse order = service.create(request);
    URI location = URI.create("/orders/" + order.id());
    return ResponseEntity.created(location).body(order);
}
java
@RestControllerAdvice
class ApiExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    ResponseEntity<ProblemDetail> invalid(MethodArgumentNotValidException error) {
        ProblemDetail problem = ProblemDetail.forStatus(HttpStatus.BAD_REQUEST);
        problem.setTitle("Request validation failed");
        problem.setProperty("fieldErrors", error.getBindingResult()
                .getFieldErrors()
                .stream()
                .map(field -> Map.of(
                        "field", field.getField(),
                        "message", field.getDefaultMessage()))
                .toList());
        return ResponseEntity.badRequest().body(problem);
    }
}

Red Flags:


Senior

Q3 — Transaction propagation and self-invocation

Question: A method annotated @Transactional(propagation = REQUIRES_NEW) does not open a new transaction when another method in the same class calls it. Explain why and how propagation works.

Expected Depth:

Ideal Answer:

java
@Service
class InvoiceService {
    private final AuditService auditService;

    @Transactional
    public void process(Invoice invoice) {
        saveInvoice(invoice);
        auditService.record(invoice.id());
    }
}

@Service
class AuditService {
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void record(Long invoiceId) {
        auditRepository.save(new AuditEntry(invoiceId));
    }
}
java
@Transactional(rollbackFor = IOException.class)
public void importFile(Path path) throws IOException {
    // database work
}

Red Flags:


Architect

Q4 — Auto-configuration and building a custom starter

Question: As architect you want to standardize cross-cutting concerns (tracing, metrics, resilience defaults) across 30 services. How does Spring Boot auto-configuration work, and how would you build a shared starter?

Expected Depth:

Ideal Answer:

text
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
java
@AutoConfiguration
@ConditionalOnClass(MeterRegistry.class)
@ConditionalOnProperty(
    prefix = "platform.observability",
    name = "enabled",
    havingValue = "true",
    matchIfMissing = true)
@EnableConfigurationProperties(PlatformProperties.class)
public class ObservabilityAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean
    ObservationHandler<?> platformObservationHandler(
        PlatformProperties properties) {
    return new PlatformObservationHandler(properties.serviceTag());
    }
}
java
@ConfigurationProperties("platform.observability")
@Validated
public record PlatformProperties(
    boolean enabled,
    @NotBlank String serviceTag) {}
java
new ApplicationContextRunner()
    .withConfiguration(AutoConfigurations.of(
        ObservabilityAutoConfiguration.class))
    .withBean(ObservationHandler.class, CustomHandler::new)
    .run(context -> assertThat(context)
        .hasSingleBean(ObservationHandler.class));

Red Flags:


Q5 — Testing strategy across the Spring stack

Question: Define a pragmatic testing strategy for a Spring Boot service so teams get confidence without slow, flaky suites.

Expected Depth:

Ideal Answer:

java
@Testcontainers
@SpringBootTest
class OrderFlowIT {
    @Container
    @ServiceConnection
    static PostgreSQLContainer<?> postgres =
            new PostgreSQLContainer<>("postgres:16");

    @Test
    void createsOrder() {
        // exercise the real HTTP and persistence flow
    }
}

Red Flags:


Scoring Rubric

Level Pass bar
JuniorUses dependency injection, scopes, validation, and HTTP responses correctly.
SeniorDefines correct transaction boundaries and understands proxy behavior.
ArchitectBuilds observable platform conventions and a balanced, reliable test strategy.