Law of Demeter and DAO pattern - spring

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.

Related

Which dependency injection is appropriate in the MVC pattern?

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.

Autowiring interface vs class

If there are more than one implementation of an interface, then I would have to use #Qualifier to indicate which class I want to autowire with. Wouldn't it make more sense to autowire the class directly instead of interface?
This is what object oriented programming (especially abstraction and polymorphism) is about.
You build the classes independendent of concrete implementations and use an interface.
This allows you to change what implementation you use at any point.
Assume you have this:
public interface I{
void doSomething();
}
#Component("a")
public class A implements I{
public void doSomething(){
//...
}
public void doSomethingElse(){
//...
}
}
#Component("b")
public class B implements I{
public void doSomething(){
//...
}
}
If you use
#Autowired
private A yourVariable;
you might be tempted to use the doSomethingElse() method that is an implementation detail (by what reason whatsoever).
However, if you use
#Qualifier("a")
private I yourVariable;
this cannot happen as the method is not present in the interface.
This gives you the ability to swap the implementation at any time.
Wouldn't it make more sense to autowire the class directly instead of interface?
This pretty much depends on how exactly do you work with qualifiers but in general, the answer is "No", autowiring the class is a bad thing to do if you have an interface - you should always work by interface.
Here are the examples:
interface I { void foo(); }
class IImpl1 implements I {
void foo() {System.out.println("Impl1");
pubic void bar() {// another method - why not?}
}
class IImpl2 implements I { void foo() {System.out.println("Impl2"); }
Note, that an implementation IImpl1 has an additional method bar that doesn't belong to the interface I
Case 1:
#Component
public class Driver {
#Autowired
private IImpl1 i;
}
Here class Driver is tightly could to the concrete implementation IImpl1 in general I can call method bar from the Driver class because I have this implementation, but in this case if I'll have to switch the implementation of Driver in future you'll have to also change the code: both change the reference, and also get rid of calls to IImpl1.bar() that might be not that easy to do - its a change in logic. As a result, the whole polymorphic behavior is lost.
By far its the worst way to program.
Now, consider Case 2:
#Component
public class Driver {
#Autowired
#Qualifier("someLogicalName") // under the hood it spring will map it to IImpl1 but you don't know that here
I i;
}
In this case - the things are much better - you never couple the driver to the concrete implementation at the level of code. This means that in general its enough to change the qualifier to get another implementation. You can't call bar anymore - it won't compile.
You also do not know what the implementation will be injected. If in future the implementation of the component that actually implements the logic of "someLogicalName" will change (by that I mean that you'll create a new class IImpl3), you won't feel it here - you'll place that qualifier on that new class and all the places that use it will get that implementation automatically.
Case 3:
#Configuration
public class MyConfiguration {
#Bean
public Driver driver(#Qualifier("someLogicalName") I i) {
return new Driver(i);
}
}
public class Driver {
private final I i;
public Driver(I i) { // in real life this constructor can be generated by
// lombok or something, put it here for the sake of completeness
this.i = i;
}
}
This by far the most "clean" approach - conceptually its really similar to case 2, however in this case you don't place the qualifier at the level of Driver class at all, in fact, the class Driver is not even aware at the level of code / metadata that its related to Spring anyhow. Of course all the "advantages" of case 2 are also applicable here as well.

How to code custom validator on WebFlux that uses a reactive datasource

In Spring MVC, I had a #UniqueEmail custom hibernate validator (to check for uniqueness of email when signup), which looked as below:
public class UniqueEmailValidator
implements ConstraintValidator<UniqueEmail, String> {
private UserRepository userRepository;
public UniqueEmailValidator(UserRepository userRepository) {
this.userRepository = userRepository;
}
#Override
public boolean isValid(String email, ConstraintValidatorContext context) {
return !userRepository.findByEmail(email).isPresent();
}
}
Now I'm migrating to WebFlux with reactive MongoDB, with my code as below:
public class UniqueEmailValidator
implements ConstraintValidator<UniqueEmail, String> {
private MongoUserRepository userRepository;
public UniqueEmailValidator(MongoUserRepository userRepository) {
this.userRepository = userRepository;
}
#Override
public boolean isValid(String email, ConstraintValidatorContext context) {
return userRepository.findByEmail(email).block() == null;
}
}
First of all, using block as above doesn't look good. Secondly, it's not working, and here is the error:
Caused by: java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-3
How to go about this? I can of course use a MongoTemplate blocking method, but is there a way to handle this reactively? I could do it manually in the service method, but I wished this error to be shown to the user along with other errors (e.g. "short" password).
As of Reactor 3.2.0, using blocking APIs inside a parallel or single Scheduler is forbidden and throws the exception you're seeing. So you got that right when you said it doesn't look good - not only it's really bad for your application (it might block the processing of new requests and crash the whole thing down), but it was so bad that the Reactor team decided to consider that as an error.
Now the problem is you'd like to do some I/O related work within a isValid call. THe complete signature of that method is:
boolean isValid(T value, ConstraintValidatorContext context)
The signature shows that it's blocking (it doesn't return a reactive type, nor provides the result as a callback). So you're not allowed to do I/O related or latency involved work in there. Here you'd like to check an entry against the database, which exactly falls into that category.
I don't think you can do that as part of this validation contract and I'm not aware of any alternative to that.
I had the same problem and finally I decided to check simple validations with ConstraintValidator and to check reactive validations in the application logic which is reactive. I don't know if there is other better solution, but it could be a good approach.

Spring HATEOAS custom controller - enable converting URI to entity

This is an example of what I would like to achieve:
#RepositoryRestController
#RequestMapping("/users")
public class UserController {
#Autowired
private UserRepository userRepository;
#Autowired
private TaskRepository taskRepository;
#PostMapping("/addCompletedTask")
public void addCompletedTask(User user, Task task) {
user.getCompletedTasks().add(task);
task.incrementCompletedBy();
userRepository.save(user);
taskRepository.save(task);
}
}
Then I would make a request like this:
POST http://localhost:8080/api/users/addCompletedTask
{
"user": "http://localhost:8080/api/db/users/59fa19bfd58dcf25e82082b2",
"task": "http://localhost:8080/api/db/tasks/59fa19bfd58dcf22d2322312"
}
I tried to wrap arguments to the method with Resource<User>, add #RequestBody, nothing works, everything is null.
I don't know if it's possible, but I've seen examples of people writing code like this, so maybe I'm missing something (here for example). Or maybe is there some way to do that through the repository in one call? I can add a task in one call, and increment counter in another, but that requires two calls from the client. Also I'm pretty sure I will encounter another situation similiar to this, so if there is a solution that would be great.

What should be returned from Spring #Service when User was not found?

As the title says, I have some repository like:
public UserRepository{
public Optional<User> findByUsername(String username){..logic..}
}
and Service:
public UserService {
#Autowired
private UserRepository userRepository;
public Optional<User> findByUsername(String username){ ..calling repository.. }
}
And in my #Controller class I want to obtain User instance from the UserService
But I have no idea what should be returned from #Service - Optional and check if it isPresent() inside controller, or just simply null? I am confused..
I am trying to move so many logic into #Service layer as I can, so checking optional may seem not good idea.
Thanks!
Ideally what you should do is throw an Exception. This is the best practice to do so. However you can also stick with null if you want but an exception clearly states what is the problem and is very maintainable and dubuggable at later stages.
you might like to do something like this
findByUsername(String username){
// find user
if(user !=null){
return User
}
else
throw new UserNotFoundException();
}
Follow this link for how to create custom exceptions.
http://techekiras.blogspot.in/2015/02/how-to-create-custom-exception-in-java.html
and this for how to handle these
http://www.ekiras.com/2015/02/how-to-create-nested-custom-exceptions-in-java.html
Catch these exceptions on your controller to take further actions.
In Java 8 there is a new possibility. To make the service to return an Optional. It is a good way to make explicit in the signature that it may return a null. You will be forced to check if it is Null but can be very helpfull to avoid the famous NullPointerException
import java.util.Optional;
[...]
public Optional<User> getUser(String userName){
User user = userDAO.getByUsername(username);
return Optional.of(user);
}

Resources