Using Service to encapsulate business logic 

It is a good practice to encapsulate business logic inside Service methods so that controllers and repositories are loosely coupled. The following is a Service written to encapsulate the business logic for Tweet:

@Service
@Transactional(readOnly = true)
public class TweetService {

private final TweetRepository tweetRepository;
private final Scheduler dbScheduler;

public TweetService(TweetRepository tweetRepository, Scheduler
dbScheduler) {
this.tweetRepository = tweetRepository;
this.dbScheduler = dbScheduler;
}

@Transactional(rollbackFor = Exception.class)
public Mono<Tweet> save(Tweet tweet) {
return Mono.fromCallable(() ->
tweetRepository.save(tweet)).publishOn(dbScheduler);
}

public Flux<Tweet> getTweets() {
return Flux.fromIterable(tweetRepository.findAll()).
publishOn(dbScheduler);
}

public Flux<Tweet> getRelevantTweets(String screenName) {
return Flux.fromIterable(tweetRepository.
findByTweetUser_ScreenNameOrContentContains(screenName,
"@"+screenName)).publishOn(dbScheduler);
}
}

The save method saves Tweet in the database. The getTweets method retrieves all Tweets from the database. getRelevantTweets will retrieve tweets intended for a user identified by a particular screenName.

 The following is the Service written to encapsulate the business logic for the User:

@Service
@Transactional(readOnly = true)
public class UserService implements UserDetailsService {

private final UserRepository userRepository;
private final Scheduler dbScheduler;

public UserService(UserRepository userRepository, Scheduler
dbScheduler) {
this.userRepository = userRepository;
this.dbScheduler = dbScheduler;
}

@Transactional(rollbackFor = Exception.class)
public Mono<User> save(User user) {
return Mono.fromCallable(() ->
userRepository.save(user)).publishOn(dbScheduler);
}

public Mono<User> getUserByScreenName(String screeName) {
return Mono.fromCallable(() ->
userRepository.findByScreenName(screeName)).
publishOn(dbScheduler);
}

public Mono<User> getByUserId(String userId) {
return Mono.fromCallable(() ->
userRepository.findById(userId).get()).
publishOn(dbScheduler);
}

@Override
public UserDetails loadUserByUsername(String screename) throws
UsernameNotFoundException {
User user = userRepository.findByScreenName(screename);

if (user == null) {
throw new UsernameNotFoundException(screename);
}

return new org.springframework.security.core.
userdetails.User(user.getScreenName(), user.getPassword(),
Arrays.asList(new SimpleGrantedAuthority
(user.getRole().toString())));
}
}

The save method saves the User in the database. The getUserByScreenName method retrieves a user by the screenName. The getUserById method retrieves a user by ID. The UserDetailsService.loadUserByUsername method is implemented in this service as well, to support Spring Security.

In these services, the DbConfig.dbScheduler bean is used to delegate the execution of synchronous tasks asynchronously, using a thread pool. The Mono and Flux constructs have a publishOn method, which can be used to achieve this delegation.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.100.120