0

I am working on a spring boot service project where we have multiple Spring Service beans which are autowired into each other.

For eg:

@Service
public class Service1

@Autowire
Service2, Service3
.
.
.
@Service
public class Service5
@Autowire
Service 4, Service 1

@Repository
public interface Service1Repository extends JpaRepository<Entity1, UUID>
.
.
.
@Repository
public interface Service5Repository extends JpaRepository<Entity5, UUID>

Most of the service beans are autowired into another service beans, along with auto-wiring their corresponding repository bean with some other beans (ModelMapper, some application context beans) Sometimes this leads to circular dependency problem and other times it fails in code quality check as there are more than 9 beans autowired via constructor injection.

My question is that is there a best practice or design pattern to structure these application spring beans?

chandresh.v
  • 77
  • 12

2 Answers2

0

I can't say exactly as I don't know what these services are exactly doing. But it looks like you had many "Transaction scripts" exposed as services, i.e. you had a top-down procedural type of computations in each service. And at some point the developers saw repetitions in the services, and decided to autowire them between each other.

Service layer is basically there to either act as a transaction script, or wire together domain objects and expose them to controller or to other layers. With that said, there can be services injected in other services, but too much of them and as you said, with cyclic dependencies seem to be a problem.

My best guess is, the project started as a Transaction script, but now it grew to become something that needs a Domain model. Maybe you should try to identify objects that correspond to business logic and can be reused between different services. That should reduce the number of services.

This would be more of an architectural problem than a Design problem.

Can't say much without knowing more about the nature of services.

Mustehssun Iqbal
  • 566
  • 3
  • 19
-1

My suggestions would be as follows:

  • If testability is not your major concern (i.e. enforcing class-level invariants), do not autowire via constructor injection, try using field injection. This helps with the code quality checks.
  • Try grouping your services primarily around models. For instance, do have for the model Person a PersonRepository and a PersonService that only manipulates objects of type Person. Also, only call repository methods from its corresponding service methods.
  • For complex business cases have service classes that are dedicated to the business issue you are solving. For instance, if you're implementing an employee rostering application, have a service for roster generating, another one for informing the employees of their current schedule, another one for exporting to Google Sheets the roster.

Your question does not give details upon what the intent of these services is. It would be beneficial if you assessed whether Strategy, Factory, Builder or Composite design patterns are of help in your case.

Eszter
  • 187
  • 1
  • 2
  • 19
  • 1
    How does field injection "help with code quality checks"? Virtually every source I can find, says field injection should not be used. For example: https://stackoverflow.com/questions/39890849/what-exactly-is-field-injection-and-how-to-avoid-it – RoToRa Jan 22 '21 at 10:31