BAEL-951 Self-Healing Services with Spring Cloud - C1
This commit is contained in:
parent
8746b525d5
commit
c03ca0e998
|
@ -16,5 +16,8 @@ logging.level.org.springframework.security=debug
|
|||
spring.redis.host=localhost
|
||||
spring.redis.port=6379
|
||||
|
||||
cache.redis.hostName=localhost
|
||||
cache.redis.port=6379
|
||||
|
||||
spring.sleuth.sampler.percentage=1.0
|
||||
spring.sleuth.web.skipPattern=(^cleanup.*)
|
||||
|
|
|
@ -1,78 +1,87 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.baeldung.spring.cloud</groupId>
|
||||
<artifactId>svc-rating</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<groupId>com.baeldung.spring.cloud</groupId>
|
||||
<artifactId>svc-rating</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
|
||||
<parent>
|
||||
<artifactId>parent-boot-4</artifactId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../../parent-boot-4</relativePath>
|
||||
</parent>
|
||||
<parent>
|
||||
<artifactId>parent-boot-4</artifactId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../../parent-boot-4</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-config</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-eureka</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-config</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-eureka</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.session</groupId>
|
||||
<artifactId>spring-session</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.session</groupId>
|
||||
<artifactId>spring-session</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-hystrix</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-zipkin</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-zipkin</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>${spring-cloud-dependencies.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<spring-cloud-dependencies.version>Brixton.SR7</spring-cloud-dependencies.version>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>${spring-cloud-dependencies.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<properties>
|
||||
<spring-cloud-dependencies.version>Brixton.SR7</spring-cloud-dependencies.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,30 @@
|
|||
package com.baeldung.spring.cloud.bootstrap.svcrating;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties({CacheProperties.class})
|
||||
public class CacheConfig {
|
||||
|
||||
@Autowired
|
||||
CacheProperties cacheProperties;
|
||||
|
||||
@Bean(name="cacheConnectionFactory")
|
||||
@Qualifier("cacheJedisConnectionFactory")
|
||||
JedisConnectionFactory cacheConnectionFactory() {
|
||||
System.out.println(">>>>>>>>>>>>>>>>>>>>>Qualified Jedis Conn.Name.."+cacheProperties.hostName);
|
||||
System.out.println(">>>>>>>>>>>>>>>>>>>>>Qualified Jedis Conn.Port.."+cacheProperties.port);
|
||||
JedisConnectionFactory factory = new JedisConnectionFactory();
|
||||
factory.setHostName(cacheProperties.hostName);
|
||||
factory.setPort(cacheProperties.port);
|
||||
factory.setUsePool(true);
|
||||
factory.afterPropertiesSet();
|
||||
return factory;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.baeldung.spring.cloud.bootstrap.svcrating;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties(prefix="cache.redis")
|
||||
public class CacheProperties {
|
||||
public String hostName;
|
||||
public int port;
|
||||
|
||||
public String getHostName() {
|
||||
return hostName;
|
||||
}
|
||||
public void setHostName(String hostName) {
|
||||
this.hostName = hostName;
|
||||
}
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,21 +1,25 @@
|
|||
package com.baeldung.spring.cloud.bootstrap.svcrating;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.discovery.EurekaClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
|
||||
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
|
||||
import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
|
||||
import org.springframework.cloud.sleuth.zipkin.HttpZipkinSpanReporter;
|
||||
import org.springframework.cloud.sleuth.zipkin.ZipkinProperties;
|
||||
import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.discovery.EurekaClient;
|
||||
|
||||
import zipkin.Span;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableEurekaClient
|
||||
@EnableHystrix
|
||||
public class RatingServiceApplication {
|
||||
@Autowired
|
||||
private EurekaClient eurekaClient;
|
||||
|
|
|
@ -20,17 +20,21 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.httpBasic()
|
||||
.disable()
|
||||
http
|
||||
.authorizeRequests()
|
||||
.regexMatchers("^/ratings\\?bookId.*$").authenticated()
|
||||
.antMatchers(HttpMethod.POST,"/ratings").authenticated()
|
||||
.antMatchers(HttpMethod.GET,"/ratings/**").authenticated()
|
||||
.antMatchers(HttpMethod.PATCH,"/ratings/*").hasRole("ADMIN")
|
||||
.antMatchers(HttpMethod.DELETE,"/ratings/*").hasRole("ADMIN")
|
||||
.antMatchers(HttpMethod.GET,"/ratings").hasRole("ADMIN")
|
||||
.antMatchers(HttpMethod.GET,"/hystrix*").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.httpBasic().and()
|
||||
.csrf()
|
||||
.disable();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,28 @@
|
|||
package com.baeldung.spring.cloud.bootstrap.svcrating;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
|
||||
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
|
||||
|
||||
@Configuration
|
||||
@EnableRedisHttpSession
|
||||
public class SessionConfig extends AbstractHttpSessionApplicationInitializer {
|
||||
@Autowired
|
||||
Environment properties;
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public JedisConnectionFactory connectionFactory() {
|
||||
JedisConnectionFactory factory = new JedisConnectionFactory();
|
||||
factory.setHostName(properties.getProperty("spring.redis.host","localhost"));
|
||||
factory.setPort(properties.getProperty("spring.redis.port", Integer.TYPE,6379));
|
||||
factory.afterPropertiesSet();
|
||||
factory.setUsePool(true);
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,34 @@
|
|||
package com.baeldung.spring.cloud.bootstrap.svcrating.rating;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
@Entity
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Rating {
|
||||
public class Rating implements Serializable{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 3308900941650386473L;
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
private Long bookId;
|
||||
private int stars;
|
||||
|
||||
@Transient
|
||||
private boolean fromCache;
|
||||
@Transient
|
||||
private Long cachedTS=-1L;
|
||||
|
||||
public Rating() {
|
||||
}
|
||||
|
||||
|
@ -54,4 +66,40 @@ public class Rating {
|
|||
public void setStars(int stars) {
|
||||
this.stars = stars;
|
||||
}
|
||||
|
||||
public boolean isFromCache() {
|
||||
return fromCache;
|
||||
}
|
||||
|
||||
public void setFromCache(boolean fromCache) {
|
||||
this.fromCache = fromCache;
|
||||
}
|
||||
|
||||
public Long getCachedTS() {
|
||||
return cachedTS;
|
||||
}
|
||||
|
||||
public void setCachedTS(Long cachedTS) {
|
||||
this.cachedTS = cachedTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Rating [" + id + "," + bookId + "," + stars + "," + cachedTS + "]";
|
||||
}
|
||||
|
||||
public static Rating fromString(String ratingAsStr){
|
||||
|
||||
if(ratingAsStr == null || ratingAsStr.isEmpty())
|
||||
return null;
|
||||
String[] attributeVals=ratingAsStr.substring(8,ratingAsStr.length()-1).split("[,]");
|
||||
|
||||
Rating rating=new Rating();
|
||||
rating.setId(Long.valueOf(attributeVals[0]));
|
||||
rating.setBookId(Long.valueOf(attributeVals[1]));
|
||||
rating.setStars(Integer.valueOf(attributeVals[2]));
|
||||
rating.setCachedTS(Long.valueOf(attributeVals[3]));
|
||||
|
||||
return rating;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.spring.cloud.bootstrap.svcrating.rating;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface RatingCacheRepository {
|
||||
|
||||
List<Rating> findCachedRatingsByBookId(Long bookId);
|
||||
Rating findCachedRatingById(Long ratingId);
|
||||
List<Rating> findAllCachedRatings();
|
||||
boolean createRating(Rating persisted);
|
||||
boolean updateRating(Rating persisted);
|
||||
boolean deleteRating(Long ratingId);
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package com.baeldung.spring.cloud.bootstrap.svcrating.rating;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.SetOperations;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.data.redis.core.ValueOperations;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public class RatingCacheRepositoryImpl implements InitializingBean, RatingCacheRepository {
|
||||
|
||||
|
||||
@Autowired
|
||||
@Qualifier("cacheJedisConnectionFactory")
|
||||
private JedisConnectionFactory cacheConnectionFactory;
|
||||
|
||||
private StringRedisTemplate redisTemplate;
|
||||
private ValueOperations<String,String> valueOps;
|
||||
private SetOperations<String,String> setOps;
|
||||
|
||||
|
||||
public List<Rating> findCachedRatingsByBookId(Long bookId){
|
||||
return setOps.members("book-" + bookId)
|
||||
.stream()
|
||||
.map(rtId -> Rating.fromString(valueOps.get(rtId)))
|
||||
.map(rt -> {
|
||||
rt.setFromCache(true);
|
||||
return rt;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public Rating findCachedRatingById(Long ratingId) {
|
||||
return Rating.fromString(valueOps.get("rating-" + ratingId));
|
||||
}
|
||||
|
||||
public List<Rating> findAllCachedRatings(){
|
||||
return redisTemplate.keys("rating*")
|
||||
.stream()
|
||||
.map(rtId -> Rating.fromString(valueOps.get(rtId)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public boolean createRating(Rating persisted){
|
||||
valueOps.set("rating-"+persisted.getId(), persisted.toString());
|
||||
setOps.add("book-"+persisted.getBookId(), "rating-"+persisted.getId());
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean updateRating(Rating persisted){
|
||||
valueOps.set("rating-"+persisted.getId(), persisted.toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean deleteRating(Long ratingId){
|
||||
Rating toDel=Rating.fromString(valueOps.get("rating-"+ratingId));
|
||||
setOps.remove("book-"+toDel.getBookId(), "rating-"+ratingId);
|
||||
redisTemplate.delete("rating-"+ratingId);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
this.redisTemplate = new StringRedisTemplate(cacheConnectionFactory);
|
||||
|
||||
this.valueOps = redisTemplate.opsForValue();
|
||||
this.setOps=redisTemplate.opsForSet();
|
||||
|
||||
}
|
||||
}
|
|
@ -1,46 +1,80 @@
|
|||
package com.baeldung.spring.cloud.bootstrap.svcrating.rating;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
|
||||
|
||||
@Service
|
||||
@Transactional(readOnly = true)
|
||||
public class RatingService {
|
||||
public class RatingService{
|
||||
|
||||
@Autowired
|
||||
private RatingRepository ratingRepository;
|
||||
|
||||
@Autowired
|
||||
private RatingCacheRepository cacheRepository;
|
||||
|
||||
|
||||
@HystrixCommand(commandKey="ratingsByBookIdFromDB",fallbackMethod="findCachedRatingsByBookId")
|
||||
public List<Rating> findRatingsByBookId(Long bookId) {
|
||||
if(bookId==2)
|
||||
throw new IllegalArgumentException("BookID 2 redirects to cache");
|
||||
|
||||
return ratingRepository.findRatingsByBookId(bookId);
|
||||
}
|
||||
|
||||
@HystrixCommand(commandKey="ratingsByBookIdFromCache",fallbackMethod="defaultRatingsByBookId")
|
||||
public List<Rating> findCachedRatingsByBookId(Long bookId){
|
||||
return cacheRepository.findCachedRatingsByBookId(bookId);
|
||||
}
|
||||
|
||||
public List<Rating> defaultRatingsByBookId(Long bookId){
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
@HystrixCommand(commandKey="ratingsFromDB",fallbackMethod="findAllCachedRatings")
|
||||
public List<Rating> findAllRatings() {
|
||||
return ratingRepository.findAll();
|
||||
}
|
||||
|
||||
public List<Rating> findAllCachedRatings(){
|
||||
return cacheRepository.findAllCachedRatings();
|
||||
}
|
||||
|
||||
@HystrixCommand(commandKey = "ratingsByIdFromDB", fallbackMethod = "findCachedRatingById", ignoreExceptions = { RatingNotFoundException.class })
|
||||
public Rating findRatingById(Long ratingId) {
|
||||
return Optional.ofNullable(ratingRepository.findOne(ratingId))
|
||||
.orElseThrow(() -> new RatingNotFoundException("Rating not found. ID: " + ratingId));
|
||||
}
|
||||
|
||||
public List<Rating> findRatingsByBookId(Long bookId) {
|
||||
return ratingRepository.findRatingsByBookId(bookId);
|
||||
}
|
||||
|
||||
public List<Rating> findAllRatings() {
|
||||
return ratingRepository.findAll();
|
||||
public Rating findCachedRatingById(Long ratingId){
|
||||
return cacheRepository.findCachedRatingById(ratingId);
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
public Rating createRating(Rating rating) {
|
||||
final Rating newRating = new Rating();
|
||||
Rating newRating = new Rating();
|
||||
newRating.setBookId(rating.getBookId());
|
||||
newRating.setStars(rating.getStars());
|
||||
return ratingRepository.save(newRating);
|
||||
Rating persisted=ratingRepository.save(newRating);
|
||||
cacheRepository.createRating(persisted);
|
||||
return persisted;
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
public void deleteRating(Long ratingId) {
|
||||
ratingRepository.delete(ratingId);
|
||||
cacheRepository.deleteRating(ratingId);
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
|
@ -54,7 +88,9 @@ public class RatingService {
|
|||
break;
|
||||
}
|
||||
});
|
||||
return ratingRepository.save(rating);
|
||||
Rating persisted= ratingRepository.save(rating);
|
||||
cacheRepository.updateRating(persisted);
|
||||
return persisted;
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
|
@ -64,4 +100,5 @@ public class RatingService {
|
|||
Preconditions.checkNotNull(ratingRepository.findOne(ratingId));
|
||||
return ratingRepository.save(rating);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue