Commit 22b36c7a authored by Benjamin Wilms's avatar Benjamin Wilms

add distributed cache example

parent c22f87d3
<?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>
<groupId>de.codecentric.resilience</groupId>
<artifactId>distributed-cache</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<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-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.8-dmr</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package de.codecentric.resilience.redis;
/**
* @author Benjamin Wilms
*/
import de.codecentric.resilience.redis.domain.User;
import de.codecentric.resilience.redis.service.UserService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@EnableCaching
@SpringBootApplication
public class UserServiceApplication implements CommandLineRunner{
protected final Log logger = LogFactory.getLog(getClass());
@Autowired
private UserService userService;
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
@Override
public void run(String... strings) throws Exception {
User user = new User("Bob","Miller");
User user1 = userService.createUser(user);
logger.info(user1);
}
}
\ No newline at end of file
package de.codecentric.resilience.redis.domain;
/**
* @author Benjamin Wilms
*/
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.io.Serializable;
import java.util.UUID;
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
@Id
private String id = UUID.randomUUID().toString();
private String firstName, lastName;
public User(String firstName, String lastName) {
id = UUID.randomUUID().toString();
this.firstName = firstName;
this.lastName = lastName;
}
}
\ No newline at end of file
package de.codecentric.resilience.redis.domain;
/**
* @author Benjamin Wilms
*/
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, String> {
}
\ No newline at end of file
package de.codecentric.resilience.redis.rest;
/**
* @author Benjamin Wilms
*/
import de.codecentric.resilience.redis.domain.User;
import de.codecentric.resilience.redis.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import java.util.Optional;
@RestController
@RequestMapping("/users")
class UserRestController {
private final UserService userService;
@Autowired
UserRestController(UserService userService) {
this.userService = userService;
}
@PostMapping
ResponseEntity create(@RequestBody User user) {
Assert.notNull(user);
return Optional.ofNullable(userService.createUser(user))
.map(result -> new ResponseEntity<>(result, HttpStatus.CREATED))
.orElse(new ResponseEntity<>(HttpStatus.CONFLICT));
}
@GetMapping("/{id}")
ResponseEntity<User> get(@PathVariable String id) {
return Optional.ofNullable(userService.getUser(id))
.map(result -> new ResponseEntity<>(result, HttpStatus.OK))
.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
@PutMapping("/{id}")
ResponseEntity updateUser(@PathVariable String id, @RequestBody User user) {
Assert.notNull(user, "the user can't be null!");
user.setId(id);
return Optional.ofNullable(userService.updateUser(id, user))
.map(result -> new ResponseEntity(HttpStatus.NO_CONTENT))
.orElse(new ResponseEntity(HttpStatus.NOT_FOUND));
}
@DeleteMapping("/{id}")
ResponseEntity deleteUser(@PathVariable(value = "id") String id) {
return Optional.ofNullable(userService.deleteUser(id))
.map(result -> new ResponseEntity<>(result, HttpStatus.NO_CONTENT))
.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
}
\ No newline at end of file
package de.codecentric.resilience.redis.service;
/**
* @author Benjamin Wilms
*/
import de.codecentric.resilience.redis.domain.User;
import de.codecentric.resilience.redis.domain.UserRepository;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class UserService {
protected final Log logger = LogFactory.getLog(getClass());
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@CacheEvict(value = "user", key = "#user.getId()")
public User createUser(User user) {
User result = null;
if (!userRepository.exists(user.getId())) {
result = this.userRepository.save(user);
}
return result;
}
@Cacheable(value = "user")
public User getUser(String id) {
logger.info("Loading user from database");
latency();
return this.userRepository.findOne(id);
}
private void latency() {
try {
logger.info("add latency 3s");
Thread.sleep(3000);
} catch (InterruptedException e) {
// nothing to do
}
}
@CachePut(value = "user", key = "#id")
public User updateUser(String id, User user) {
User result = null;
if (userRepository.exists(user.getId())) {
result = this.userRepository.save(user);
}
return result;
}
@CacheEvict(value = "user", key = "#id")
public boolean deleteUser(String id) {
boolean deleted = false;
if (userRepository.exists(id)) {
this.userRepository.delete(id);
deleted = true;
}
return deleted;
}
}
spring:
redis:
host: localhost
port: 6379
jpa:
show_sql: false
database: MYSQL
generate-ddl: true
datasource:
url: jdbc:mysql://localhost:3306/dev?useSSL=false
username: root
password: root
......@@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>de.codecentric.resilience</groupId>
<artifactId>greeting-eureka-app</artifactId>
<artifactId>greeting-app-eureka</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
......@@ -81,4 +81,4 @@
</repository>
</repositories>
</project>
\ No newline at end of file
</project>
<?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>
<groupId>de.codecentirc.resilience.ribbon</groupId>
<artifactId>greeting-client</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</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-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
\ No newline at end of file
package de.codecentric.resilience.ribbon;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* @author Benjamin Wilms
*/
@SpringBootApplication
@RestController
public class GreetingClient {
@Bean
RestTemplate restTemplate(){
return new RestTemplate();
}
@Autowired
RestTemplate restTemplate;
@RequestMapping("/hi")
public String hi(@RequestParam(value="name", defaultValue="Artaban") String name) {
String greeting = this.restTemplate.getForObject("http://localhost:8010/greeting", String.class);
return String.format("%s, %s!", greeting, name);
}
public static void main(String[] args) {
SpringApplication.run(GreetingClient.class, args);
}
}
package de.codecentric.resilience.ribbon;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
/**
* @author Benjamin Wilms
*/
public class SayHelloConfiguration {
@Autowired
IClientConfig ribbonClientConfig;
@Bean
public IPing ribbonPing(IClientConfig config) {
return new PingUrl();
}
@Bean
public IRule ribbonRule(IClientConfig config) {
return new RoundRobinRule();
}
}
say-hello:
ribbon:
eureka:
enabled: false
listOfServers: localhost:8010,localhost:9092,localhost:9999
ServerListRefreshInterval: 15000
security:
basic:
enabled: false
management:
security:
enabled: false
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment