MichaelB
MichaelB

Reputation: 1132

Spring Boot program structure for access to data objects

I have an spring boot app that has a mongo repository and is using spring data to connect to it. This means there's an "entity" class and then a "repository" class.

However, to actually use the repository I need spring to @Autowire my repo to a variable inside another class (we'll call it X) that might want to use it. But if the X class is itself not a spring bean, it's just a regular pojo created by "new X" somewhere then it can't make use of Autowiring and therefore cant use the repo.

This seems like a show stopper... No one could ever make use of a repo outside of some very specific situations like calling the repo directly from your RestController or whatever without any intervening logic. Yet I am sure people are using this.

So my question is how to structure code so that it can be used? Do I need to do a bunch of processing and then return back up to the controller to interact with the databases? Is there a way to create some kind of other "intermediate helper bean" to mediate the connection? What should that look like?

disclaimer: I am fairly new to spring

Upvotes: 1

Views: 328

Answers (2)

riddle_me_this
riddle_me_this

Reputation: 9145

Perhaps I can post some excerpts that can clarify your situation.

//nothing spring specific
public class MyPojo {
  //properties
}

in a different package:

@Repository
public class MyRepositoryImpl implements MyRepository {
    //CRUD implementation or whatever
}

in a different package:

@Service
public class MyServiceImpl implements MyService {

    @Autowired //constructor-injection
    public MyService(MyRepository myRepository) {
        this.myRepository = myRepository;
    }

    private final MyRepository myRepository;

    public void myBusinessLogic() {
        MyPojo pojo = new MyPojo(); //not dependent on Spring
        myRepository.doSomething();
        //place calls to X here as needed
    }
}

And finally:

@Controller
public class MyController {

    @Autowired
    public MyController(MyService myService) {
        this.myService = myService;
    }

    private final MyService myService;

    @GetMapping("/myPage")
    public String doIt() {
       myService.myBusinessLogic();
       return "myPage";
    }  
}

Where MyRepository and MyService are interfaces that would contain the contract for their respective implementations.

Single Responsibility Principle

A major point to note is that your POJO isn't going to "use the repo" as you mention in your question. It represents an entity and shouldn't care about any specific repository. And this seems related to your issue - a POJO shouldn't be making calls to a repository (your "X" class in this case). Seems like the design should be revisited if that is the case.

Upvotes: 1

Mr. Wrong
Mr. Wrong

Reputation: 510

As you say, you can only autowire fields in objects that themselves are autowired. This is inherent to bean injection. You should annotate X with for instance @Component and inject it where you need it.

Upvotes: 1

Related Questions