Which dependency injection is appropriate in the MVC pattern? - spring-boot

Let me explain the situation with an example.
Currently, there are teams and members as Models.
class Member {
String name;
Team team;
}
class Team {
String teamName;
}
There is a MemberRepository that can access the Member database.
public interface MemberRepository {
public Member findByName(String name);
}
MemberService that can inquire Member exists.
#Service
Memberservice {
#Autowired
MemberRepository memberRepository;
public Member searchMember(String name) {
return memberRepository.findByName(name);
}
}
In this situation, When creating TeamService
If you need to inquire about members , Which one is better to inject, Memberservice or MemberRepository?

Following the single responsibility principle, you should strive to keep your classes focused on doing a few and related things. With this in mind, MemberService should be the only one managing Members and this includes being the only one that touches MemberRepository. Having said this you should definitely inject MemberService.
As a general rule of thumb, you should avoid multiple Services using the same Repository. If you fail to do so you might end up with spaghetti code. This means that Services should "communicate" between them.

Related

How to use #Autowired in an class annotated with #Entity?

I have an entity called TimeBooking. When I request this entity and return to the client I want to get a list of ActivityTimeBookings from a repository. But when the function get called the repo is null.
So I tried to #Autowired the repo and marked it as transient and also said Spring that there is a dependency which should be injected.
#Configurable(preConstruction = true)
#Entity
public class TimeBooking extends BaseEntity{
#Autowired
private transient ActivityTimeBookingRepository activityTimeBookingRepository;
...
#JsonProperty("activityTimeBookings")
private List<ActivityTimeBooking> activityTimeBookings() {
return this.activityTimeBookingRepository.findByDate(this.timeFrom);
}
}
Any suggestions?
Using #Autowired in a class annotated with #Entity is a bad practice.
The solution is given below :
1. Create a service interface :
public interface TimeBookingService {
public List<ActivityTimeBooking> activityTimeBookings();
}
2. Create an implementation of the service interface :
#Service
public class TimeBookingServiceImpl implements TimeBookingService {
#Autowired
private ActivityTimeBookingRepository activityTimeBookingRepository;
public List<ActivityTimeBooking> activityTimeBookings() {
return this.activityTimeBookingRepository.findByDate(this.timeFrom);
}
}
Usually its indeed a bad practice to inject something into JPA entities.
These are usually created by JPA implementation (like Hibernate) and spring as a DI framework doesn't really participate in this process.
Note, that there can be many instances of this class created as a result of query, so if you later use this for serialization of the list of this object you might end up running N queries to the database given N entities like this were retrieved.
Answering your question about "getting access to the repo" I believe you should consider refactoring:
In the service class (assuming you have a "regular" contoller, service and dao):
you can:
class MyService {
SomeResult.. doSomething() {
List<TimeBooking> allTimeBookings = dao.getAllTimeBooking();
LocalDateTime timeFrom = calculateTimeFrom(allTimeBookings);
List<ActivityTimeBooking> allActivityTimeBookings = dao.findByDate(timeFrom);
return calculateResults(allTimeBookings, allActivityTimeBooking);
}
}
class MyDao {
List<ActivityTimeBooking> findByDate(LocalDateTime timeFrom) {...}
List<TimeBooking> getAllTimeBookings() {...}
}
Regarding the service implementation, I've assumed this use case can't be covered by usual "JOIN between two tables" so that that creating an association between TimeBooking and ActivityTimeBooking is not an option.
Note 2, I've used one repository (dao) for brevity, in real application you might want to inject two different repositories into the service.

Repository pattern in MVC: controller code explanation

