Reputation: 2025
I have problem with injecting service in controller's method. I have following service:
@Service
@RequiredArgsConstructor
public class CreateFranchiseUseCase {
private final FranchiseService franchiseService;
private final UserService userService;
private final ACLEntryService aclEntryService;
private final FranchiseDTOMapper franchiseDTOMapper;
public Franchise execute(CreateFranchiseDTO dto) {
// ...
}
}
And then in Controller:
@RestController
@RequiredArgsConstructor
public class FranchiseController {
// ...
@PostMapping("/api/franchises")
public ResponseEntity<Object> createFranchise(CreateFranchiseDTO dto, CreateFranchiseUseCase useCase) {
Frachise franchise = useCase.execute(dto);
// ...
}
}
When I call this endpoint I get NullPointerException. The exception occurs in execute method and debugging the method I discovered that all attributes: franchiseService
, userService
, aclEntryService
and franchiseDTOMapper
are NULL.
All classes: FranchiseService
, UserService
and ACLEntryService
are annotated with @Service
annotation. And FranchiseDTOMapper
is annotated with @Mapper(componentModel = "spring")
Does Spring support Method Injection? Alternativly is there any way I can request instance of CreateFranchiseUseCase
class inside createFranchise()
method like so:
@PostMapping("/api/franchises")
public ResponseEntity<Object> createFranchise(CreateFranchiseDTO dto) {
CreateFranchiseUseCase useCase = container.get(CreateFranchiseUseCase.class) // <-- something like this
Frachise franchise = useCase.execute(dto);
// ...
}
Upvotes: 2
Views: 10989
Reputation: 2643
Does Spring support Method Injection?
No. Receivable objects by arguments is listed here:
You can use ApplicatonContext#getBean()
:
@Autowired
private ApplicationContext context;
@PostMapping("/api/franchises")
public ResponseEntity<Object> createFranchise(CreateFranchiseDTO dto) {
reateFranchiseUseCase useCase = context.getBean(CreateFranchiseUseCase.class);
// ...
}
If CreateFranchiseUseCase
object instanciation by each request is required, you need to add @Scope(WebApplicationContext.SCOPE_REQUEST)
:
@Service
@Scope(WebApplicationContext.SCOPE_REQUEST)
public class CreateFranchiseUseCase {
Upvotes: 3
Reputation: 1
You can inject it like this, but consider injecting service through your controller constructor.
@PostMapping("/api/franchises")
public ResponseEntity<Object> createFranchise(CreateFranchiseDTO dto) {
CreateFranchiseUseCase useCase = new CreateFranchiseUseCase();
Frachise franchise = useCase.execute(dto);
// ...
}
edit: But remember that you have to inject other services to CreateFranchiseUseCase. You can just do this in constructor like that:
public CreateFranchiseUseCase () {
FranchiseService franchiseService = new FranchiseService();
UserService userService = new UserService();
ACLEntryService aclEntryService = new ACLEntryService();
FranchiseDTOMapper franchiseDTOMapper = new FranchiseDTOMapper();
}
or just inject it without constructor like that:
@Service
@RequiredArgsConstructor
public class CreateFranchiseUseCase {
private final FranchiseService franchiseService = new FranchiseService();
private final UserService userService = new UserService();
private final ACLEntryService aclEntryService = new ACLEntryService();
private final FranchiseDTOMapper franchiseDTOMapper = new FranchiseDTOMapper();
public Franchise execute(CreateFranchiseDTO dto) {
// ...
}
}
Upvotes: 0
Reputation: 1641
As far as I know it is not possible to let Spring inject Objects into methods.
Instead you can let Spring inject the object through the constructor of your controller.
This would lead to something like this:
@RestController
public class FranchiseController {
private final CreateFranchiseUseCase createFranchiseUseCase;
public FranchiseController(CreateFranchiseUseCase createFranchiseUseCase) {
this.createFranchiseUseCase = createFranchiseUseCase;
}
@PostMapping("/api/franchises")
public ResponseEntity<Object> createFranchise(CreateFranchiseDTO dto) {
Frachise franchise = createFranchiseUseCase.execute(dto);
// ...
}
}
This should also work even when you use Lombok to create your constructor.
Upvotes: 1