How to remove Spring CrudRepository unchecked conversion beside using suppress annotation - spring

This is my code :
public interface UserRepo extends CrudRepository<User, Long> {
boolean exist(Long id);
#Override
User save(User user);
}
In eclipse, there is a warning on the return type User.
Description Resource Path Location Type
Type safety: The return type User for save(User) from the type UserRepo needs unchecked conversion to conform to S from the type CrudRepository UserRepo.java
May I know
what is the reason ecplise warning on return type unchecked conversion?
what is the correct way to get rid of the warning?
TQ

As #dunny figured out in his comment, this statement makes no sense in the interface, as it is already implemented in org.springframework.data.repository.CrudRepository.save(S)
Eclipse gives this warning as it can not know, that the S in the super implementation is a User in this case.
In order to answer your 2. question, you can do a
#Override
<S extends User> S save(S user);
Then you get rid of the warning, but even then, it does not make more sense to provide this signature.
Just skip this statement, as it is already there.

Related

targetDomainObject is always null in PermissionEvaluator

I have a CRUD repository from this example of Spring Data. I'm trying to add custom permission evaluation, but in my implementation of PermissionEvalutor, targetDomainObject is always null.
ItemRepository
#PreAuthorize("hasRole('ROLE_USER')")
public interface ItemRepository extends CrudRepository<Item, Long> {
#PreAuthorize("hasPermission(#entity, 'DELETE')")
<S extends Item> S save(S entity);
#PreAuthorize("hasRole('ROLE_ADMIN')")
void delete(Long id);
}
Following the suggestions in the answers to this question of making the interface and implementation parameter names to match, I've tried changing entity by item in both the expression and the method parameter. I'm not sure what implementation should match against what interface here, so I'm guessing is SimpleJpaRepository against ItemRepository/CrudRepository. Anyway, it doesn't work, targetDomainObject is always null. Same for targetId in the other method.
Debugging MethodSecurityEvaluationContext.lookupVariable shows that args.length = 0, inside the method addArgumentsAsVariables(), that then logs Unable to resolve method parameter names for method: public abstract xx.xxx.Item xx.xxx.ItemRepository.save(xx.xxx.Item). Debug symbol information is required if you are using parameter names in expressions.. At lookupVariable, everything is null.
Is the debug symbol not #? What am I doing wrong?
Haven't looked in the actual code, but judging from what you write about the debug information, Spring isn't able to find the parameter names, probably since the come from interfaces and those aren't included in the bytecode by default.
Try adding a -parameters compiler flag. Also see this answer for a probably similar problem: https://stackoverflow.com/a/40787280

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);
}

Return custom-typed object from JpaRepository

I have the following repository:
public interface UserRepository extends BaseDAO<User> {
Collection<User> findByEmail(#Param("email") String email);
#Query("select new com.data.CustomUser(upper(substring(u.lastName, 1, 1)) as initial, count(*)) from User u join u.chats c where c.business=:business group by upper(substring(u.lastName, 1, 1)) order by initial")
List<CustomUser> getContactsIndex(#Param("email") String email);
}
which is exposed with Spring Data REST. The User object is a managed entity, while CustomUser not and as you can see, it's build on-fly by using custom query.
Once I want to call that function, it fails with Persistent entity must not be a null! exception. Is there any way to implement this behavior?
P.S. Expose CustomUser with separate repository is impossible because it is not a managed entity.
One challenge with using Spring Data Rest is when you hit an edge case and you don't know whether you've hit a bug or whether you're just outside the scope of what the library is intended for. In this case I think you are at the edge of what SDR will easily do for you, and it's time to implement your own controller.
Spring Data Rest is looking for an Entity - in your case a User - as the return type for ALL methods in the repository to expose under /entities/search, and breaks when it doesn't find that entity type. The User it wants to serialize isn't there, hence the "Persistent entity must not be null".
The way around this is to write a simple #Controller that has a #RequestMapping for the exact same url exposed by the repository method. This will override the SDR generated implementation for that url, and from that you can return whatever you want.
Your implementation might look something like this:
#Controller
public class CustomUserController {
private final UserRepository repository;
#Inject
public CustomUserController(UserRepository repo) {
repository = repo;
}
#RequestMapping(value = "/users/search/getContactsIndex", method = GET, produces = {MediaType.APPLICATION_JSON_VALUE})
public #ResponseBody List<CustomUser> getContactsIndex(#RequestParam String email) {
return repository.getContactsIndex(email);
}
}
Be aware that there is a "recommended" way to override functionality this way. There is an open issue to document the best way to do this.

HibernateCallback implementation

Consider code
public List<Product> listProducts(){
HibernateCallback callBack=new HibernateCallback(){
public Object doInHibernate(Session session){
Query query=session.createQuery("from Product");
return query.list();
}
};
return (List<Product>)hibernateTemplate.execute(callBack);
}
Is there anything wrong with above code? In eclipse Helios it is showing following error:
The type new HibernateCallback(){} must implement the inherited abstract method HibernateCallback.doInHibernate(Session)
doInHibernate() is implemented then why it showing the above error?
Make sure that Session is org.hibernate.Session, not something else (e.g. org.hibernate.classic.Session).
The pair of org.hibernate.Session and org.hibernate.classic.Session is especially tricky - since the latter interface extends the former one, accidential mistake of this kind doesn't cause other problems and cannot be easily noticed.

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