What is the purpose of SudentRepository in this example? Why do I need one?
public class StudentController : Controller
{
private IStudentRepository _repository;
public StudentController() : this(new StudentRepository())
{
}
public StudentController(IStudentRepository repository)
{
_repository = repository;
}
I updated to actually include a specific question that I think you're getting at. The purpose of StudentRepository is to encapsulate interactions with persisted data. The Controller need not know if its stored in a db, flat file, in memory, etc.
The reason you're injecting it in via an interface is because you may eventually have multiple implementations of that repository, and the interface is just a contract to ensure basic functionality across all implementations. This is called constructor injection (a type of dependency injection) in case you want to learn more.

How to decouple repository and entities

This is a question on domain model design.
Let's say for a domain design involving users and groups, we have the following interfaces to implement:
interface IUser
{
string Name{get;}
DateTime DOB {get;}
}
interface IGroup
{
string Name {get;}
bool IsUserInGroup(IUser user); // #1
void IncludeUser(IUser user); // #2
void ExcludeUser(IUser user); // #3
}
interface IUserRepository
{
IUser Create(string name);
IUser GetByName(string name);
void Remove(IUser user);
void Save(IUser user);
}
interface IGroupRepository
{
IGroup Create(string name);
IGroup GetByName(string name);
void Remove(IGroup group);
void Save(IGroup group);
}
The tricky bit is to implement #1 #2 and #3 while keeping the entity classes (User, Group) decoupled from the repository classes (UserRepository, GroupRepository.)
Another technicality to consider is that most RMDB systems do not implement many-to-many relationships, and in practice there is always a separate table (say, UserGroupAssociation) to have records each associates a user and a group via foreign keys. I would like to hide this implementation detail from the domain interfaces and expose the equivalent logic through members #1 #2 and #3.
The effect of calling #2 and #3 should not persist until the group object in question has been saved (i.e. passed to the Save() method of the repository object)
How do you usually do it?
I don't do it. My Repository objects are tightly coupled to the root of the aggregate to which they relate, and (as kind of an aside) I don't bother making interfaces for my domain model objects unless I find I have a good reason to do so - do you have a particular reason to do this?
I've not come across any Repository examples which don't use the entity implementation type in the repository class (this one, for instance) and can't think of any real advantage of using an interface instead. Interfaces earn their keep for infrastructure components (like a Repository) by making it easier to mock out entire layers of the system when testing, you don't get the same type of advantage using interfaces for domain objects.
And to perhaps actually answer the question...
I never have a domain object access a Repository - the domain object after all is supposed to represent something in the domain in real life, and Repositories are infrastructure components that don't exist in real life, so why would a domain object know about one?
For the specific example of adding a User to a Group, I'd use a Service Layer class, and do this:
public class UserService
{
private readonly IGroupRepository _groupRepository;
private readonly IUserRepository _userRepository;
public UserService(
IGroupRepository groupRepository,
IUserRepository userRepository)
{
this._groupRepository = groupRepository;
this._userRepository = userRepository;
}
public void IncludeUserInGroup(string groupName, string userName)
{
var group = this._groupRepository.FindByName(groupName);
var user = this._userRepository.FindByName(userName);
group.IncludeUser(user);
this._userRepository.SaveChanges();
}
}
public class User
{
public void AddToGroup(Group group)
{
this.Groups.Add(group);
}
public void RemoveFromGroup(Group group)
{
this.Groups.Remove(group);
}
}
Some points to note:
To avoid lazy-loading large numbers of Users when adding a User to a Group I've moved the Group administration methods onto User - depending on how much behaviour you actually have for Group, you might even consider turning it into an enumeration rather than a class. Be aware that if you're using the Entity Framework POCO T4 Templates with FixupCollections, this will still lazy-load all the Users in a Group, but you can get around that in one way or another :)
The Service Layer class would implement a Create() method, the like of which you have on your Repositories. The Repositories would have an Add method, Find methods and a SaveChanges() method. Add would add an object created by the Service Layer to the object context.
All Repository classes would be set up to use the same underlying, request-scoped object context, so it wouldn't matter which one you call SaveChanges() on.
SaveChanges() would cause all changes which had happened to objects during that request to be saved, such as a User having a new Group's added to their Groups collection.
Finally, another good technique for decoupling entities from Repositories and other infrastructure components is Domain Events.

Dependency Injection with Interface implemented by multiple classes

Update: Is there a way to achieve what I'm trying to do in an IoC framework other than Windsor? Windsor will handle the controllers fine but won't resolve anything else. I'm sure it's my fault but I'm following the tutorial verbatim and objects are not resolving with ctor injection, they are still null despite doing the registers and resolves. I've since scrapped my DI code and have manual injection for now because the project is time sensitive. Hoping to get DI worked out before deadline.
I have a solution that has multiple classes that all implement the same interface
As a simple example, the Interface
public interface IMyInterface {
string GetString();
int GetInt();
...
}
The concrete classes
public class MyClassOne : IMyInterface {
public string GetString() {
....
}
public int GetInt() {
....
}
}
public class MyClassTwo : IMyInterface {
public string GetString() {
....
}
public int GetInt() {
....
}
}
Now these classes will be injected where needed into layers above them like:
public class HomeController {
private readonly IMyInterface myInterface;
public HomeController() {}
public HomeController(IMyInterface _myInterface) {
myInterface = _myInterface
}
...
}
public class OtherController {
private readonly IMyInterface myInterface;
public OtherController() {}
public OtherController(IMyInterface _myInterface) {
myInterface = _myInterface
}
...
}
Both controllers are getting injected with the same interface.
When it comes to resolving these interfaces with the proper concrete class in my IoC, how do I differentiate that HomeController needs an instance of MyClassOne and OtherController needs an instance of MyClassTwo?
How do I bind two different concrete classes to the same interface in the IoC? I don't want to create 2 different interfaces as that breaks the DRY rule and doesn't make sense anyway.
In Castle Windsor I would have 2 lines like this:
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassOne>());
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassTwo>());
This won't work because I will only ever get a copy of MyClassTwo because it's the last one registered for the interface.
Like I said, I don't get how I can do it without creating specific interfaces for each concrete, doing that breaks not only DRY rules but basic OOP as well. How do I achieve this?
Update based on Mark Polsen's answer
Here is my current IoC, where would the .Resolve statements go? I don' see anything in the Windsor docs
public class Dependency : IDependency {
private readonly WindsorContainer container = new WindsorContainer();
private IDependency() {
}
public IDependency AddWeb() {
...
container.Register(Component.For<IListItemRepository>().ImplementedBy<ProgramTypeRepository>().Named("ProgramTypeList"));
container.Register(Component.For<IListItemRepository>().ImplementedBy<IndexTypeRepository>().Named("IndexTypeList"));
return this;
}
public static IDependency Start() {
return new IDependency();
}
}
I hope you can use service overrides.
Ex.
container.Register(
Component.For<IMyService>()
.ImplementedBy<MyServiceImpl>()
.Named("myservice.default"),
Component.For<IMyService>()
.ImplementedBy<OtherServiceImpl>()
.Named("myservice.alternative"),
Component.For<ProductController>()
.ServiceOverrides(ServiceOverride.ForKey("myService").Eq("myservice.alternative"))
);
public class ProductController
{
// Will get a OtherServiceImpl for myService.
// MyServiceImpl would be given without the service override.
public ProductController(IMyService myService)
{
}
}
You should be able to accomplish it with named component registration.
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassOne>().Named("One"));
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassTwo>().Named("Two"));
and then resolve them with
kernel.Resolve<IMyInterface>("One");
or
kernel.Resolve<IMyInterface>("Two");
See: To specify a name for the component
Typically DI containers follow Register, Resolve and Release patterns. During the register phase there are two steps. The first is to specify the mapping as you are doing. The second step is to specify the rules which govern which to inject where.
This problem is very common when we try to address Cross cutting concerns using decorators. In these situations, you have multiple classes(decorators) implementing a single interface.
Briefly, we need to implement IModelInterceptorsSelector which allows you to write imperative code that decides which Interceptor to apply to which types or members.
This is elaborately described in the book Dependency Injection in .Net book by Mark Seemann. Look for chapter 9 interception or search for the above interface.
I am not an expert at this, but was searching for the exact same problem and found the ans in the above book.
Hope this helps.
Regards
Dev1

Law of Demeter and DAO pattern

Here's a method in my Spring/Hibernate website's code that exemplifies my codebase:
public class UserVoteServiceImpl implements UserVoteService {
#Autowired UserRepository userRepository;
public static int getUserScore(long userId) {
return userRepository.findUserById(userId).getScore();
}
}
I believe that this method violates the Law of Demeter, since it is making calls on the object returned by findUserById(). How can I change this code to obey the Principle of Least Knowledge?
I don't think it's a violation of the Law of Demeter. It would be a violation if you were passing in some object, getting userId off of it, and using only the userid.
Here's an example that would be a violation:
public class UserVoteServiceImpl implements UserVoteService {
#Autowired UserRepository userRepository;
public static int getUserScore(SomeWrapper someWrapper) {
return userRepository.findUserById(someWrapper.getUserId()).getScore();
}
}
But there's nothing wrong with delegating work within the implementation of your method, and there's nothing wrong with making a call on the object returned from the repository.
(Personally I'm not crazy about using services to wrap single dao calls, but that's a different problem.)
Currently I'm working on a codebase perpetrated by people who apparently never heard of LoD, full of stuff like
public Thing getThing(Integer id) {
return new Beta().getGamma().getDelta().getEpsilon().getOmega().getThing(id);
}
and initially I thought your example didn't rise to the same level of pathology as that. But after reading this blog post, which is where I got the above example, of course,
I think I'd recommend you changing your method to
public class UserVoteServiceImpl implements UserVoteService {
#Autowired UserRepository userRepository;
public User getUser(Long userId) {
return userRepository.findUserById(userId);
}
}
and letting the caller pull the score off the User. This change also has the benefit of having the application's service interface deal in domain objects, not in primitives.

Resources