提交 7c7f7b2a 编写于 作者: J Jason Song

format according google code style

上级 d25e0cbf
<?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/maven-v4_0_0.xsd">
<parent>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apollo-adminservice</artifactId>
<name>Apollo AdminService</name>
<dependencies>
<!-- apollo -->
<dependency>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo-biz</artifactId>
</dependency>
<!-- end of apollo -->
<!-- redis -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!-- end of redis -->
<!-- eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<!-- end of eureka -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apollo-adminservice</artifactId>
<name>Apollo AdminService</name>
<dependencies>
<!-- apollo -->
<dependency>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo-biz</artifactId>
</dependency>
<!-- end of apollo -->
<!-- redis -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!-- end of redis -->
<!-- eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<!-- end of eureka -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
......@@ -2,13 +2,12 @@ package com.ctrip.apollo;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
//@EnableEurekaClient
public class AdminServiceApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(AdminServiceApplication.class).web(true).run(args);
}
public static void main(String[] args) {
new SpringApplicationBuilder(AdminServiceApplication.class).web(true).run(args);
}
}
......@@ -2,6 +2,7 @@ package com.ctrip.apollo.adminservice.controller;
import com.ctrip.apollo.biz.service.AdminConfigService;
import com.ctrip.apollo.core.dto.ClusterDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
......@@ -13,11 +14,11 @@ import java.util.List;
@RequestMapping("/cluster")
public class ClusterController {
@Autowired
private AdminConfigService adminConfigService;
@Autowired
private AdminConfigService adminConfigService;
@RequestMapping("/app/{appId}")
public List<ClusterDTO> findClustersByApp(@PathVariable long appId){
return adminConfigService.findClustersByApp(appId);
}
@RequestMapping("/app/{appId}")
public List<ClusterDTO> findClustersByApp(@PathVariable long appId) {
return adminConfigService.findClustersByApp(appId);
}
}
......@@ -3,31 +3,34 @@ package com.ctrip.apollo.adminservice.controller;
import com.ctrip.apollo.biz.service.AdminConfigService;
import com.ctrip.apollo.core.dto.ConfigItemDTO;
import com.ctrip.apollo.core.dto.ReleaseSnapshotDTO;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
import javax.annotation.Resource;
@RestController
@RequestMapping("/configs")
public class ConfigController {
@Resource(name = "adminConfigService")
private AdminConfigService adminConfigService;
@Resource(name = "adminConfigService")
private AdminConfigService adminConfigService;
@RequestMapping("/release/{releaseId}")
public List<ReleaseSnapshotDTO> getRelaseSnapshot(@PathVariable long releaseId){
return adminConfigService.findReleaseSnapshotByReleaseId(releaseId);
}
@RequestMapping("/release/{releaseId}")
public List<ReleaseSnapshotDTO> getRelaseSnapshot(@PathVariable long releaseId) {
return adminConfigService.findReleaseSnapshotByReleaseId(releaseId);
}
@RequestMapping("/latest")
public List<ConfigItemDTO> findConfigItemsByClusters(@RequestParam(value = "clusterIds") List<Long> clusterIds){
return adminConfigService.findConfigItemsByClusters(clusterIds);
}
@RequestMapping("/latest")
public List<ConfigItemDTO> findConfigItemsByClusters(
@RequestParam(value = "clusterIds") List<Long> clusterIds) {
return adminConfigService.findConfigItemsByClusters(clusterIds);
}
}
......@@ -2,6 +2,7 @@ package com.ctrip.apollo.adminservice.controller;
import com.ctrip.apollo.biz.service.AdminConfigService;
import com.ctrip.apollo.core.dto.VersionDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
......@@ -13,21 +14,19 @@ import java.util.List;
@RequestMapping("/version")
public class VersionController {
@Autowired
private AdminConfigService adminConfigService;
@RequestMapping("/app/{appId}")
public List<VersionDTO> versions(@PathVariable long appId){
return adminConfigService.findVersionsByApp(appId);
}
@Autowired
private AdminConfigService adminConfigService;
@RequestMapping("/{versionId}")
public VersionDTO version(@PathVariable long versionId){
return adminConfigService.loadVersionById(versionId);
}
@RequestMapping("/app/{appId}")
public List<VersionDTO> versions(@PathVariable long appId) {
return adminConfigService.findVersionsByApp(appId);
}
@RequestMapping("/{versionId}")
public VersionDTO version(@PathVariable long versionId) {
return adminConfigService.loadVersionById(versionId);
}
}
package com.ctrip.apollo.biz.entity;
import com.ctrip.apollo.core.dto.ClusterDTO;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
......@@ -16,58 +17,58 @@ import javax.persistence.Id;
@Where(clause = "isDeleted = 0")
@SQLDelete(sql = "Update Cluster set isDeleted = 1 where id = ?")
public class Cluster {
@Id
@GeneratedValue
private long id;
@Id
@GeneratedValue
private long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private long appId;
@Column(nullable = false)
private long appId;
private boolean isDeleted;
private boolean isDeleted;
public Cluster() {
}
public Cluster() {
}
public long getId() {
return id;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public long getAppId() {
return appId;
}
public long getAppId() {
return appId;
}
public void setAppId(long appId) {
this.appId = appId;
}
public void setAppId(long appId) {
this.appId = appId;
}
public boolean isDeleted() {
return isDeleted;
}
public boolean isDeleted() {
return isDeleted;
}
public void setDeleted(boolean deleted) {
isDeleted = deleted;
}
public void setDeleted(boolean deleted) {
isDeleted = deleted;
}
public ClusterDTO toDTO(){
ClusterDTO dto = new ClusterDTO();
dto.setAppId(appId);
dto.setId(id);
dto.setName(name);
return dto;
}
public ClusterDTO toDTO() {
ClusterDTO dto = new ClusterDTO();
dto.setAppId(appId);
dto.setId(id);
dto.setName(name);
return dto;
}
}
package com.ctrip.apollo.biz.entity;
import com.ctrip.apollo.core.dto.ConfigItemDTO;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.util.Date;
@Entity
@Where(clause = "isDeleted = 0")
@SQLDelete(sql = "Update ConfigItem set isDeleted = 1 where id = ?")
public class ConfigItem {
@Id
@GeneratedValue
private long id;
@Id
@GeneratedValue
private long id;
@Column(nullable = false)
private long clusterId;
@Column(nullable = false)
private long clusterId;
@Column(nullable = false)
private String clusterName;
@Column(nullable = false)
private String clusterName;
@Column(nullable = false)
private long appId;
@Column(nullable = false)
private long appId;
@Column(nullable = false)
private String key;
@Column(nullable = false)
private String key;
@Column
private String value;
@Column
private String value;
@Column
private String comment;
@Column
private String comment;
@Column
private String dataChangeCreatedBy;
@Column
private String dataChangeCreatedBy;
@Column
private Date dataChangeCreatedTime;
@Column
private Date dataChangeCreatedTime;
@Column
private String dataChangeLastModifiedBy;
@Column
private String dataChangeLastModifiedBy;
@Column
private Date dataChangeLastModifiedTime;
@Column
private Date dataChangeLastModifiedTime;
@Column
private boolean IsDeleted;
@Column
private boolean IsDeleted;
public long getId() {
return id;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public void setId(long id) {
this.id = id;
}
public long getClusterId() {
return clusterId;
}
public long getClusterId() {
return clusterId;
}
public void setClusterId(long clusterId) {
this.clusterId = clusterId;
}
public void setClusterId(long clusterId) {
this.clusterId = clusterId;
}
public String getClusterName() {
return clusterName;
}
public String getClusterName() {
return clusterName;
}
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
public long getAppId() {
return appId;
}
public long getAppId() {
return appId;
}
public void setAppId(long appId) {
this.appId = appId;
}
public void setAppId(long appId) {
this.appId = appId;
}
public String getKey() {
return key;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public void setValue(String value) {
this.value = value;
}
public String getComment() {
return comment;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getDataChangeCreatedBy() {
return dataChangeCreatedBy;
}
public String getDataChangeCreatedBy() {
return dataChangeCreatedBy;
}
public void setDataChangeCreatedBy(String dataChangeCreatedBy) {
this.dataChangeCreatedBy = dataChangeCreatedBy;
}
public Date getDataChangeCreatedTime() {
return dataChangeCreatedTime;
}
public void setDataChangeCreatedTime(Date dataChangeCreatedTime) {
this.dataChangeCreatedTime = dataChangeCreatedTime;
}
public String getDataChangeLastModifiedBy() {
return dataChangeLastModifiedBy;
}
public void setDataChangeLastModifiedBy(String dataChangeLastModifiedBy) {
this.dataChangeLastModifiedBy = dataChangeLastModifiedBy;
}
public boolean isDeleted() {
return IsDeleted;
}
public void setDeleted(boolean isDeleted) {
IsDeleted = isDeleted;
}
public Date getDataChangeLastModifiedTime() {
return dataChangeLastModifiedTime;
}
public void setDataChangeLastModifiedTime(Date dataChangeLastModifiedTime) {
this.dataChangeLastModifiedTime = dataChangeLastModifiedTime;
}
public ConfigItemDTO toDTO(){
ConfigItemDTO dto = new ConfigItemDTO();
dto.setAppId(appId);
dto.setId(id);
dto.setClusterId(clusterId);
dto.setClusterName(clusterName);
dto.setDataChangeCreatedBy(dataChangeCreatedBy);
dto.setDataChangeLastModifiedBy(dataChangeLastModifiedBy);
dto.setDataChangeCreatedTime(dataChangeCreatedTime);
dto.setDataChangeLastModifiedTime(dataChangeLastModifiedTime);
dto.setKey(key);
dto.setValue(value);
dto.setComment(comment);
return dto;
}
public void setDataChangeCreatedBy(String dataChangeCreatedBy) {
this.dataChangeCreatedBy = dataChangeCreatedBy;
}
public Date getDataChangeCreatedTime() {
return dataChangeCreatedTime;
}
public void setDataChangeCreatedTime(Date dataChangeCreatedTime) {
this.dataChangeCreatedTime = dataChangeCreatedTime;
}
public String getDataChangeLastModifiedBy() {
return dataChangeLastModifiedBy;
}
public void setDataChangeLastModifiedBy(String dataChangeLastModifiedBy) {
this.dataChangeLastModifiedBy = dataChangeLastModifiedBy;
}
public boolean isDeleted() {
return IsDeleted;
}
public void setDeleted(boolean isDeleted) {
IsDeleted = isDeleted;
}
public Date getDataChangeLastModifiedTime() {
return dataChangeLastModifiedTime;
}
public void setDataChangeLastModifiedTime(Date dataChangeLastModifiedTime) {
this.dataChangeLastModifiedTime = dataChangeLastModifiedTime;
}
public ConfigItemDTO toDTO() {
ConfigItemDTO dto = new ConfigItemDTO();
dto.setAppId(appId);
dto.setId(id);
dto.setClusterId(clusterId);
dto.setClusterName(clusterName);
dto.setDataChangeCreatedBy(dataChangeCreatedBy);
dto.setDataChangeLastModifiedBy(dataChangeLastModifiedBy);
dto.setDataChangeCreatedTime(dataChangeCreatedTime);
dto.setDataChangeLastModifiedTime(dataChangeLastModifiedTime);
dto.setKey(key);
dto.setValue(value);
dto.setComment(comment);
return dto;
}
}
......@@ -14,55 +14,55 @@ import javax.persistence.Id;
@Where(clause = "isDeleted = 0")
@SQLDelete(sql = "Update Release set isDeleted = 1 where id = ?")
public class Release {
@Id
@GeneratedValue
private long id;
@Id
@GeneratedValue
private long id;
private String name;
private long appId;
private String comment;
private boolean isDeleted;
private String name;
private long appId;
private String comment;
private boolean isDeleted;
public Release() {
}
public Release() {
}
public long getId() {
return id;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public long getAppId() {
return appId;
}
public long getAppId() {
return appId;
}
public void setAppId(long appId) {
this.appId = appId;
}
public void setAppId(long appId) {
this.appId = appId;
}
public String getComment() {
return comment;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public boolean isDeleted() {
return isDeleted;
}
public boolean isDeleted() {
return isDeleted;
}
public void setDeleted(boolean deleted) {
isDeleted = deleted;
}
public void setDeleted(boolean deleted) {
isDeleted = deleted;
}
}
package com.ctrip.apollo.biz.entity;
import com.ctrip.apollo.core.dto.ReleaseSnapshotDTO;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
......@@ -16,70 +17,70 @@ import javax.persistence.Id;
@Where(clause = "isDeleted = 0")
@SQLDelete(sql = "Update ReleaseSnapShot set isDeleted = 1 where id = ?")
public class ReleaseSnapShot {
@Id
@GeneratedValue
private long id;
@Id
@GeneratedValue
private long id;
@Column(nullable = false)
private long releaseId;
@Column(nullable = false)
private long releaseId;
@Column(nullable = false)
private String clusterName;
@Column(nullable = false)
private String clusterName;
@Column(nullable = false)
private String configurations;
@Column(nullable = false)
private String configurations;
private boolean isDeleted;
private boolean isDeleted;
public ReleaseSnapShot() {
}
public ReleaseSnapShot() {
}
public long getId() {
return id;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public void setId(long id) {
this.id = id;
}
public long getReleaseId() {
return releaseId;
}
public long getReleaseId() {
return releaseId;
}
public void setReleaseId(long releaseId) {
this.releaseId = releaseId;
}
public void setReleaseId(long releaseId) {
this.releaseId = releaseId;
}
public String getClusterName() {
return clusterName;
}
public String getClusterName() {
return clusterName;
}
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
public String getConfigurations() {
return configurations;
}
public String getConfigurations() {
return configurations;
}
public void setConfigurations(String configurations) {
this.configurations = configurations;
}
public void setConfigurations(String configurations) {
this.configurations = configurations;
}
public boolean isDeleted() {
return isDeleted;
}
public boolean isDeleted() {
return isDeleted;
}
public void setDeleted(boolean deleted) {
isDeleted = deleted;
}
public void setDeleted(boolean deleted) {
isDeleted = deleted;
}
public ReleaseSnapshotDTO toDTO(){
ReleaseSnapshotDTO dto = new ReleaseSnapshotDTO();
dto.setId(id);
dto.setClusterName(clusterName);
dto.setConfigurations(configurations);
dto.setReleaseId(releaseId);
return dto;
}
public ReleaseSnapshotDTO toDTO() {
ReleaseSnapshotDTO dto = new ReleaseSnapshotDTO();
dto.setId(id);
dto.setClusterName(clusterName);
dto.setConfigurations(configurations);
dto.setReleaseId(releaseId);
return dto;
}
}
package com.ctrip.apollo.biz.entity;
import com.ctrip.apollo.core.dto.VersionDTO;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
......@@ -16,80 +17,80 @@ import javax.persistence.Id;
@Where(clause = "isDeleted = 0")
@SQLDelete(sql = "Update Version set isDeleted = 1 where id = ?")
public class Version {
@Id
@GeneratedValue
private long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private long appId;
@Column(nullable = false)
private long releaseId;
//parent version could be null
private Long parentVersion;
private boolean isDeleted;
public Version() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getAppId() {
return appId;
}
public void setAppId(long appId) {
this.appId = appId;
}
public long getReleaseId() {
return releaseId;
}
public void setReleaseId(long releaseId) {
this.releaseId = releaseId;
}
public boolean isDeleted() {
return isDeleted;
}
public void setDeleted(boolean deleted) {
isDeleted = deleted;
}
public Long getParentVersion() {
return parentVersion;
}
public void setParentVersion(Long parentVersion) {
this.parentVersion = parentVersion;
}
public VersionDTO toDTO() {
VersionDTO dto = new VersionDTO();
dto.setAppId(this.appId);
dto.setId(this.id);
dto.setName(this.name);
dto.setParentVersion(this.parentVersion);
dto.setReleaseId(this.releaseId);
return dto;
}
@Id
@GeneratedValue
private long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private long appId;
@Column(nullable = false)
private long releaseId;
//parent version could be null
private Long parentVersion;
private boolean isDeleted;
public Version() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getAppId() {
return appId;
}
public void setAppId(long appId) {
this.appId = appId;
}
public long getReleaseId() {
return releaseId;
}
public void setReleaseId(long releaseId) {
this.releaseId = releaseId;
}
public boolean isDeleted() {
return isDeleted;
}
public void setDeleted(boolean deleted) {
isDeleted = deleted;
}
public Long getParentVersion() {
return parentVersion;
}
public void setParentVersion(Long parentVersion) {
this.parentVersion = parentVersion;
}
public VersionDTO toDTO() {
VersionDTO dto = new VersionDTO();
dto.setAppId(this.appId);
dto.setId(this.id);
dto.setName(this.name);
dto.setParentVersion(this.parentVersion);
dto.setReleaseId(this.releaseId);
return dto;
}
}
......@@ -2,12 +2,13 @@ package com.ctrip.apollo.biz.repository;
import com.ctrip.apollo.biz.entity.Cluster;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List;
public interface ClusterRepository extends PagingAndSortingRepository<Cluster, Long> {
List<Cluster> findByAppId(long appId);
List<Cluster> findByAppId(long appId);
}
package com.ctrip.apollo.biz.repository;
import com.ctrip.apollo.biz.entity.ConfigItem;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List;
public interface ConfigItemRepository extends PagingAndSortingRepository<ConfigItem, Long> {
List<ConfigItem> findByClusterIdIsIn(List<Long> clusterIds);
List<ConfigItem> findByClusterIdIsIn(List<Long> clusterIds);
}
package com.ctrip.apollo.biz.repository;
import com.ctrip.apollo.biz.entity.ReleaseSnapShot;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List;
......@@ -8,8 +9,9 @@ import java.util.List;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public interface ReleaseSnapShotRepository extends PagingAndSortingRepository<ReleaseSnapShot, Long> {
ReleaseSnapShot findByReleaseIdAndClusterName(long releaseId, String clusterName);
public interface ReleaseSnapShotRepository
extends PagingAndSortingRepository<ReleaseSnapShot, Long> {
ReleaseSnapShot findByReleaseIdAndClusterName(long releaseId, String clusterName);
List<ReleaseSnapShot> findByReleaseId(long releaseId);
List<ReleaseSnapShot> findByReleaseId(long releaseId);
}
package com.ctrip.apollo.biz.repository;
import com.ctrip.apollo.biz.entity.Version;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List;
......@@ -9,9 +10,9 @@ import java.util.List;
* @author Jason Song(song_s@ctrip.com)
*/
public interface VersionRepository extends PagingAndSortingRepository<Version, Long> {
Version findByAppIdAndName(long appId, String name);
Version findByAppIdAndName(long appId, String name);
Version findById(long id);
Version findById(long id);
List<Version> findByAppId(long appId);
List<Version> findByAppId(long appId);
}
package com.ctrip.apollo.biz.service;
import com.ctrip.apollo.core.dto.*;
import com.ctrip.apollo.core.dto.ClusterDTO;
import com.ctrip.apollo.core.dto.ConfigItemDTO;
import com.ctrip.apollo.core.dto.ReleaseSnapshotDTO;
import com.ctrip.apollo.core.dto.VersionDTO;
import java.util.List;
......@@ -9,14 +12,14 @@ import java.util.List;
*/
public interface AdminConfigService {
List<ReleaseSnapshotDTO> findReleaseSnapshotByReleaseId(long releaseId);
List<ReleaseSnapshotDTO> findReleaseSnapshotByReleaseId(long releaseId);
List<VersionDTO> findVersionsByApp(long appId);
List<VersionDTO> findVersionsByApp(long appId);
VersionDTO loadVersionById(long versionId);
VersionDTO loadVersionById(long versionId);
List<ClusterDTO> findClustersByApp(long appId);
List<ClusterDTO> findClustersByApp(long appId);
List<ConfigItemDTO> findConfigItemsByClusters(List<Long> clusterIds);
List<ConfigItemDTO> findConfigItemsByClusters(List<Long> clusterIds);
}
......@@ -5,31 +5,22 @@ import com.ctrip.apollo.core.dto.ApolloConfig;
/**
* Config Service
*
* @author Jason Song(song_s@ctrip.com)
*/
public interface ConfigService {
/**
* Load configuration from database
* @param appId
* @param clusterName
* @param versionName
* @return
*/
ApolloConfig loadConfig(long appId, String clusterName, String versionName);
/**
* Load configuration from database
*/
ApolloConfig loadConfig(long appId, String clusterName, String versionName);
/**
* Load Version by appId and versionName from database
* @param appId
* @param versionName
* @return
*/
Version loadVersionByAppIdAndVersionName(long appId, String versionName);
/**
* Load Version by appId and versionName from database
*/
Version loadVersionByAppIdAndVersionName(long appId, String versionName);
/**
* Load Config by version and clusterName from database
* @param version
* @param clusterName
* @return
*/
ApolloConfig loadConfigByVersionAndClusterName(Version version, String clusterName);
/**
* Load Config by version and clusterName from database
*/
ApolloConfig loadConfigByVersionAndClusterName(Version version, String clusterName);
}
......@@ -9,103 +9,109 @@ import com.ctrip.apollo.biz.repository.ConfigItemRepository;
import com.ctrip.apollo.biz.repository.ReleaseSnapShotRepository;
import com.ctrip.apollo.biz.repository.VersionRepository;
import com.ctrip.apollo.biz.service.AdminConfigService;
import com.ctrip.apollo.core.dto.*;
import com.ctrip.apollo.core.dto.ClusterDTO;
import com.ctrip.apollo.core.dto.ConfigItemDTO;
import com.ctrip.apollo.core.dto.ReleaseSnapshotDTO;
import com.ctrip.apollo.core.dto.VersionDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Service("adminConfigService")
public class AdminConfigServiceImpl implements AdminConfigService {
@Autowired
private VersionRepository versionRepository;
@Autowired
private ReleaseSnapShotRepository releaseSnapShotRepository;
@Autowired
private ClusterRepository clusterRepository;
@Autowired
private ConfigItemRepository configItemRepository;
@Override
public List<ReleaseSnapshotDTO> findReleaseSnapshotByReleaseId(long releaseId) {
if (releaseId <= 0){
return Collections.EMPTY_LIST;
}
List<ReleaseSnapShot> releaseSnapShots = releaseSnapShotRepository.findByReleaseId(releaseId);
if (releaseSnapShots == null || releaseSnapShots.size() == 0){
return Collections.EMPTY_LIST;
}
List<ReleaseSnapshotDTO> result = new ArrayList<>(releaseSnapShots.size());
for (ReleaseSnapShot releaseSnapShot: releaseSnapShots){
result.add(releaseSnapShot.toDTO());
}
return result;
@Autowired
private VersionRepository versionRepository;
@Autowired
private ReleaseSnapShotRepository releaseSnapShotRepository;
@Autowired
private ClusterRepository clusterRepository;
@Autowired
private ConfigItemRepository configItemRepository;
@Override
public List<ReleaseSnapshotDTO> findReleaseSnapshotByReleaseId(long releaseId) {
if (releaseId <= 0) {
return Collections.EMPTY_LIST;
}
List<ReleaseSnapShot> releaseSnapShots = releaseSnapShotRepository.findByReleaseId(releaseId);
if (releaseSnapShots == null || releaseSnapShots.size() == 0) {
return Collections.EMPTY_LIST;
}
@Override
public List<VersionDTO> findVersionsByApp(long appId) {
if (appId <= 0) {
return Collections.EMPTY_LIST;
}
List<ReleaseSnapshotDTO> result = new ArrayList<>(releaseSnapShots.size());
for (ReleaseSnapShot releaseSnapShot : releaseSnapShots) {
result.add(releaseSnapShot.toDTO());
}
return result;
}
List<Version> versions = versionRepository.findByAppId(appId);
if (versions == null || versions.size() == 0) {
return Collections.EMPTY_LIST;
}
List<VersionDTO> result = new ArrayList<>(versions.size());
for (Version version : versions) {
result.add(version.toDTO());
}
return result;
@Override
public List<VersionDTO> findVersionsByApp(long appId) {
if (appId <= 0) {
return Collections.EMPTY_LIST;
}
@Override
public VersionDTO loadVersionById(long versionId) {
if (versionId <= 0){
return null;
}
Version version = versionRepository.findById(versionId);
return version.toDTO();
List<Version> versions = versionRepository.findByAppId(appId);
if (versions == null || versions.size() == 0) {
return Collections.EMPTY_LIST;
}
@Override
public List<ClusterDTO> findClustersByApp(long appId) {
if (appId <= 0){
return Collections.EMPTY_LIST;
}
List<Cluster> clusters = clusterRepository.findByAppId(appId);
if (clusters == null || clusters.size() == 0){
return Collections.EMPTY_LIST;
}
List<ClusterDTO> result = new ArrayList<>(clusters.size());
for (Cluster cluster: clusters){
result.add(cluster.toDTO());
}
return result;
List<VersionDTO> result = new ArrayList<>(versions.size());
for (Version version : versions) {
result.add(version.toDTO());
}
return result;
}
@Override
public VersionDTO loadVersionById(long versionId) {
if (versionId <= 0) {
return null;
}
Version version = versionRepository.findById(versionId);
return version.toDTO();
}
@Override
public List<ClusterDTO> findClustersByApp(long appId) {
if (appId <= 0) {
return Collections.EMPTY_LIST;
}
List<Cluster> clusters = clusterRepository.findByAppId(appId);
if (clusters == null || clusters.size() == 0) {
return Collections.EMPTY_LIST;
}
List<ClusterDTO> result = new ArrayList<>(clusters.size());
for (Cluster cluster : clusters) {
result.add(cluster.toDTO());
}
return result;
}
@Override
public List<ConfigItemDTO> findConfigItemsByClusters(List<Long> clusterIds) {
if (clusterIds == null || clusterIds.size() == 0) {
return Collections.EMPTY_LIST;
}
List<ConfigItem> configItems = configItemRepository.findByClusterIdIsIn(clusterIds);
if (configItems == null || configItems.size() == 0) {
return Collections.EMPTY_LIST;
}
@Override
public List<ConfigItemDTO> findConfigItemsByClusters(List<Long> clusterIds) {
if (clusterIds == null || clusterIds.size() == 0){
return Collections.EMPTY_LIST;
}
List<ConfigItem> configItems = configItemRepository.findByClusterIdIsIn(clusterIds);
if (configItems == null || configItems.size() == 0){
return Collections.EMPTY_LIST;
}
List<ConfigItemDTO> result = new ArrayList<>(configItems.size());
for (ConfigItem configItem: configItems){
result.add(configItem.toDTO());
}
return result;
List<ConfigItemDTO> result = new ArrayList<>(configItems.size());
for (ConfigItem configItem : configItems) {
result.add(configItem.toDTO());
}
return result;
}
}
package com.ctrip.apollo.biz.service.impl;
import com.google.common.collect.Maps;
import com.ctrip.apollo.biz.entity.ReleaseSnapShot;
import com.ctrip.apollo.biz.entity.Version;
import com.ctrip.apollo.biz.repository.ReleaseSnapShotRepository;
......@@ -8,7 +10,7 @@ import com.ctrip.apollo.biz.service.ConfigService;
import com.ctrip.apollo.core.dto.ApolloConfig;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
......@@ -20,56 +22,58 @@ import java.util.Map;
*/
@Service("configService")
public class ConfigServiceImpl implements ConfigService {
@Autowired
private VersionRepository versionRepository;
@Autowired
private ReleaseSnapShotRepository releaseSnapShotRepository;
@Autowired
private ObjectMapper objectMapper;
private TypeReference<Map<String, Object>> configurationTypeReference =
new TypeReference<Map<String, Object>>() {
};
@Autowired
private VersionRepository versionRepository;
@Autowired
private ReleaseSnapShotRepository releaseSnapShotRepository;
@Autowired
private ObjectMapper objectMapper;
private TypeReference<Map<String, Object>> configurationTypeReference =
new TypeReference<Map<String, Object>>() {
};
@Override
public ApolloConfig loadConfig(long appId, String clusterName, String versionName) {
Version version = loadVersionByAppIdAndVersionName(appId, versionName);
if (version == null) {
return null;
}
return loadConfigByVersionAndClusterName(version, clusterName);
@Override
public ApolloConfig loadConfig(long appId, String clusterName, String versionName) {
Version version = loadVersionByAppIdAndVersionName(appId, versionName);
if (version == null) {
return null;
}
@Override
public Version loadVersionByAppIdAndVersionName(long appId, String versionName) {
return versionRepository.findByAppIdAndName(appId, versionName);
}
return loadConfigByVersionAndClusterName(version, clusterName);
}
@Override
public ApolloConfig loadConfigByVersionAndClusterName(Version version, String clusterName) {
ReleaseSnapShot releaseSnapShot =
releaseSnapShotRepository.findByReleaseIdAndClusterName(version.getReleaseId(), clusterName);
if (releaseSnapShot == null) {
return null;
}
@Override
public Version loadVersionByAppIdAndVersionName(long appId, String versionName) {
return versionRepository.findByAppIdAndName(appId, versionName);
}
return assembleConfig(version, releaseSnapShot);
@Override
public ApolloConfig loadConfigByVersionAndClusterName(Version version, String clusterName) {
ReleaseSnapShot releaseSnapShot =
releaseSnapShotRepository
.findByReleaseIdAndClusterName(version.getReleaseId(), clusterName);
if (releaseSnapShot == null) {
return null;
}
private ApolloConfig assembleConfig(Version version, ReleaseSnapShot releaseSnapShot) {
ApolloConfig config =
new ApolloConfig(version.getAppId(), releaseSnapShot.getClusterName(), version.getName(), version.getReleaseId());
config.setConfigurations(transformConfigurationToMap(releaseSnapShot.getConfigurations()));
return assembleConfig(version, releaseSnapShot);
}
return config;
}
private ApolloConfig assembleConfig(Version version, ReleaseSnapShot releaseSnapShot) {
ApolloConfig config =
new ApolloConfig(version.getAppId(), releaseSnapShot.getClusterName(), version.getName(),
version.getReleaseId());
config.setConfigurations(transformConfigurationToMap(releaseSnapShot.getConfigurations()));
return config;
}
Map<String, Object> transformConfigurationToMap(String configurations) {
try {
return objectMapper.readValue(configurations, configurationTypeReference);
} catch (IOException e) {
e.printStackTrace();
return Maps.newHashMap();
}
Map<String, Object> transformConfigurationToMap(String configurations) {
try {
return objectMapper.readValue(configurations, configurationTypeReference);
} catch (IOException e) {
e.printStackTrace();
return Maps.newHashMap();
}
}
}
package com.ctrip.apollo.biz;
import com.ctrip.apollo.biz.service.impl.ConfigServiceImplTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({
ConfigServiceImplTest.class})
ConfigServiceImplTest.class})
public class AllTests {
}
package com.ctrip.apollo.biz.service.impl;
import com.google.common.collect.Maps;
import com.ctrip.apollo.biz.entity.ReleaseSnapShot;
import com.ctrip.apollo.biz.entity.Version;
import com.ctrip.apollo.biz.repository.ReleaseSnapShotRepository;
......@@ -7,7 +9,7 @@ import com.ctrip.apollo.biz.repository.VersionRepository;
import com.ctrip.apollo.core.dto.ApolloConfig;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
......@@ -21,123 +23,140 @@ import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.anyObject;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith(MockitoJUnitRunner.class)
public class ConfigServiceImplTest {
@Mock
private VersionRepository versionRepository;
@Mock
private ReleaseSnapShotRepository releaseSnapShotRepository;
@Mock
private ObjectMapper objectMapper;
private ConfigServiceImpl configService;
@Before
public void setUp() throws Exception {
configService = new ConfigServiceImpl();
ReflectionTestUtils.setField(configService, "versionRepository", versionRepository);
ReflectionTestUtils.setField(configService, "releaseSnapShotRepository", releaseSnapShotRepository);
ReflectionTestUtils.setField(configService, "objectMapper", objectMapper);
}
@Test
public void testLoadConfig() throws Exception {
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersionName";
long someReleaseId = 1;
String someValidConfiguration = "{\"apollo.bar\": \"foo\"}";
Version someVersion = assembleVersion(someAppId, someVersionName, someReleaseId);
ReleaseSnapShot someReleaseSnapShot = assembleReleaseSnapShot(someReleaseId, someClusterName, someValidConfiguration);
Map<String, Object> someMap = Maps.newHashMap();
when(versionRepository.findByAppIdAndName(someAppId, someVersionName)).thenReturn(someVersion);
when(releaseSnapShotRepository.findByReleaseIdAndClusterName(someReleaseId, someClusterName)).thenReturn(someReleaseSnapShot);
when(objectMapper.readValue(eq(someValidConfiguration), (TypeReference) anyObject())).thenReturn(someMap);
ApolloConfig result = configService.loadConfig(someAppId, someClusterName, someVersionName);
assertEquals(someAppId, result.getAppId());
assertEquals(someClusterName, result.getCluster());
assertEquals(someVersionName, result.getVersion());
assertEquals(someReleaseId, result.getReleaseId());
assertEquals(someMap, result.getConfigurations());
}
@Test
public void testLoadConfigWithVersionNotFound() throws Exception {
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersionName";
when(versionRepository.findByAppIdAndName(someAppId, someVersionName)).thenReturn(null);
ApolloConfig result = configService.loadConfig(someAppId, someClusterName, someVersionName);
assertNull(result);
verify(versionRepository, times(1)).findByAppIdAndName(someAppId, someVersionName);
}
@Test
public void testLoadConfigWithConfigNotFound() throws Exception {
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersionName";
long someReleaseId = 1;
Version someVersion = assembleVersion(someAppId, someVersionName, someReleaseId);
when(versionRepository.findByAppIdAndName(someAppId, someVersionName)).thenReturn(someVersion);
when(releaseSnapShotRepository.findByReleaseIdAndClusterName(someReleaseId, someClusterName)).thenReturn(null);
ApolloConfig result = configService.loadConfig(someAppId, someClusterName, someVersionName);
assertNull(result);
verify(versionRepository, times(1)).findByAppIdAndName(someAppId, someVersionName);
verify(releaseSnapShotRepository, times(1)).findByReleaseIdAndClusterName(someReleaseId, someClusterName);
}
private Version assembleVersion(long appId, String versionName, long releaseId) {
Version version = new Version();
version.setAppId(appId);
version.setName(versionName);
version.setReleaseId(releaseId);
return version;
}
private ReleaseSnapShot assembleReleaseSnapShot(long releaseId, String clusterName, String configurations) {
ReleaseSnapShot releaseSnapShot = new ReleaseSnapShot();
releaseSnapShot.setReleaseId(releaseId);
releaseSnapShot.setClusterName(clusterName);
releaseSnapShot.setConfigurations(configurations);
return releaseSnapShot;
}
@Test
public void testTransformConfigurationToMapSuccessful() throws Exception {
String someValidConfiguration = "{\"apollo.bar\": \"foo\"}";
Map<String, String> someMap = Maps.newHashMap();
when(objectMapper.readValue(eq(someValidConfiguration), (TypeReference) anyObject())).thenReturn(someMap);
Map<String, Object> result = configService.transformConfigurationToMap(someValidConfiguration);
assertEquals(someMap, result);
verify(objectMapper, times(1)).readValue(eq(someValidConfiguration), (TypeReference) anyObject());
}
@Test
public void testTransformConfigurationToMapFailed() throws Exception {
String someInvalidConfiguration = "xxx";
when(objectMapper.readValue(eq(someInvalidConfiguration), (TypeReference) anyObject())).thenThrow(IOException.class);
Map<String, Object> result = configService.transformConfigurationToMap(someInvalidConfiguration);
assertTrue(result.isEmpty());
}
@Mock
private VersionRepository versionRepository;
@Mock
private ReleaseSnapShotRepository releaseSnapShotRepository;
@Mock
private ObjectMapper objectMapper;
private ConfigServiceImpl configService;
@Before
public void setUp() throws Exception {
configService = new ConfigServiceImpl();
ReflectionTestUtils.setField(configService, "versionRepository", versionRepository);
ReflectionTestUtils
.setField(configService, "releaseSnapShotRepository", releaseSnapShotRepository);
ReflectionTestUtils.setField(configService, "objectMapper", objectMapper);
}
@Test
public void testLoadConfig() throws Exception {
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersionName";
long someReleaseId = 1;
String someValidConfiguration = "{\"apollo.bar\": \"foo\"}";
Version someVersion = assembleVersion(someAppId, someVersionName, someReleaseId);
ReleaseSnapShot
someReleaseSnapShot =
assembleReleaseSnapShot(someReleaseId, someClusterName, someValidConfiguration);
Map<String, Object> someMap = Maps.newHashMap();
when(versionRepository.findByAppIdAndName(someAppId, someVersionName)).thenReturn(someVersion);
when(releaseSnapShotRepository.findByReleaseIdAndClusterName(someReleaseId, someClusterName))
.thenReturn(someReleaseSnapShot);
when(objectMapper.readValue(eq(someValidConfiguration), (TypeReference) anyObject()))
.thenReturn(someMap);
ApolloConfig result = configService.loadConfig(someAppId, someClusterName, someVersionName);
assertEquals(someAppId, result.getAppId());
assertEquals(someClusterName, result.getCluster());
assertEquals(someVersionName, result.getVersion());
assertEquals(someReleaseId, result.getReleaseId());
assertEquals(someMap, result.getConfigurations());
}
@Test
public void testLoadConfigWithVersionNotFound() throws Exception {
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersionName";
when(versionRepository.findByAppIdAndName(someAppId, someVersionName)).thenReturn(null);
ApolloConfig result = configService.loadConfig(someAppId, someClusterName, someVersionName);
assertNull(result);
verify(versionRepository, times(1)).findByAppIdAndName(someAppId, someVersionName);
}
@Test
public void testLoadConfigWithConfigNotFound() throws Exception {
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersionName";
long someReleaseId = 1;
Version someVersion = assembleVersion(someAppId, someVersionName, someReleaseId);
when(versionRepository.findByAppIdAndName(someAppId, someVersionName)).thenReturn(someVersion);
when(releaseSnapShotRepository.findByReleaseIdAndClusterName(someReleaseId, someClusterName))
.thenReturn(null);
ApolloConfig result = configService.loadConfig(someAppId, someClusterName, someVersionName);
assertNull(result);
verify(versionRepository, times(1)).findByAppIdAndName(someAppId, someVersionName);
verify(releaseSnapShotRepository, times(1))
.findByReleaseIdAndClusterName(someReleaseId, someClusterName);
}
private Version assembleVersion(long appId, String versionName, long releaseId) {
Version version = new Version();
version.setAppId(appId);
version.setName(versionName);
version.setReleaseId(releaseId);
return version;
}
private ReleaseSnapShot assembleReleaseSnapShot(long releaseId, String clusterName,
String configurations) {
ReleaseSnapShot releaseSnapShot = new ReleaseSnapShot();
releaseSnapShot.setReleaseId(releaseId);
releaseSnapShot.setClusterName(clusterName);
releaseSnapShot.setConfigurations(configurations);
return releaseSnapShot;
}
@Test
public void testTransformConfigurationToMapSuccessful() throws Exception {
String someValidConfiguration = "{\"apollo.bar\": \"foo\"}";
Map<String, String> someMap = Maps.newHashMap();
when(objectMapper.readValue(eq(someValidConfiguration), (TypeReference) anyObject()))
.thenReturn(someMap);
Map<String, Object> result = configService.transformConfigurationToMap(someValidConfiguration);
assertEquals(someMap, result);
verify(objectMapper, times(1))
.readValue(eq(someValidConfiguration), (TypeReference) anyObject());
}
@Test
public void testTransformConfigurationToMapFailed() throws Exception {
String someInvalidConfiguration = "xxx";
when(objectMapper.readValue(eq(someInvalidConfiguration), (TypeReference) anyObject()))
.thenThrow(IOException.class);
Map<String, Object>
result =
configService.transformConfigurationToMap(someInvalidConfiguration);
assertTrue(result.isEmpty());
}
}
<?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/maven-v4_0_0.xsd">
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo</artifactId>
......
......@@ -5,6 +5,7 @@ import com.ctrip.apollo.client.loader.ConfigLoaderManager;
import com.ctrip.apollo.client.model.PropertyChange;
import com.ctrip.apollo.client.model.PropertySourceReloadResult;
import com.ctrip.apollo.client.util.ConfigUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
......@@ -35,140 +36,155 @@ import java.util.concurrent.atomic.AtomicReference;
*
* @author Jason Song(song_s@ctrip.com)
*/
public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ApplicationContextAware {
private static final Logger logger = LoggerFactory.getLogger(ApolloConfigManager.class);
private static AtomicReference<ApolloConfigManager> singletonProtector = new AtomicReference<ApolloConfigManager>();
private ConfigLoaderManager configLoaderManager;
private ConfigurableApplicationContext applicationContext;
private ConfigUtil configUtil;
private ScheduledExecutorService executorService;
private AtomicLong counter;
private RefreshScope scope;
public ApolloConfigManager() {
if(!singletonProtector.compareAndSet(null, this)) {
throw new IllegalStateException("There should be only one ApolloConfigManager instance!");
}
this.configLoaderManager = ConfigLoaderFactory.getInstance().getConfigLoaderManager();
this.configUtil = ConfigUtil.getInstance();
this.counter = new AtomicLong();
executorService = Executors.newScheduledThreadPool(1, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, "ApolloConfigManager-" + counter.incrementAndGet());
return thread;
}
});
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (!(applicationContext instanceof ConfigurableApplicationContext)) {
throw new RuntimeException(
String.format("ApplicationContext must implement ConfigurableApplicationContext, but found: %s", applicationContext.getClass().getName()));
}
this.applicationContext = (ConfigurableApplicationContext) applicationContext;
this.configUtil.setApplicationContext(applicationContext);
}
/**
* This is the first method invoked, so we could prepare the property sources here.
* Specifically we need to finish preparing property source before PropertySourcesPlaceholderConfigurer
* so that configurations could be injected correctly
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
registerDependentBeans(registry);
initializePropertySource();
schedulePeriodicRefresh();
public class ApolloConfigManager
implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ApplicationContextAware {
private static final Logger logger = LoggerFactory.getLogger(ApolloConfigManager.class);
private static AtomicReference<ApolloConfigManager>
singletonProtector =
new AtomicReference<ApolloConfigManager>();
private ConfigLoaderManager configLoaderManager;
private ConfigurableApplicationContext applicationContext;
private ConfigUtil configUtil;
private ScheduledExecutorService executorService;
private AtomicLong counter;
private RefreshScope scope;
public ApolloConfigManager() {
if (!singletonProtector.compareAndSet(null, this)) {
throw new IllegalStateException("There should be only one ApolloConfigManager instance!");
}
/**
* Register beans needed for Apollo Config Client
* <li>
* - RefreshScope: used to refresh beans when configurations changes
* </li>
* <li>
* - PropertySourcesPlaceholderConfigurer: used to support placeholder configuration injection
* </li>
* @param registry
*/
private void registerDependentBeans(BeanDefinitionRegistry registry) {
BeanDefinition refreshScope = BeanDefinitionBuilder.genericBeanDefinition(RefreshScope.class).getBeanDefinition();
registry.registerBeanDefinition("refreshScope", refreshScope);
BeanDefinition propertySourcesPlaceholderConfigurer = BeanDefinitionBuilder.genericBeanDefinition(PropertySourcesPlaceholderConfigurer.class).getBeanDefinition();
registry.registerBeanDefinition("propertySourcesPlaceholderConfigurer", propertySourcesPlaceholderConfigurer);
this.configLoaderManager = ConfigLoaderFactory.getInstance().getConfigLoaderManager();
this.configUtil = ConfigUtil.getInstance();
this.counter = new AtomicLong();
executorService = Executors.newScheduledThreadPool(1, new ThreadFactory() {
@Override
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable, "ApolloConfigManager-" + counter.incrementAndGet());
return thread;
}
});
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (!(applicationContext instanceof ConfigurableApplicationContext)) {
throw new RuntimeException(
String.format(
"ApplicationContext must implement ConfigurableApplicationContext, but found: %s",
applicationContext.getClass().getName()));
}
/**
* This is executed after postProcessBeanDefinitionRegistry
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
/**
* Make sure this bean is called before other beans
* @return
*/
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
this.applicationContext = (ConfigurableApplicationContext) applicationContext;
this.configUtil.setApplicationContext(applicationContext);
}
/**
* This is the first method invoked, so we could prepare the property sources here.
* Specifically we need to finish preparing property source before PropertySourcesPlaceholderConfigurer
* so that configurations could be injected correctly
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
throws BeansException {
registerDependentBeans(registry);
initializePropertySource();
schedulePeriodicRefresh();
}
/**
* Register beans needed for Apollo Config Client
* <li>
* - RefreshScope: used to refresh beans when configurations changes
* </li>
* <li>
* - PropertySourcesPlaceholderConfigurer: used to support placeholder configuration injection
* </li>
*/
private void registerDependentBeans(BeanDefinitionRegistry registry) {
BeanDefinition
refreshScope =
BeanDefinitionBuilder.genericBeanDefinition(RefreshScope.class).getBeanDefinition();
registry.registerBeanDefinition("refreshScope", refreshScope);
BeanDefinition
propertySourcesPlaceholderConfigurer =
BeanDefinitionBuilder.genericBeanDefinition(PropertySourcesPlaceholderConfigurer.class)
.getBeanDefinition();
registry.registerBeanDefinition("propertySourcesPlaceholderConfigurer",
propertySourcesPlaceholderConfigurer);
}
/**
* This is executed after postProcessBeanDefinitionRegistry
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
}
/**
* Make sure this bean is called before other beans
*/
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
/**
* Initialize property sources
*/
void initializePropertySource() {
//TODO stop application from starting when config cannot be loaded?
CompositePropertySource result = this.configLoaderManager.loadPropertySource();
updateEnvironmentPropertySource(result);
}
private void updateEnvironmentPropertySource(CompositePropertySource currentPropertySource) {
MutablePropertySources
currentPropertySources =
applicationContext.getEnvironment().getPropertySources();
if (currentPropertySources.contains(currentPropertySource.getName())) {
currentPropertySources.replace(currentPropertySource.getName(), currentPropertySource);
return;
}
/**
* Initialize property sources
*/
void initializePropertySource() {
//TODO stop application from starting when config cannot be loaded?
CompositePropertySource result = this.configLoaderManager.loadPropertySource();
updateEnvironmentPropertySource(result);
}
private void updateEnvironmentPropertySource(CompositePropertySource currentPropertySource) {
MutablePropertySources currentPropertySources = applicationContext.getEnvironment().getPropertySources();
if (currentPropertySources.contains(currentPropertySource.getName())) {
currentPropertySources.replace(currentPropertySource.getName(), currentPropertySource);
return;
}
currentPropertySources.addFirst(currentPropertySource);
}
void schedulePeriodicRefresh() {
executorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
updatePropertySource();
} catch (Throwable e) {
logger.error("Refreshing config failed", e);
}
currentPropertySources.addFirst(currentPropertySource);
}
void schedulePeriodicRefresh() {
executorService.scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
try {
updatePropertySource();
} catch (Throwable ex) {
logger.error("Refreshing config failed", ex);
}
}, configUtil.getRefreshInterval(), configUtil.getRefreshInterval(), configUtil.getRefreshTimeUnit());
}
}, configUtil.getRefreshInterval(), configUtil.getRefreshInterval(),
configUtil.getRefreshTimeUnit());
}
public List<PropertyChange> updatePropertySource() {
PropertySourceReloadResult result = this.configLoaderManager.reloadPropertySource();
if (result.hasChanges()) {
logger.info("Found changes, refresh environment and refreshscope beans.");
updateEnvironmentPropertySource(result.getPropertySource());
refreshBeans();
}
return result.getChanges();
}
public List<PropertyChange> updatePropertySource() {
PropertySourceReloadResult result = this.configLoaderManager.reloadPropertySource();
if (result.hasChanges()) {
logger.info("Found changes, refresh environment and refreshscope beans.");
updateEnvironmentPropertySource(result.getPropertySource());
refreshBeans();
}
return result.getChanges();
private void refreshBeans() {
if (this.scope == null) {
this.scope = applicationContext.getBean("refreshScope", RefreshScope.class);
}
private void refreshBeans() {
if (this.scope == null) {
this.scope = applicationContext.getBean("refreshScope", RefreshScope.class);
}
if (this.scope == null) {
logger.error("Could not get refresh scope object, skip refresh beans");
return;
}
this.scope.refreshAll();
if (this.scope == null) {
logger.error("Could not get refresh scope object, skip refresh beans");
return;
}
this.scope.refreshAll();
}
}
......@@ -4,8 +4,8 @@ package com.ctrip.apollo.client.constants;
* @author Jason Song(song_s@ctrip.com)
*/
public class Constants {
public static final String APP_ID = "app.id";
public static final String VERSION = "version";
public static final String DEFAULT_VERSION_NAME = "latest-release";
public static final String ENV = "env";
public static final String APP_ID = "app.id";
public static final String VERSION = "version";
public static final String DEFAULT_VERSION_NAME = "latest-release";
public static final String ENV = "env";
}
......@@ -5,17 +5,17 @@ package com.ctrip.apollo.client.enums;
* @author Jason Song(song_s@ctrip.com)
*/
public enum PropertyChangeType {
NEW("New"),
MODIFIED("Modified"),
DELETED("Deleted");
NEW("New"),
MODIFIED("Modified"),
DELETED("Deleted");
private String type;
private String type;
PropertyChangeType(String type) {
this.type = type;
}
PropertyChangeType(String type) {
this.type = type;
}
public String getType() {
return type;
}
public String getType() {
return type;
}
}
package com.ctrip.apollo.client.env;
import com.ctrip.apollo.Apollo;
import com.ctrip.apollo.Apollo.Env;
import com.ctrip.apollo.client.constants.Constants;
import com.ctrip.apollo.core.MetaDomainConsts;
import com.ctrip.apollo.core.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
......@@ -10,20 +19,11 @@ import java.util.Enumeration;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ctrip.apollo.Apollo;
import com.ctrip.apollo.Apollo.Env;
import com.ctrip.apollo.client.constants.Constants;
import com.ctrip.apollo.core.MetaDomainConsts;
import com.ctrip.apollo.core.utils.StringUtils;
public class ClientEnvironment {
private static final Logger logger = LoggerFactory.getLogger(ClientEnvironment.class);
private final static String DEFAULT_FILE = "/apollo.properties";
private static final String DEFAULT_FILE = "/apollo.properties";
private AtomicReference<Env> env = new AtomicReference<Env>();
......@@ -84,20 +84,20 @@ public class ClientEnvironment {
props.load(in);
in.close();
}
} catch (Exception e) {
logger.warn("Reading config failed: {}", e.getMessage());
} catch (Exception ex) {
logger.warn("Reading config failed: {}", ex.getMessage());
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
logger.warn("Close config failed: {}", e.getMessage());
} catch (IOException ex) {
logger.warn("Close config failed: {}", ex.getMessage());
}
}
}
StringBuilder sb = new StringBuilder();
for (Enumeration<String> e = (Enumeration<String>) props.propertyNames(); e
.hasMoreElements();) {
.hasMoreElements(); ) {
String key = e.nextElement();
String val = (String) props.getProperty(key);
sb.append(key).append('=').append(val).append('\n');
......
......@@ -7,7 +7,7 @@ import com.ctrip.apollo.core.dto.ApolloConfig;
* @author Jason Song(songs_ctrip.com)
*/
public interface ConfigLoader {
ApolloConfig loadApolloConfig(ApolloRegistry apolloRegistry, ApolloConfig previous);
ApolloConfig loadApolloConfig(ApolloRegistry apolloRegistry, ApolloConfig previous);
void setFallBackLoader(ConfigLoader configLoader);
void setFallBackLoader(ConfigLoader configLoader);
}
package com.ctrip.apollo.client.loader;
import com.ctrip.apollo.client.loader.impl.InMemoryConfigLoader;
import com.ctrip.apollo.client.loader.impl.LocalFileConfigLoader;
import com.ctrip.apollo.Apollo.Env;
import com.ctrip.apollo.client.env.ClientEnvironment;
import com.ctrip.apollo.client.loader.impl.InMemoryConfigLoader;
import com.ctrip.apollo.client.loader.impl.LocalFileConfigLoader;
import com.ctrip.apollo.client.loader.impl.RemoteConfigLoader;
import com.ctrip.apollo.client.util.ConfigUtil;
import org.springframework.web.client.RestTemplate;
/**
......@@ -14,35 +15,39 @@ import org.springframework.web.client.RestTemplate;
public class ConfigLoaderFactory {
private static ConfigLoaderFactory configLoaderFactory = new ConfigLoaderFactory();
private ConfigLoaderFactory() {}
private ConfigLoaderFactory() {
}
public static ConfigLoaderFactory getInstance() {
return configLoaderFactory;
}
public ConfigLoader getLocalFileConfigLoader() {
ConfigLoader configLoader = new LocalFileConfigLoader();
return configLoader;
}
public ConfigLoader getLocalFileConfigLoader() {
ConfigLoader configLoader = new LocalFileConfigLoader();
return configLoader;
}
public ConfigLoader getInMemoryConfigLoader() {
ConfigLoader inMemoryConfigLoader = new InMemoryConfigLoader();
inMemoryConfigLoader.setFallBackLoader(getLocalFileConfigLoader());
return inMemoryConfigLoader;
}
public ConfigLoader getInMemoryConfigLoader() {
ConfigLoader inMemoryConfigLoader = new InMemoryConfigLoader();
inMemoryConfigLoader.setFallBackLoader(getLocalFileConfigLoader());
return inMemoryConfigLoader;
}
public ConfigLoader getRemoteConfigLoader() {
ConfigLoader remoteConfigLoader = new RemoteConfigLoader(new RestTemplate(), ConfigUtil.getInstance(), new ConfigServiceLocator());
public ConfigLoader getRemoteConfigLoader() {
ConfigLoader
remoteConfigLoader =
new RemoteConfigLoader(new RestTemplate(), ConfigUtil.getInstance(),
new ConfigServiceLocator());
// remoteConfigLoader.setFallBackLoader(getInMemoryConfigLoader());
return remoteConfigLoader;
}
return remoteConfigLoader;
}
public ConfigLoaderManager getConfigLoaderManager() {
ClientEnvironment env = ClientEnvironment.getInstance();
if (env.getEnv().equals(Env.LOCAL)) {
return new ConfigLoaderManager(getLocalFileConfigLoader(), ConfigUtil.getInstance());
} else {
return new ConfigLoaderManager(getRemoteConfigLoader(), ConfigUtil.getInstance());
}
public ConfigLoaderManager getConfigLoaderManager() {
ClientEnvironment env = ClientEnvironment.getInstance();
if (env.getEnv().equals(Env.LOCAL)) {
return new ConfigLoaderManager(getLocalFileConfigLoader(), ConfigUtil.getInstance());
} else {
return new ConfigLoaderManager(getRemoteConfigLoader(), ConfigUtil.getInstance());
}
}
}
package com.ctrip.apollo.client.loader;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.ctrip.apollo.client.enums.PropertyChangeType;
import com.ctrip.apollo.client.model.ApolloRegistry;
import com.ctrip.apollo.client.model.PropertyChange;
import com.ctrip.apollo.client.model.PropertySourceReloadResult;
import com.ctrip.apollo.client.util.ConfigUtil;
import com.ctrip.apollo.core.dto.ApolloConfig;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.CompositePropertySource;
......@@ -19,172 +21,186 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class ConfigLoaderManager {
public static final String APOLLO_PROPERTY_SOURCE_NAME = "ApolloConfigProperties";
private static final Logger logger = LoggerFactory.getLogger(ConfigLoaderManager.class);
private ConfigLoader configLoader;
private ConfigUtil configUtil;
private final ExecutorService executorService;
private final AtomicLong counter;
private Map<ApolloRegistry, ApolloConfig> currentApolloRegistryConfigCache;
private Map<ApolloRegistry, ApolloConfig> previousApolloRegistryConfigCache;
private List<ApolloRegistry> apolloRegistries;
public ConfigLoaderManager(ConfigLoader configLoader, ConfigUtil configUtil) {
this.configLoader = configLoader;
this.configUtil = configUtil;
this.counter = new AtomicLong();
this.executorService = Executors.newFixedThreadPool(5, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, "ConfigLoaderManager-" + counter.incrementAndGet());
return thread;
}
});
this.currentApolloRegistryConfigCache = Maps.newConcurrentMap();
public static final String APOLLO_PROPERTY_SOURCE_NAME = "ApolloConfigProperties";
private static final Logger logger = LoggerFactory.getLogger(ConfigLoaderManager.class);
private ConfigLoader configLoader;
private ConfigUtil configUtil;
private final ExecutorService executorService;
private final AtomicLong counter;
private Map<ApolloRegistry, ApolloConfig> currentApolloRegistryConfigCache;
private Map<ApolloRegistry, ApolloConfig> previousApolloRegistryConfigCache;
private List<ApolloRegistry> apolloRegistries;
public ConfigLoaderManager(ConfigLoader configLoader, ConfigUtil configUtil) {
this.configLoader = configLoader;
this.configUtil = configUtil;
this.counter = new AtomicLong();
this.executorService = Executors.newFixedThreadPool(5, new ThreadFactory() {
@Override
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable, "ConfigLoaderManager-" + counter.incrementAndGet());
return thread;
}
});
this.currentApolloRegistryConfigCache = Maps.newConcurrentMap();
}
public CompositePropertySource loadPropertySource() {
try {
apolloRegistries = configUtil.loadApolloRegistries();
} catch (IOException ex) {
throw new RuntimeException("Load apollo config registry failed", ex);
}
public CompositePropertySource loadPropertySource() {
try {
apolloRegistries = configUtil.loadApolloRegistries();
} catch (IOException e) {
throw new RuntimeException("Load apollo config registry failed", e);
}
return loadPropertySourceWithApolloRegistries(apolloRegistries);
}
public PropertySourceReloadResult reloadPropertySource() {
CompositePropertySource composite = loadPropertySourceWithApolloRegistries(apolloRegistries);
List<ApolloConfig> previous = Lists.newArrayList(this.previousApolloRegistryConfigCache.values());
List<ApolloConfig> current = Lists.newArrayList(this.currentApolloRegistryConfigCache.values());
return new PropertySourceReloadResult(composite, calcPropertyChanges(previous, current));
return loadPropertySourceWithApolloRegistries(apolloRegistries);
}
public PropertySourceReloadResult reloadPropertySource() {
CompositePropertySource composite = loadPropertySourceWithApolloRegistries(apolloRegistries);
List<ApolloConfig>
previous =
Lists.newArrayList(this.previousApolloRegistryConfigCache.values());
List<ApolloConfig> current = Lists.newArrayList(this.currentApolloRegistryConfigCache.values());
return new PropertySourceReloadResult(composite, calcPropertyChanges(previous, current));
}
/**
* Load property source with apollo registries provided
* Should not be invoked in parallel since there are some operations like create/destroy cache,
* writing to files etc.
*/
private synchronized CompositePropertySource loadPropertySourceWithApolloRegistries(
List<ApolloRegistry> apolloRegistries) {
resetApolloRegistryConfigCache();
CompositePropertySource composite = new CompositePropertySource(APOLLO_PROPERTY_SOURCE_NAME);
if (apolloRegistries == null || apolloRegistries.isEmpty()) {
logger.warn("No Apollo Registry found!");
return composite;
}
/**
* Load property source with apollo registries provided
* Should not be invoked in parallel since there are some operations like create/destroy cache,
* writing to files etc.
* @param apolloRegistries
* @return
*/
private synchronized CompositePropertySource loadPropertySourceWithApolloRegistries(List<ApolloRegistry> apolloRegistries) {
resetApolloRegistryConfigCache();
CompositePropertySource composite = new CompositePropertySource(APOLLO_PROPERTY_SOURCE_NAME);
if (apolloRegistries == null || apolloRegistries.isEmpty()) {
logger.warn("No Apollo Registry found!");
return composite;
}
try {
List<ApolloConfig> apolloConfigList = loadApolloConfigs(apolloRegistries);
Collections.sort(apolloConfigList);
for (ApolloConfig apolloConfig : apolloConfigList) {
composite.addPropertySource(new MapPropertySource(assemblePropertySourceName(apolloConfig), apolloConfig.getConfigurations()));
}
return composite;
} catch (Throwable throwable) {
throw new RuntimeException("Load apollo configs failed", throwable);
}
try {
List<ApolloConfig> apolloConfigList = loadApolloConfigs(apolloRegistries);
Collections.sort(apolloConfigList);
for (ApolloConfig apolloConfig : apolloConfigList) {
composite.addPropertySource(new MapPropertySource(assemblePropertySourceName(apolloConfig),
apolloConfig.getConfigurations()));
}
return composite;
} catch (Throwable throwable) {
throw new RuntimeException("Load apollo configs failed", throwable);
}
}
List<PropertyChange> calcPropertyChanges(List<ApolloConfig> previous, List<ApolloConfig> current) {
Map<String, Object> previousMap = collectConfigurations(previous);
Map<String, Object> currentMap = collectConfigurations(current);
List<PropertyChange> calcPropertyChanges(List<ApolloConfig> previous,
List<ApolloConfig> current) {
Map<String, Object> previousMap = collectConfigurations(previous);
Map<String, Object> currentMap = collectConfigurations(current);
Set<String> previousKeys = previousMap.keySet();
Set<String> currentKeys = currentMap.keySet();
Set<String> previousKeys = previousMap.keySet();
Set<String> currentKeys = currentMap.keySet();
Set<String> commonKeys = Sets.intersection(previousKeys, currentKeys);
Set<String> newKeys = Sets.difference(currentKeys, commonKeys);
Set<String> removedKeys = Sets.difference(previousKeys, commonKeys);
Set<String> commonKeys = Sets.intersection(previousKeys, currentKeys);
Set<String> newKeys = Sets.difference(currentKeys, commonKeys);
Set<String> removedKeys = Sets.difference(previousKeys, commonKeys);
List<PropertyChange> changes = Lists.newArrayList();
for (String newKey : newKeys) {
changes.add(new PropertyChange(newKey, null, currentMap.get(newKey), PropertyChangeType.NEW));
}
List<PropertyChange> changes = Lists.newArrayList();
for (String removedKey : removedKeys) {
changes.add(new PropertyChange(removedKey, previousMap.get(removedKey), null, PropertyChangeType.DELETED));
}
for (String commonKey : commonKeys) {
if (previousMap.get(commonKey).equals(currentMap.get(commonKey))) {
continue;
}
changes.add(new PropertyChange(commonKey, previousMap.get(commonKey), currentMap.get(commonKey), PropertyChangeType.MODIFIED));
}
for (String newKey : newKeys) {
changes.add(new PropertyChange(newKey, null, currentMap.get(newKey), PropertyChangeType.NEW));
}
return changes;
for (String removedKey : removedKeys) {
changes.add(new PropertyChange(removedKey, previousMap.get(removedKey), null,
PropertyChangeType.DELETED));
}
Map<String, Object> collectConfigurations(List<ApolloConfig> apolloConfigs) {
Collections.sort(apolloConfigs);
Map<String, Object> configMap = Maps.newHashMap();
for (int i = apolloConfigs.size() - 1; i > -1; i--) {
configMap.putAll(apolloConfigs.get(i).getConfigurations());
}
return configMap;
for (String commonKey : commonKeys) {
if (previousMap.get(commonKey).equals(currentMap.get(commonKey))) {
continue;
}
changes.add(
new PropertyChange(commonKey, previousMap.get(commonKey), currentMap.get(commonKey),
PropertyChangeType.MODIFIED));
}
List<ApolloConfig> loadApolloConfigs(List<ApolloRegistry> apolloRegistries) throws Throwable {
List<Future<ApolloConfig>> futures = Lists.newArrayList();
for (final ApolloRegistry apolloRegistry : apolloRegistries) {
futures.add(executorService.submit(new Callable<ApolloConfig>() {
@Override
public ApolloConfig call() throws Exception {
return loadSingleApolloConfig(apolloRegistry);
}
}));
}
List<ApolloConfig> apolloConfigList = Lists.newArrayList();
for (Future<ApolloConfig> future : futures) {
try {
ApolloConfig result = future.get();
if (result == null) {
continue;
}
apolloConfigList.add(result);
} catch (ExecutionException e) {
throw e.getCause();
}
return changes;
}
Map<String, Object> collectConfigurations(List<ApolloConfig> apolloConfigs) {
Collections.sort(apolloConfigs);
Map<String, Object> configMap = Maps.newHashMap();
for (int i = apolloConfigs.size() - 1; i > -1; i--) {
configMap.putAll(apolloConfigs.get(i).getConfigurations());
}
return configMap;
}
List<ApolloConfig> loadApolloConfigs(List<ApolloRegistry> apolloRegistries) throws Throwable {
List<Future<ApolloConfig>> futures = Lists.newArrayList();
for (final ApolloRegistry apolloRegistry : apolloRegistries) {
futures.add(executorService.submit(new Callable<ApolloConfig>() {
@Override
public ApolloConfig call() throws Exception {
return loadSingleApolloConfig(apolloRegistry);
}
return apolloConfigList;
}));
}
ApolloConfig loadSingleApolloConfig(ApolloRegistry apolloRegistry) {
ApolloConfig result = configLoader.loadApolloConfig(apolloRegistry, getPreviousApolloConfig(apolloRegistry));
List<ApolloConfig> apolloConfigList = Lists.newArrayList();
for (Future<ApolloConfig> future : futures) {
try {
ApolloConfig result = future.get();
if (result == null) {
logger.error("Loaded config null...");
return null;
continue;
}
logger.info("Loaded config: {}", result);
updateCurrentApolloConfigCache(apolloRegistry, result);
return result;
apolloConfigList.add(result);
} catch (ExecutionException ex) {
throw ex.getCause();
}
}
void resetApolloRegistryConfigCache() {
this.previousApolloRegistryConfigCache = currentApolloRegistryConfigCache;
this.currentApolloRegistryConfigCache = Maps.newConcurrentMap();
return apolloConfigList;
}
ApolloConfig loadSingleApolloConfig(ApolloRegistry apolloRegistry) {
ApolloConfig
result =
configLoader.loadApolloConfig(apolloRegistry, getPreviousApolloConfig(apolloRegistry));
if (result == null) {
logger.error("Loaded config null...");
return null;
}
logger.info("Loaded config: {}", result);
updateCurrentApolloConfigCache(apolloRegistry, result);
ApolloConfig getPreviousApolloConfig(ApolloRegistry apolloRegistry) {
return previousApolloRegistryConfigCache.get(apolloRegistry);
}
return result;
}
void updateCurrentApolloConfigCache(ApolloRegistry apolloRegistry, ApolloConfig apolloConfig) {
currentApolloRegistryConfigCache.put(apolloRegistry, apolloConfig);
}
void resetApolloRegistryConfigCache() {
this.previousApolloRegistryConfigCache = currentApolloRegistryConfigCache;
this.currentApolloRegistryConfigCache = Maps.newConcurrentMap();
}
private String assemblePropertySourceName(ApolloConfig apolloConfig) {
return String.format("%d-%s-%s-%d", apolloConfig.getAppId(), apolloConfig.getCluster(), apolloConfig.getVersion(), apolloConfig.getReleaseId());
}
ApolloConfig getPreviousApolloConfig(ApolloRegistry apolloRegistry) {
return previousApolloRegistryConfigCache.get(apolloRegistry);
}
void updateCurrentApolloConfigCache(ApolloRegistry apolloRegistry, ApolloConfig apolloConfig) {
currentApolloRegistryConfigCache.put(apolloRegistry, apolloConfig);
}
private String assemblePropertySourceName(ApolloConfig apolloConfig) {
return String.format("%d-%s-%s-%d", apolloConfig.getAppId(), apolloConfig.getCluster(),
apolloConfig.getVersion(), apolloConfig.getReleaseId());
}
}
package com.ctrip.apollo.client.loader;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import com.ctrip.apollo.client.env.ClientEnvironment;
import com.ctrip.apollo.core.serivce.ApolloService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.client.RestTemplate;
import com.ctrip.apollo.client.env.ClientEnvironment;
import com.ctrip.apollo.core.serivce.ApolloService;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
public class ConfigServiceLocator {
......@@ -31,8 +31,8 @@ public class ConfigServiceLocator {
serviceCaches.add(service);
}
}
} catch (Exception e) {
logger.warn(e.getMessage());
} catch (Exception ex) {
logger.warn(ex.getMessage());
}
return serviceCaches;
}
......
......@@ -3,6 +3,7 @@ package com.ctrip.apollo.client.loader.impl;
import com.ctrip.apollo.client.loader.ConfigLoader;
import com.ctrip.apollo.client.model.ApolloRegistry;
import com.ctrip.apollo.core.dto.ApolloConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -10,26 +11,29 @@ import org.slf4j.LoggerFactory;
* @author Jason Song(song_s@ctrip.com)
*/
public abstract class AbstractConfigLoader implements ConfigLoader {
private static final Logger logger = LoggerFactory.getLogger(AbstractConfigLoader.class);
private ConfigLoader fallback;
private static final Logger logger = LoggerFactory.getLogger(AbstractConfigLoader.class);
private ConfigLoader fallback;
@Override
public ApolloConfig loadApolloConfig(ApolloRegistry apolloRegistry, ApolloConfig previous) {
try {
return doLoadApolloConfig(apolloRegistry, previous);
} catch (Throwable e) {
if (this.fallback == null) {
throw new RuntimeException(String.format("Load Apollo Config failed - %s", apolloRegistry.toString()), e);
}
logger.error("Load Config via {} failed, try to use its fallback {} to load", getClass().getSimpleName(), fallback.getClass().getSimpleName(), e);
return this.fallback.loadApolloConfig(apolloRegistry, previous);
}
@Override
public ApolloConfig loadApolloConfig(ApolloRegistry apolloRegistry, ApolloConfig previous) {
try {
return doLoadApolloConfig(apolloRegistry, previous);
} catch (Throwable ex) {
if (this.fallback == null) {
throw new RuntimeException(
String.format("Load Apollo Config failed - %s", apolloRegistry.toString()), ex);
}
logger.error("Load Config via {} failed, try to use its fallback {} to load",
getClass().getSimpleName(), fallback.getClass().getSimpleName(), ex);
return this.fallback.loadApolloConfig(apolloRegistry, previous);
}
}
protected abstract ApolloConfig doLoadApolloConfig(ApolloRegistry apolloRegistry, ApolloConfig previous);
protected abstract ApolloConfig doLoadApolloConfig(ApolloRegistry apolloRegistry,
ApolloConfig previous);
@Override
public void setFallBackLoader(ConfigLoader configLoader) {
this.fallback = configLoader;
}
@Override
public void setFallBackLoader(ConfigLoader configLoader) {
this.fallback = configLoader;
}
}
......@@ -6,10 +6,10 @@ import com.ctrip.apollo.core.dto.ApolloConfig;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class InMemoryConfigLoader extends AbstractConfigLoader{
public class InMemoryConfigLoader extends AbstractConfigLoader {
@Override
protected ApolloConfig doLoadApolloConfig(ApolloRegistry apolloRegistry, ApolloConfig previous) {
return null;
}
@Override
protected ApolloConfig doLoadApolloConfig(ApolloRegistry apolloRegistry, ApolloConfig previous) {
return null;
}
}
......@@ -5,11 +5,12 @@ import com.ctrip.apollo.core.dto.ApolloConfig;
/**
* Load config from local backup file
*
* @author Jason Song(song_s@ctrip.com)
*/
public class LocalFileConfigLoader extends AbstractConfigLoader{
@Override
public ApolloConfig doLoadApolloConfig(ApolloRegistry apolloRegistry, ApolloConfig previous) {
return null;
}
public class LocalFileConfigLoader extends AbstractConfigLoader {
@Override
public ApolloConfig doLoadApolloConfig(ApolloRegistry apolloRegistry, ApolloConfig previous) {
return null;
}
}
package com.ctrip.apollo.client.loader.impl;
import com.google.common.collect.Maps;
import com.ctrip.apollo.client.loader.ConfigServiceLocator;
import com.ctrip.apollo.client.model.ApolloRegistry;
import com.ctrip.apollo.client.util.ConfigUtil;
import com.ctrip.apollo.core.dto.ApolloConfig;
import com.ctrip.apollo.core.serivce.ApolloService;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
......@@ -24,76 +26,80 @@ import java.util.Map;
* @author Jason Song(song_s@ctrip.com)
*/
public class RemoteConfigLoader extends AbstractConfigLoader {
private static final Logger logger = LoggerFactory.getLogger(RemoteConfigLoader.class);
private final RestTemplate restTemplate;
private final ConfigUtil configUtil;
private final ConfigServiceLocator serviceLocator;
public RemoteConfigLoader(RestTemplate restTemplate, ConfigUtil configUtil, ConfigServiceLocator locator) {
this.restTemplate = restTemplate;
this.configUtil = configUtil;
this.serviceLocator = locator;
private static final Logger logger = LoggerFactory.getLogger(RemoteConfigLoader.class);
private final RestTemplate restTemplate;
private final ConfigUtil configUtil;
private final ConfigServiceLocator serviceLocator;
public RemoteConfigLoader(RestTemplate restTemplate, ConfigUtil configUtil,
ConfigServiceLocator locator) {
this.restTemplate = restTemplate;
this.configUtil = configUtil;
this.serviceLocator = locator;
}
ApolloConfig getRemoteConfig(RestTemplate restTemplate, String uri, String cluster,
ApolloRegistry apolloRegistry, ApolloConfig previousConfig) {
long appId = apolloRegistry.getAppId();
String version = apolloRegistry.getVersion();
logger.info("Loading config from {}, appId={}, cluster={}, version={}", uri, appId, cluster,
version);
String path = "/config/{appId}/{cluster}";
Map<String, Object> paramMap = Maps.newHashMap();
paramMap.put("appId", appId);
paramMap.put("cluster", cluster);
if (StringUtils.hasText(version)) {
path = path + "/{version}";
paramMap.put("version", version);
}
if (previousConfig != null) {
path = path + "?releaseId={releaseId}";
paramMap.put("releaseId", previousConfig.getReleaseId());
}
ApolloConfig getRemoteConfig(RestTemplate restTemplate, String uri, String cluster, ApolloRegistry apolloRegistry, ApolloConfig previousConfig) {
long appId = apolloRegistry.getAppId();
String version = apolloRegistry.getVersion();
logger.info("Loading config from {}, appId={}, cluster={}, version={}", uri, appId, cluster, version);
String path = "/config/{appId}/{cluster}";
Map<String, Object> paramMap = Maps.newHashMap();
paramMap.put("appId", appId);
paramMap.put("cluster", cluster);
if (StringUtils.hasText(version)) {
path = path + "/{version}";
paramMap.put("version", version);
}
if (previousConfig != null) {
path = path + "?releaseId={releaseId}";
paramMap.put("releaseId", previousConfig.getReleaseId());
}
ResponseEntity<ApolloConfig> response;
try {
// TODO retry
response = restTemplate.exchange(uri
+ path, HttpMethod.GET, new HttpEntity<Void>((Void) null), ApolloConfig.class, paramMap);
} catch (Throwable e) {
throw e;
}
if (response == null) {
throw new RuntimeException("Load apollo config failed, response is null");
}
if (response.getStatusCode() == HttpStatus.NOT_MODIFIED) {
return null;
}
if (response.getStatusCode() != HttpStatus.OK) {
throw new RuntimeException(String.format("Load apollo config failed, response status %s", response.getStatusCode()));
}
ApolloConfig result = response.getBody();
return result;
ResponseEntity<ApolloConfig> response;
try {
// TODO retry
response = restTemplate.exchange(uri
+ path, HttpMethod.GET, new HttpEntity<Void>((Void) null), ApolloConfig.class, paramMap);
} catch (Throwable ex) {
throw ex;
}
if (response == null) {
throw new RuntimeException("Load apollo config failed, response is null");
}
if (response.getStatusCode() == HttpStatus.NOT_MODIFIED) {
return null;
}
@Override
protected ApolloConfig doLoadApolloConfig(ApolloRegistry apolloRegistry, ApolloConfig previous) {
ApolloConfig result = this.getRemoteConfig(restTemplate,
getConfigServiceUrl(), configUtil.getCluster(),
apolloRegistry, previous);
//When remote server return 304, we need to return the previous result
return result == null ? previous : result;
if (response.getStatusCode() != HttpStatus.OK) {
throw new RuntimeException(
String.format("Load apollo config failed, response status %s", response.getStatusCode()));
}
ApolloConfig result = response.getBody();
return result;
}
@Override
protected ApolloConfig doLoadApolloConfig(ApolloRegistry apolloRegistry, ApolloConfig previous) {
ApolloConfig result = this.getRemoteConfig(restTemplate,
getConfigServiceUrl(), configUtil.getCluster(),
apolloRegistry, previous);
//When remote server return 304, we need to return the previous result
return result == null ? previous : result;
}
private String getConfigServiceUrl() {
List<ApolloService> services = serviceLocator.getConfigServices();
if (services.size() == 0) {
throw new RuntimeException("No available config service");
}
private String getConfigServiceUrl() {
List<ApolloService> services = serviceLocator.getConfigServices();
if(services.size()==0){
throw new RuntimeException("No available config service");
}
return services.get(0).getHomepageUrl();
}
}
\ No newline at end of file
return services.get(0).getHomepageUrl();
}
}
......@@ -6,31 +6,31 @@ import com.google.common.base.MoreObjects;
* @author Jason Song(song_s@ctrip.com)
*/
public class ApolloRegistry {
private long appId;
private String version;
private long appId;
private String version;
public long getAppId() {
return appId;
}
public long getAppId() {
return appId;
}
public void setAppId(long appId) {
this.appId = appId;
}
public void setAppId(long appId) {
this.appId = appId;
}
public String getVersion() {
return version;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public void setVersion(String version) {
this.version = version;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.omitNullValues()
.add("appId", appId)
.add("version", version)
.toString();
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.omitNullValues()
.add("appId", appId)
.add("version", version)
.toString();
}
}
......@@ -6,47 +6,48 @@ import com.ctrip.apollo.client.enums.PropertyChangeType;
* @author Jason Song(song_s@ctrip.com)
*/
public class PropertyChange {
private String propertyName;
private Object oldValue;
private Object newValue;
private PropertyChangeType changeType;
public PropertyChange(String propertyName, Object oldValue, Object newValue, PropertyChangeType changeType) {
this.propertyName = propertyName;
this.oldValue = oldValue;
this.newValue = newValue;
this.changeType = changeType;
}
public String getPropertyName() {
return propertyName;
}
public void setPropertyName(String propertyName) {
this.propertyName = propertyName;
}
public Object getOldValue() {
return oldValue;
}
public void setOldValue(Object oldValue) {
this.oldValue = oldValue;
}
public Object getNewValue() {
return newValue;
}
public void setNewValue(Object newValue) {
this.newValue = newValue;
}
public PropertyChangeType getChangeType() {
return changeType;
}
public void setChangeType(PropertyChangeType changeType) {
this.changeType = changeType;
}
private String propertyName;
private Object oldValue;
private Object newValue;
private PropertyChangeType changeType;
public PropertyChange(String propertyName, Object oldValue, Object newValue,
PropertyChangeType changeType) {
this.propertyName = propertyName;
this.oldValue = oldValue;
this.newValue = newValue;
this.changeType = changeType;
}
public String getPropertyName() {
return propertyName;
}
public void setPropertyName(String propertyName) {
this.propertyName = propertyName;
}
public Object getOldValue() {
return oldValue;
}
public void setOldValue(Object oldValue) {
this.oldValue = oldValue;
}
public Object getNewValue() {
return newValue;
}
public void setNewValue(Object newValue) {
this.newValue = newValue;
}
public PropertyChangeType getChangeType() {
return changeType;
}
public void setChangeType(PropertyChangeType changeType) {
this.changeType = changeType;
}
}
package com.ctrip.apollo.client.model;
import com.google.common.collect.Lists;
import org.springframework.core.env.CompositePropertySource;
import java.util.List;
......@@ -9,36 +10,37 @@ import java.util.List;
* @author Jason Song(song_s@ctrip.com)
*/
public class PropertySourceReloadResult {
private CompositePropertySource propertySource;
private List<PropertyChange> changes;
public PropertySourceReloadResult(CompositePropertySource propertySource) {
this.propertySource = propertySource;
changes = Lists.newArrayList();
}
public PropertySourceReloadResult(CompositePropertySource propertySource, List<PropertyChange> changes) {
this.propertySource = propertySource;
this.changes = changes;
}
public CompositePropertySource getPropertySource() {
return propertySource;
}
public void setPropertySource(CompositePropertySource propertySource) {
this.propertySource = propertySource;
}
public List<PropertyChange> getChanges() {
return changes;
}
public void setChanges(List<PropertyChange> changes) {
this.changes = changes;
}
public boolean hasChanges() {
return !changes.isEmpty();
}
private CompositePropertySource propertySource;
private List<PropertyChange> changes;
public PropertySourceReloadResult(CompositePropertySource propertySource) {
this.propertySource = propertySource;
changes = Lists.newArrayList();
}
public PropertySourceReloadResult(CompositePropertySource propertySource,
List<PropertyChange> changes) {
this.propertySource = propertySource;
this.changes = changes;
}
public CompositePropertySource getPropertySource() {
return propertySource;
}
public void setPropertySource(CompositePropertySource propertySource) {
this.propertySource = propertySource;
}
public List<PropertyChange> getChanges() {
return changes;
}
public void setChanges(List<PropertyChange> changes) {
this.changes = changes;
}
public boolean hasChanges() {
return !changes.isEmpty();
}
}
......@@ -7,18 +7,18 @@ import org.slf4j.LoggerFactory;
* @author Jason Song(song_s@ctrip.com)
*/
public class ClassLoaderUtil {
private static final Logger logger = LoggerFactory.getLogger(ClassLoaderUtil.class);
private static final Logger logger = LoggerFactory.getLogger(ClassLoaderUtil.class);
private static ClassLoader loader = Thread.currentThread().getContextClassLoader();
private static ClassLoader loader = Thread.currentThread().getContextClassLoader();
static {
if (loader == null) {
logger.info("Using system class loader");
loader = ClassLoader.getSystemClassLoader();
}
static {
if (loader == null) {
logger.info("Using system class loader");
loader = ClassLoader.getSystemClassLoader();
}
}
public static ClassLoader getLoader() {
return loader;
}
public static ClassLoader getLoader() {
return loader;
}
}
package com.ctrip.apollo.client.util;
import com.ctrip.apollo.client.constants.Constants;
import com.ctrip.apollo.client.model.ApolloRegistry;
import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import com.ctrip.apollo.client.constants.Constants;
import com.ctrip.apollo.client.model.ApolloRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.EncodedResource;
......@@ -21,68 +23,69 @@ import java.util.concurrent.TimeUnit;
* @author Jason Song(song_s@ctrip.com)
*/
public class ConfigUtil {
public static final String APOLLO_PROPERTY = "apollo.properties";
//TODO read from config?
private static final int refreshInterval = 5;
private static final TimeUnit refreshIntervalTimeUnit = TimeUnit.MINUTES;
public static final String APOLLO_PROPERTY = "apollo.properties";
//TODO read from config?
private static final int refreshInterval = 5;
private static final TimeUnit refreshIntervalTimeUnit = TimeUnit.MINUTES;
private static ConfigUtil configUtil = new ConfigUtil();
private ApplicationContext applicationContext;
private ConfigUtil() {
}
private static ConfigUtil configUtil = new ConfigUtil();
private ApplicationContext applicationContext;
public static ConfigUtil getInstance() {
return configUtil;
}
private ConfigUtil() {
}
public String getCluster() {
// TODO return the actual cluster
return "default";
}
public static ConfigUtil getInstance() {
return configUtil;
}
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public String getCluster() {
// TODO return the actual cluster
return "default";
}
public int getRefreshInterval() {
return refreshInterval;
}
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public TimeUnit getRefreshTimeUnit() {
return refreshIntervalTimeUnit;
}
public int getRefreshInterval() {
return refreshInterval;
}
public List<ApolloRegistry> loadApolloRegistries() throws IOException {
List<URL> resourceUrls =
Collections.list(ClassLoaderUtil.getLoader().getResources(APOLLO_PROPERTY));
List<ApolloRegistry> registries =
FluentIterable.from(resourceUrls).transform(new Function<URL, ApolloRegistry>() {
@Override
public ApolloRegistry apply(URL input) {
Properties properties = loadPropertiesFromResourceURL(input);
if (properties == null || !properties.containsKey(Constants.APP_ID)) {
return null;
}
ApolloRegistry registry = new ApolloRegistry();
registry.setAppId(Long.parseLong(properties.getProperty(Constants.APP_ID)));
registry.setVersion(properties.getProperty(Constants.VERSION, Constants.DEFAULT_VERSION_NAME));
return registry;
}
}).filter(Predicates.notNull()).toList();
return registries;
}
public TimeUnit getRefreshTimeUnit() {
return refreshIntervalTimeUnit;
}
public List<ApolloRegistry> loadApolloRegistries() throws IOException {
List<URL> resourceUrls =
Collections.list(ClassLoaderUtil.getLoader().getResources(APOLLO_PROPERTY));
List<ApolloRegistry> registries =
FluentIterable.from(resourceUrls).transform(new Function<URL, ApolloRegistry>() {
@Override
public ApolloRegistry apply(URL input) {
Properties properties = loadPropertiesFromResourceURL(input);
if (properties == null || !properties.containsKey(Constants.APP_ID)) {
return null;
}
ApolloRegistry registry = new ApolloRegistry();
registry.setAppId(Long.parseLong(properties.getProperty(Constants.APP_ID)));
registry.setVersion(
properties.getProperty(Constants.VERSION, Constants.DEFAULT_VERSION_NAME));
return registry;
}
}).filter(Predicates.notNull()).toList();
return registries;
}
Properties loadPropertiesFromResourceURL(URL resourceUrl) {
Resource resource = applicationContext.getResource(resourceUrl.toExternalForm());
if (resource == null || !resource.exists()) {
return null;
}
try {
return PropertiesLoaderUtils.loadProperties(new EncodedResource(resource, "UTF-8"));
} catch (IOException e) {
e.printStackTrace();
}
return null;
Properties loadPropertiesFromResourceURL(URL resourceUrl) {
Resource resource = applicationContext.getResource(resourceUrl.toExternalForm());
if (resource == null || !resource.exists()) {
return null;
}
try {
return PropertiesLoaderUtils.loadProperties(new EncodedResource(resource, "UTF-8"));
} catch (IOException ex) {
ex.printStackTrace();
}
return null;
}
}
......@@ -3,14 +3,15 @@ package com.ctrip.apollo.client;
import com.ctrip.apollo.client.loader.ConfigLoaderManagerTest;
import com.ctrip.apollo.client.loader.impl.RemoteConfigLoaderTest;
import com.ctrip.apollo.client.util.ConfigUtilTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({
ApolloConfigManagerTest.class, ConfigLoaderManagerTest.class, RemoteConfigLoaderTest.class,
ConfigUtilTest.class
ApolloConfigManagerTest.class, ConfigLoaderManagerTest.class, RemoteConfigLoaderTest.class,
ConfigUtilTest.class
})
public class AllTests {
......
......@@ -3,6 +3,7 @@ package com.ctrip.apollo.client;
import com.ctrip.apollo.client.loader.ConfigLoaderManager;
import com.ctrip.apollo.client.model.PropertyChange;
import com.ctrip.apollo.client.model.PropertySourceReloadResult;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
......@@ -25,110 +26,126 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith(MockitoJUnitRunner.class)
public class ApolloConfigManagerTest {
private ApolloConfigManager apolloConfigManager;
@Mock
private ConfigLoaderManager configLoaderManager;
@Mock
private ConfigurableApplicationContext applicationContext;
@Mock
private ConfigurableEnvironment env;
@Mock
private MutablePropertySources mutablePropertySources;
@Mock
private BeanDefinitionRegistry beanDefinitionRegistry;
@Mock
private RefreshScope scope;
@Before
public void setUp() {
apolloConfigManager = spy(new ApolloConfigManager());
when(applicationContext.getEnvironment()).thenReturn(env);
when(env.getPropertySources()).thenReturn(mutablePropertySources);
apolloConfigManager.setApplicationContext(applicationContext);
ReflectionTestUtils.setField(apolloConfigManager, "configLoaderManager", configLoaderManager);
ReflectionTestUtils.setField(apolloConfigManager, "scope", scope);
}
@After
public void tearDown() throws Exception {
AtomicReference<ApolloConfigManager> singletonProtector =
(AtomicReference<ApolloConfigManager>)ReflectionTestUtils.getField(ApolloConfigManager.class, "singletonProtector");
singletonProtector.set(null);
}
@Test(expected = RuntimeException.class)
public void testInvalidApplicationContext() {
ApplicationContext someInvalidApplication = mock(ApplicationContext.class);
apolloConfigManager.setApplicationContext(someInvalidApplication);
}
@Test
public void testInitializePropertySourceSuccessfully() {
CompositePropertySource somePropertySource = mock(CompositePropertySource.class);
final ArgumentCaptor<CompositePropertySource> captor = ArgumentCaptor.forClass(CompositePropertySource.class);
when(configLoaderManager.loadPropertySource()).thenReturn(somePropertySource);
apolloConfigManager.initializePropertySource();
verify(configLoaderManager, times(1)).loadPropertySource();
verify(mutablePropertySources, times(1)).addFirst(captor.capture());
final CompositePropertySource insertedPropertySource = captor.getValue();
assertEquals(insertedPropertySource, somePropertySource);
}
@Test
public void testPostProcessBeanDefinitionRegistry() {
doNothing().when(apolloConfigManager).initializePropertySource();
apolloConfigManager.postProcessBeanDefinitionRegistry(beanDefinitionRegistry);
verify(beanDefinitionRegistry, times(2)).registerBeanDefinition(anyString(), any(BeanDefinition.class));
}
@Test
public void testUpdatePropertySourceWithChanges() throws Exception {
PropertySourceReloadResult somePropertySourceReloadResult = mock(PropertySourceReloadResult.class);
CompositePropertySource somePropertySource = mock(CompositePropertySource.class);
List<PropertyChange> someChanges = mock(List.class);
when(somePropertySourceReloadResult.hasChanges()).thenReturn(true);
when(somePropertySourceReloadResult.getPropertySource()).thenReturn(somePropertySource);
when(somePropertySourceReloadResult.getChanges()).thenReturn(someChanges);
when(configLoaderManager.reloadPropertySource()).thenReturn(somePropertySourceReloadResult);
List<PropertyChange> result = apolloConfigManager.updatePropertySource();
assertEquals(someChanges, result);
verify(scope, times(1)).refreshAll();
}
@Test
public void testUpdatePropertySourceWithNoChange() throws Exception {
PropertySourceReloadResult somePropertySourceReloadResult = mock(PropertySourceReloadResult.class);
CompositePropertySource somePropertySource = mock(CompositePropertySource.class);
List<PropertyChange> emptyChanges = Collections.emptyList();
when(somePropertySourceReloadResult.hasChanges()).thenReturn(false);
when(somePropertySourceReloadResult.getPropertySource()).thenReturn(somePropertySource);
when(somePropertySourceReloadResult.getChanges()).thenReturn(emptyChanges);
when(configLoaderManager.reloadPropertySource()).thenReturn(somePropertySourceReloadResult);
List<PropertyChange> result = apolloConfigManager.updatePropertySource();
assertEquals(emptyChanges, result);
verify(scope, never()).refreshAll();
}
private ApolloConfigManager apolloConfigManager;
@Mock
private ConfigLoaderManager configLoaderManager;
@Mock
private ConfigurableApplicationContext applicationContext;
@Mock
private ConfigurableEnvironment env;
@Mock
private MutablePropertySources mutablePropertySources;
@Mock
private BeanDefinitionRegistry beanDefinitionRegistry;
@Mock
private RefreshScope scope;
@Before
public void setUp() {
apolloConfigManager = spy(new ApolloConfigManager());
when(applicationContext.getEnvironment()).thenReturn(env);
when(env.getPropertySources()).thenReturn(mutablePropertySources);
apolloConfigManager.setApplicationContext(applicationContext);
ReflectionTestUtils.setField(apolloConfigManager, "configLoaderManager", configLoaderManager);
ReflectionTestUtils.setField(apolloConfigManager, "scope", scope);
}
@After
public void tearDown() throws Exception {
AtomicReference<ApolloConfigManager> singletonProtector =
(AtomicReference<ApolloConfigManager>) ReflectionTestUtils
.getField(ApolloConfigManager.class, "singletonProtector");
singletonProtector.set(null);
}
@Test(expected = RuntimeException.class)
public void testInvalidApplicationContext() {
ApplicationContext someInvalidApplication = mock(ApplicationContext.class);
apolloConfigManager.setApplicationContext(someInvalidApplication);
}
@Test
public void testInitializePropertySourceSuccessfully() {
CompositePropertySource somePropertySource = mock(CompositePropertySource.class);
final ArgumentCaptor<CompositePropertySource>
captor =
ArgumentCaptor.forClass(CompositePropertySource.class);
when(configLoaderManager.loadPropertySource()).thenReturn(somePropertySource);
apolloConfigManager.initializePropertySource();
verify(configLoaderManager, times(1)).loadPropertySource();
verify(mutablePropertySources, times(1)).addFirst(captor.capture());
final CompositePropertySource insertedPropertySource = captor.getValue();
assertEquals(insertedPropertySource, somePropertySource);
}
@Test
public void testPostProcessBeanDefinitionRegistry() {
doNothing().when(apolloConfigManager).initializePropertySource();
apolloConfigManager.postProcessBeanDefinitionRegistry(beanDefinitionRegistry);
verify(beanDefinitionRegistry, times(2))
.registerBeanDefinition(anyString(), any(BeanDefinition.class));
}
@Test
public void testUpdatePropertySourceWithChanges() throws Exception {
PropertySourceReloadResult
somePropertySourceReloadResult =
mock(PropertySourceReloadResult.class);
CompositePropertySource somePropertySource = mock(CompositePropertySource.class);
List<PropertyChange> someChanges = mock(List.class);
when(somePropertySourceReloadResult.hasChanges()).thenReturn(true);
when(somePropertySourceReloadResult.getPropertySource()).thenReturn(somePropertySource);
when(somePropertySourceReloadResult.getChanges()).thenReturn(someChanges);
when(configLoaderManager.reloadPropertySource()).thenReturn(somePropertySourceReloadResult);
List<PropertyChange> result = apolloConfigManager.updatePropertySource();
assertEquals(someChanges, result);
verify(scope, times(1)).refreshAll();
}
@Test
public void testUpdatePropertySourceWithNoChange() throws Exception {
PropertySourceReloadResult
somePropertySourceReloadResult =
mock(PropertySourceReloadResult.class);
CompositePropertySource somePropertySource = mock(CompositePropertySource.class);
List<PropertyChange> emptyChanges = Collections.emptyList();
when(somePropertySourceReloadResult.hasChanges()).thenReturn(false);
when(somePropertySourceReloadResult.getPropertySource()).thenReturn(somePropertySource);
when(somePropertySourceReloadResult.getChanges()).thenReturn(emptyChanges);
when(configLoaderManager.reloadPropertySource()).thenReturn(somePropertySourceReloadResult);
List<PropertyChange> result = apolloConfigManager.updatePropertySource();
assertEquals(emptyChanges, result);
verify(scope, never()).refreshAll();
}
}
package com.ctrip.apollo.client.loader;
import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ctrip.apollo.client.enums.PropertyChangeType;
import com.ctrip.apollo.client.model.ApolloRegistry;
import com.ctrip.apollo.client.model.PropertyChange;
import com.ctrip.apollo.client.model.PropertySourceReloadResult;
import com.ctrip.apollo.client.util.ConfigUtil;
import com.ctrip.apollo.core.dto.ApolloConfig;
import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.ObjectArrays;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.test.util.ReflectionTestUtils;
......@@ -26,173 +26,192 @@ import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.anyList;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith(MockitoJUnitRunner.class)
public class ConfigLoaderManagerTest {
private ConfigLoaderManager configLoaderManager;
@Mock
private ConfigLoader configLoader;
@Mock
private ConfigUtil configUtil;
@Before
public void setUp() {
configLoaderManager = spy(new ConfigLoaderManager(configLoader, configUtil));
}
@Test
public void testLoadPropertySource() throws Exception {
long someAppId = 100;
long anotherAppId = 101;
ApolloRegistry someApolloRegistry = assembleSomeApolloRegistry(someAppId, "someVersion");
ApolloRegistry anotherApolloRegistry = assembleSomeApolloRegistry(anotherAppId, "anotherVersion");
ApolloConfig someApolloConfig = mock(ApolloConfig.class);
ApolloConfig anotherApolloConfig = mock(ApolloConfig.class);
Map<String, Object> someMap = mock(Map.class);
Map<String, Object> anotherMap = mock(Map.class);
when(someApolloConfig.getAppId()).thenReturn(someAppId);
when(someApolloConfig.getAppId()).thenReturn(anotherAppId);
when(configUtil.loadApolloRegistries()).thenReturn(Lists.newArrayList(someApolloRegistry, anotherApolloRegistry));
doReturn(someApolloConfig).when(configLoaderManager).loadSingleApolloConfig(someApolloRegistry);
doReturn(anotherApolloConfig).when(configLoaderManager).loadSingleApolloConfig(anotherApolloRegistry);
when(someApolloConfig.getConfigurations()).thenReturn(someMap);
when(anotherApolloConfig.getConfigurations()).thenReturn(anotherMap);
CompositePropertySource result = configLoaderManager.loadPropertySource();
assertEquals(2, result.getPropertySources().size());
List<Map<String, Object>> resultMaps = FluentIterable.from(result.getPropertySources()).transform(new Function<PropertySource<?>, Map<String, Object>>() {
@Override
public Map<String, Object> apply(PropertySource<?> input) {
return (Map<String, Object>)input.getSource();
}
}).toList();
assertTrue(resultMaps.containsAll(Lists.newArrayList(someMap, anotherMap)));
}
@Test(expected = RuntimeException.class)
public void testLoadPropertySourceWithError() throws Exception {
Exception someException = mock(Exception.class);
long someAppId = 100;
ApolloRegistry someApolloRegistry = assembleSomeApolloRegistry(someAppId, "someVersion");
when(configUtil.loadApolloRegistries()).thenReturn(Lists.newArrayList(someApolloRegistry));
doThrow(someException).when(configLoaderManager).loadSingleApolloConfig(someApolloRegistry);
configLoaderManager.loadPropertySource();
}
@Test
public void testLoadApolloConfigsWithNoApolloRegistry() throws Exception {
when(configUtil.loadApolloRegistries()).thenReturn(null);
CompositePropertySource result = configLoaderManager.loadPropertySource();
assertTrue(result.getPropertySources().isEmpty());
}
@Test
public void testLoadSingleApolloConfig() throws Exception {
ApolloConfig someApolloConfig = mock(ApolloConfig.class);
Map<String, Object> someMap = Maps.newHashMap();
long someAppId = 100;
ApolloRegistry someApolloRegistry = assembleSomeApolloRegistry(someAppId, "someVersion");
ApolloConfig previousConfig = null;
doReturn(null).when(configLoaderManager).getPreviousApolloConfig(someApolloRegistry);
when(someApolloConfig.getConfigurations()).thenReturn(someMap);
when(configLoader.loadApolloConfig(someApolloRegistry, previousConfig)).thenReturn(someApolloConfig);
ApolloConfig result = configLoaderManager.loadSingleApolloConfig(someApolloRegistry);
assertEquals(someMap, result.getConfigurations());
}
@Test
public void testReloadPropertySource() throws Exception {
long someAppId = 100;
ApolloRegistry someApolloRegistry = assembleSomeApolloRegistry(someAppId, "someVersion");
ApolloConfig someApolloConfig = mock(ApolloConfig.class);
Map<String, Object> someMap = mock(Map.class);
List<PropertyChange> someChanges = mock(List.class);
ReflectionTestUtils.setField(configLoaderManager, "apolloRegistries", Lists.newArrayList(someApolloRegistry));
doReturn(someApolloConfig).when(configLoaderManager).loadSingleApolloConfig(someApolloRegistry);
when(someApolloConfig.getAppId()).thenReturn(someAppId);
when(someApolloConfig.getConfigurations()).thenReturn(someMap);
doReturn(someChanges).when(configLoaderManager).calcPropertyChanges(anyList(), anyList());
PropertySourceReloadResult result = configLoaderManager.reloadPropertySource();
assertEquals(1, result.getPropertySource().getPropertySources().size());
assertEquals(someChanges, result.getChanges());
List<Map<String, Object>> resultMaps = FluentIterable.from(result.getPropertySource().getPropertySources()).transform(new Function<PropertySource<?>, Map<String, Object>>() {
@Override
public Map<String, Object> apply(PropertySource<?> input) {
return (Map<String, Object>)input.getSource();
}
}).toList();
assertTrue(resultMaps.containsAll(Lists.newArrayList(someMap)));
}
@Test
public void testCalcPropertyChanges() throws Exception {
long someAppId = 1;
Map<String, Object> someConfig = Maps.newHashMap();
someConfig.put("key1", "val1");
someConfig.put("key2", "val2");
Map<String, Object> anotherConfig = Maps.newHashMap();
anotherConfig.put("key1", "val11");
anotherConfig.put("key3", "val3");
List<ApolloConfig> previous = Lists.newArrayList(assembleApolloConfig(someAppId, someConfig));
List<ApolloConfig> current = Lists.newArrayList(assembleApolloConfig(someAppId, anotherConfig));
List<PropertyChange> changes = configLoaderManager.calcPropertyChanges(previous, current);
assertEquals(3, changes.size());
List<String> changeResult = FluentIterable.from(changes).transform(new Function<PropertyChange, String>() {
@Override
public String apply(PropertyChange input) {
return String.format("%s-%s", input.getPropertyName(), input.getChangeType());
}
private ConfigLoaderManager configLoaderManager;
@Mock
private ConfigLoader configLoader;
@Mock
private ConfigUtil configUtil;
@Before
public void setUp() {
configLoaderManager = spy(new ConfigLoaderManager(configLoader, configUtil));
}
@Test
public void testLoadPropertySource() throws Exception {
long someAppId = 100;
long anotherAppId = 101;
ApolloRegistry someApolloRegistry = assembleSomeApolloRegistry(someAppId, "someVersion");
ApolloRegistry
anotherApolloRegistry =
assembleSomeApolloRegistry(anotherAppId, "anotherVersion");
ApolloConfig someApolloConfig = mock(ApolloConfig.class);
ApolloConfig anotherApolloConfig = mock(ApolloConfig.class);
Map<String, Object> someMap = mock(Map.class);
Map<String, Object> anotherMap = mock(Map.class);
when(someApolloConfig.getAppId()).thenReturn(someAppId);
when(someApolloConfig.getAppId()).thenReturn(anotherAppId);
when(configUtil.loadApolloRegistries())
.thenReturn(Lists.newArrayList(someApolloRegistry, anotherApolloRegistry));
doReturn(someApolloConfig).when(configLoaderManager).loadSingleApolloConfig(someApolloRegistry);
doReturn(anotherApolloConfig).when(configLoaderManager)
.loadSingleApolloConfig(anotherApolloRegistry);
when(someApolloConfig.getConfigurations()).thenReturn(someMap);
when(anotherApolloConfig.getConfigurations()).thenReturn(anotherMap);
CompositePropertySource result = configLoaderManager.loadPropertySource();
assertEquals(2, result.getPropertySources().size());
List<Map<String, Object>>
resultMaps =
FluentIterable.from(result.getPropertySources())
.transform(new Function<PropertySource<?>, Map<String, Object>>() {
@Override
public Map<String, Object> apply(PropertySource<?> input) {
return (Map<String, Object>) input.getSource();
}
}).toList();
assertTrue(resultMaps.containsAll(Lists.newArrayList(someMap, anotherMap)));
}
@Test(expected = RuntimeException.class)
public void testLoadPropertySourceWithError() throws Exception {
Exception someException = mock(Exception.class);
long someAppId = 100;
ApolloRegistry someApolloRegistry = assembleSomeApolloRegistry(someAppId, "someVersion");
when(configUtil.loadApolloRegistries()).thenReturn(Lists.newArrayList(someApolloRegistry));
doThrow(someException).when(configLoaderManager).loadSingleApolloConfig(someApolloRegistry);
configLoaderManager.loadPropertySource();
}
@Test
public void testLoadApolloConfigsWithNoApolloRegistry() throws Exception {
when(configUtil.loadApolloRegistries()).thenReturn(null);
CompositePropertySource result = configLoaderManager.loadPropertySource();
assertTrue(result.getPropertySources().isEmpty());
}
@Test
public void testLoadSingleApolloConfig() throws Exception {
ApolloConfig someApolloConfig = mock(ApolloConfig.class);
Map<String, Object> someMap = Maps.newHashMap();
long someAppId = 100;
ApolloRegistry someApolloRegistry = assembleSomeApolloRegistry(someAppId, "someVersion");
ApolloConfig previousConfig = null;
doReturn(null).when(configLoaderManager).getPreviousApolloConfig(someApolloRegistry);
when(someApolloConfig.getConfigurations()).thenReturn(someMap);
when(configLoader.loadApolloConfig(someApolloRegistry, previousConfig))
.thenReturn(someApolloConfig);
ApolloConfig result = configLoaderManager.loadSingleApolloConfig(someApolloRegistry);
assertEquals(someMap, result.getConfigurations());
}
@Test
public void testReloadPropertySource() throws Exception {
long someAppId = 100;
ApolloRegistry someApolloRegistry = assembleSomeApolloRegistry(someAppId, "someVersion");
ApolloConfig someApolloConfig = mock(ApolloConfig.class);
Map<String, Object> someMap = mock(Map.class);
List<PropertyChange> someChanges = mock(List.class);
ReflectionTestUtils
.setField(configLoaderManager, "apolloRegistries", Lists.newArrayList(someApolloRegistry));
doReturn(someApolloConfig).when(configLoaderManager).loadSingleApolloConfig(someApolloRegistry);
when(someApolloConfig.getAppId()).thenReturn(someAppId);
when(someApolloConfig.getConfigurations()).thenReturn(someMap);
doReturn(someChanges).when(configLoaderManager).calcPropertyChanges(anyList(), anyList());
PropertySourceReloadResult result = configLoaderManager.reloadPropertySource();
assertEquals(1, result.getPropertySource().getPropertySources().size());
assertEquals(someChanges, result.getChanges());
List<Map<String, Object>>
resultMaps =
FluentIterable.from(result.getPropertySource().getPropertySources())
.transform(new Function<PropertySource<?>, Map<String, Object>>() {
@Override
public Map<String, Object> apply(PropertySource<?> input) {
return (Map<String, Object>) input.getSource();
}
}).toList();
assertTrue(resultMaps.containsAll(Lists.newArrayList(someMap)));
}
@Test
public void testCalcPropertyChanges() throws Exception {
long someAppId = 1;
Map<String, Object> someConfig = Maps.newHashMap();
someConfig.put("key1", "val1");
someConfig.put("key2", "val2");
Map<String, Object> anotherConfig = Maps.newHashMap();
anotherConfig.put("key1", "val11");
anotherConfig.put("key3", "val3");
List<ApolloConfig> previous = Lists.newArrayList(assembleApolloConfig(someAppId, someConfig));
List<ApolloConfig> current = Lists.newArrayList(assembleApolloConfig(someAppId, anotherConfig));
List<PropertyChange> changes = configLoaderManager.calcPropertyChanges(previous, current);
assertEquals(3, changes.size());
List<String>
changeResult =
FluentIterable.from(changes).transform(new Function<PropertyChange, String>() {
@Override
public String apply(PropertyChange input) {
return String.format("%s-%s", input.getPropertyName(), input.getChangeType());
}
}).toList();
assertTrue(changeResult.containsAll(
Lists.newArrayList(
"key1-" + PropertyChangeType.MODIFIED,
"key2-" + PropertyChangeType.DELETED,
"key3-" + PropertyChangeType.NEW
)));
}
assertTrue(changeResult.containsAll(
Lists.newArrayList(
"key1-" + PropertyChangeType.MODIFIED,
"key2-" + PropertyChangeType.DELETED,
"key3-" + PropertyChangeType.NEW
)));
}
ApolloConfig assembleApolloConfig(long appId, Map<String, Object> configurations) {
String someCluster = "someCluster";
String someVersion = "someVersion";
long someReleaseId = 1;
ApolloConfig assembleApolloConfig(long appId, Map<String, Object> configurations) {
String someCluster = "someCluster";
String someVersion = "someVersion";
long someReleaseId = 1;
ApolloConfig config = new ApolloConfig(appId, someCluster, someVersion, someReleaseId);
ApolloConfig config = new ApolloConfig(appId, someCluster, someVersion, someReleaseId);
config.setConfigurations(configurations);
config.setConfigurations(configurations);
return config;
}
return config;
}
private ApolloRegistry assembleSomeApolloRegistry(long someAppId, String someVersion) {
ApolloRegistry someApolloRegistry = new ApolloRegistry();
someApolloRegistry.setAppId(someAppId);
someApolloRegistry.setVersion(someVersion);
private ApolloRegistry assembleSomeApolloRegistry(long someAppId, String someVersion) {
ApolloRegistry someApolloRegistry = new ApolloRegistry();
someApolloRegistry.setAppId(someAppId);
someApolloRegistry.setVersion(someVersion);
return someApolloRegistry;
}
return someApolloRegistry;
}
}
package com.ctrip.apollo.client.loader.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyMap;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import com.ctrip.apollo.client.loader.ConfigServiceLocator;
import com.ctrip.apollo.client.model.ApolloRegistry;
import com.ctrip.apollo.client.util.ConfigUtil;
import com.ctrip.apollo.core.dto.ApolloConfig;
import com.ctrip.apollo.core.serivce.ApolloService;
import org.junit.Before;
import org.junit.Test;
......@@ -25,116 +17,132 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import com.ctrip.apollo.client.loader.ConfigServiceLocator;
import com.ctrip.apollo.client.model.ApolloRegistry;
import com.ctrip.apollo.client.util.ConfigUtil;
import com.ctrip.apollo.core.dto.ApolloConfig;
import com.ctrip.apollo.core.serivce.ApolloService;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyMap;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith(MockitoJUnitRunner.class)
public class RemoteConfigLoaderTest {
private RemoteConfigLoader remoteConfigLoader;
@Mock
private RestTemplate restTemplate;
private ConfigUtil configUtil;
@Mock
private ConfigServiceLocator serviceLocater;
@Mock
private ResponseEntity<ApolloConfig> someResponse;
@Before
public void setUp() {
configUtil = spy(ConfigUtil.getInstance());
remoteConfigLoader = spy(new RemoteConfigLoader(restTemplate, configUtil, serviceLocater));
}
@Test
public void testLoadApolloConfig() throws Exception {
String someServerUrl = "http://someUrl";
String someCluster = "some cluster";
ApolloConfig apolloConfig = mock(ApolloConfig.class);
long someAppId = 1;
ApolloRegistry apolloRegistry = assembleSomeApolloRegistry(someAppId, "someVersion");
ApolloConfig previousConfig = null;
ApolloService someService = new ApolloService();
someService.setHomepageUrl(someServerUrl);
List<ApolloService> someServices = new ArrayList<>();
someServices.add(someService);
when(serviceLocater.getConfigServices()).thenReturn(someServices);
when(configUtil.getCluster()).thenReturn(someCluster);
doReturn(apolloConfig).when(remoteConfigLoader)
.getRemoteConfig(restTemplate, someServerUrl, someCluster, apolloRegistry, previousConfig);
ApolloConfig result = remoteConfigLoader.loadApolloConfig(apolloRegistry, previousConfig);
assertEquals(apolloConfig, result);
}
@Test
public void testGetRemoteConfig() throws Exception {
long someAppId = 1;
String someServerUrl = "http://someServer";
String someClusterName = "someCluster";
String someVersionName = "someVersion";
ApolloConfig someApolloConfig = mock(ApolloConfig.class);
ApolloRegistry apolloRegistry = assembleSomeApolloRegistry(someAppId, someVersionName);
ApolloConfig previousConfig = null;
when(someResponse.getStatusCode()).thenReturn(HttpStatus.OK);
when(someResponse.getBody()).thenReturn(someApolloConfig);
when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class),
eq(ApolloConfig.class), anyMap())).thenReturn(someResponse);
ApolloConfig result = remoteConfigLoader.getRemoteConfig(restTemplate, someServerUrl, someClusterName, apolloRegistry, previousConfig);
assertEquals(someApolloConfig, result);
}
@Test(expected = RuntimeException.class)
public void testGetRemoteConfigWithServerError() throws Exception {
long someAppId = 1;
String someServerUrl = "http://someServer";
String someClusterName = "someCluster";
String someVersionName = "someVersion";
ApolloRegistry apolloRegistry = assembleSomeApolloRegistry(someAppId, someVersionName);
ApolloConfig previousConfig = null;
HttpStatus someErrorCode = HttpStatus.INTERNAL_SERVER_ERROR;
when(someResponse.getStatusCode()).thenReturn(someErrorCode);
when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class),
eq(ApolloConfig.class), anyMap())).thenReturn(someResponse);
remoteConfigLoader.getRemoteConfig(restTemplate, someServerUrl, someClusterName, apolloRegistry, previousConfig);
}
@Test
public void testGetRemoteConfigWith304Response() throws Exception {
long someAppId = 1;
String someServerUrl = "http://someServer";
String someClusterName = "someCluster";
String someVersionName = "someVersion";
ApolloRegistry apolloRegistry = assembleSomeApolloRegistry(someAppId, someVersionName);
ApolloConfig previousConfig = null;
when(someResponse.getStatusCode()).thenReturn(HttpStatus.NOT_MODIFIED);
when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class),
eq(ApolloConfig.class), anyMap())).thenReturn(someResponse);
ApolloConfig result = remoteConfigLoader.getRemoteConfig(restTemplate, someServerUrl, someClusterName, apolloRegistry, previousConfig);
assertNull(result);
}
private ApolloRegistry assembleSomeApolloRegistry(long someAppId, String someVersion) {
ApolloRegistry someApolloRegistry = new ApolloRegistry();
someApolloRegistry.setAppId(someAppId);
someApolloRegistry.setVersion(someVersion);
return someApolloRegistry;
}
private RemoteConfigLoader remoteConfigLoader;
@Mock
private RestTemplate restTemplate;
private ConfigUtil configUtil;
@Mock
private ConfigServiceLocator serviceLocater;
@Mock
private ResponseEntity<ApolloConfig> someResponse;
@Before
public void setUp() {
configUtil = spy(ConfigUtil.getInstance());
remoteConfigLoader = spy(new RemoteConfigLoader(restTemplate, configUtil, serviceLocater));
}
@Test
public void testLoadApolloConfig() throws Exception {
String someServerUrl = "http://someUrl";
String someCluster = "some cluster";
ApolloConfig apolloConfig = mock(ApolloConfig.class);
long someAppId = 1;
ApolloRegistry apolloRegistry = assembleSomeApolloRegistry(someAppId, "someVersion");
ApolloConfig previousConfig = null;
ApolloService someService = new ApolloService();
someService.setHomepageUrl(someServerUrl);
List<ApolloService> someServices = new ArrayList<>();
someServices.add(someService);
when(serviceLocater.getConfigServices()).thenReturn(someServices);
when(configUtil.getCluster()).thenReturn(someCluster);
doReturn(apolloConfig).when(remoteConfigLoader)
.getRemoteConfig(restTemplate, someServerUrl, someCluster, apolloRegistry, previousConfig);
ApolloConfig result = remoteConfigLoader.loadApolloConfig(apolloRegistry, previousConfig);
assertEquals(apolloConfig, result);
}
@Test
public void testGetRemoteConfig() throws Exception {
long someAppId = 1;
String someServerUrl = "http://someServer";
String someClusterName = "someCluster";
String someVersionName = "someVersion";
ApolloConfig someApolloConfig = mock(ApolloConfig.class);
ApolloRegistry apolloRegistry = assembleSomeApolloRegistry(someAppId, someVersionName);
ApolloConfig previousConfig = null;
when(someResponse.getStatusCode()).thenReturn(HttpStatus.OK);
when(someResponse.getBody()).thenReturn(someApolloConfig);
when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class),
eq(ApolloConfig.class), anyMap())).thenReturn(someResponse);
ApolloConfig
result =
remoteConfigLoader
.getRemoteConfig(restTemplate, someServerUrl, someClusterName, apolloRegistry,
previousConfig);
assertEquals(someApolloConfig, result);
}
@Test(expected = RuntimeException.class)
public void testGetRemoteConfigWithServerError() throws Exception {
long someAppId = 1;
String someServerUrl = "http://someServer";
String someClusterName = "someCluster";
String someVersionName = "someVersion";
ApolloRegistry apolloRegistry = assembleSomeApolloRegistry(someAppId, someVersionName);
ApolloConfig previousConfig = null;
HttpStatus someErrorCode = HttpStatus.INTERNAL_SERVER_ERROR;
when(someResponse.getStatusCode()).thenReturn(someErrorCode);
when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class),
eq(ApolloConfig.class), anyMap())).thenReturn(someResponse);
remoteConfigLoader.getRemoteConfig(restTemplate, someServerUrl, someClusterName, apolloRegistry,
previousConfig);
}
@Test
public void testGetRemoteConfigWith304Response() throws Exception {
long someAppId = 1;
String someServerUrl = "http://someServer";
String someClusterName = "someCluster";
String someVersionName = "someVersion";
ApolloRegistry apolloRegistry = assembleSomeApolloRegistry(someAppId, someVersionName);
ApolloConfig previousConfig = null;
when(someResponse.getStatusCode()).thenReturn(HttpStatus.NOT_MODIFIED);
when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class),
eq(ApolloConfig.class), anyMap())).thenReturn(someResponse);
ApolloConfig
result =
remoteConfigLoader
.getRemoteConfig(restTemplate, someServerUrl, someClusterName, apolloRegistry,
previousConfig);
assertNull(result);
}
private ApolloRegistry assembleSomeApolloRegistry(long someAppId, String someVersion) {
ApolloRegistry someApolloRegistry = new ApolloRegistry();
someApolloRegistry.setAppId(someAppId);
someApolloRegistry.setVersion(someVersion);
return someApolloRegistry;
}
}
package com.ctrip.apollo.client.util;
import com.google.common.collect.Lists;
import com.ctrip.apollo.client.constants.Constants;
import com.ctrip.apollo.client.model.ApolloRegistry;
import com.google.common.collect.Lists;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
......@@ -19,60 +21,65 @@ import java.util.Properties;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith(MockitoJUnitRunner.class)
public class ConfigUtilTest {
private ConfigUtil configUtil;
@Mock
private ConfigurableApplicationContext applicationContext;
private ConfigUtil configUtil;
@Mock
private ConfigurableApplicationContext applicationContext;
@Before
public void setUp() throws Exception {
configUtil = spy(ConfigUtil.getInstance());
@Before
public void setUp() throws Exception {
configUtil = spy(ConfigUtil.getInstance());
configUtil.setApplicationContext(applicationContext);
}
configUtil.setApplicationContext(applicationContext);
}
@Test
public void testLoadApolloRegistriesSuccessfully() throws Exception {
Properties someProperties = mock(Properties.class);
preparePropertiesFromLocalResource(someProperties);
@Test
public void testLoadApolloRegistriesSuccessfully() throws Exception {
Properties someProperties = mock(Properties.class);
preparePropertiesFromLocalResource(someProperties);
String someAppId = "1";
String someVersionId = "someVersion";
String someAppId = "1";
String someVersionId = "someVersion";
when(someProperties.containsKey(Constants.APP_ID)).thenReturn(true);
when(someProperties.getProperty(Constants.APP_ID)).thenReturn(someAppId);
when(someProperties.getProperty(eq(Constants.VERSION), anyString())).thenReturn(someVersionId);
when(someProperties.containsKey(Constants.APP_ID)).thenReturn(true);
when(someProperties.getProperty(Constants.APP_ID)).thenReturn(someAppId);
when(someProperties.getProperty(eq(Constants.VERSION), anyString())).thenReturn(someVersionId);
List<ApolloRegistry> apolloRegistries = configUtil.loadApolloRegistries();
List<ApolloRegistry> apolloRegistries = configUtil.loadApolloRegistries();
ApolloRegistry apolloRegistry = apolloRegistries.get(0);
assertEquals(1, apolloRegistries.size());
assertEquals(Long.parseLong(someAppId), apolloRegistry.getAppId());
assertEquals(someVersionId, apolloRegistry.getVersion());
}
ApolloRegistry apolloRegistry = apolloRegistries.get(0);
assertEquals(1, apolloRegistries.size());
assertEquals(Long.parseLong(someAppId), apolloRegistry.getAppId());
assertEquals(someVersionId, apolloRegistry.getVersion());
}
@Test
public void testLoadApolloRegistriesError() throws Exception {
preparePropertiesFromLocalResource(null);
@Test
public void testLoadApolloRegistriesError() throws Exception {
preparePropertiesFromLocalResource(null);
List<ApolloRegistry> apolloRegistries = configUtil.loadApolloRegistries();
List<ApolloRegistry> apolloRegistries = configUtil.loadApolloRegistries();
assertTrue(apolloRegistries.isEmpty());
}
assertTrue(apolloRegistries.isEmpty());
}
private void preparePropertiesFromLocalResource(Properties someProperties) throws IOException {
ClassLoader someClassLoader = mock(ClassLoader.class);
Thread.currentThread().setContextClassLoader(someClassLoader);
URL someUrl = new URL("http", "somepath/", "someFile");
Enumeration<URL> someResourceUrls = Collections.enumeration(Lists.newArrayList(someUrl));
private void preparePropertiesFromLocalResource(Properties someProperties) throws IOException {
ClassLoader someClassLoader = mock(ClassLoader.class);
Thread.currentThread().setContextClassLoader(someClassLoader);
URL someUrl = new URL("http", "somepath/", "someFile");
Enumeration<URL> someResourceUrls = Collections.enumeration(Lists.newArrayList(someUrl));
when(someClassLoader.getResources(anyString())).thenReturn(someResourceUrls);
doReturn(someProperties).when(configUtil).loadPropertiesFromResourceURL(someUrl);
}
when(someClassLoader.getResources(anyString())).thenReturn(someResourceUrls);
doReturn(someProperties).when(configUtil).loadPropertiesFromResourceURL(someUrl);
}
}
......@@ -5,7 +5,7 @@
<PatternLayout pattern="[apollo-client][%t]%d %-5p [%c] %m%n"/>
</Console>
<Async name="Async" includeLocation="true">
<AppenderRef ref="Console" />
<AppenderRef ref="Console"/>
</Async>
</appenders>
<loggers>
......
<?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/maven-v4_0_0.xsd">
<parent>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apollo-configservice</artifactId>
<name>Apollo ConfigService</name>
<dependencies>
<!-- apollo -->
<dependency>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo-biz</artifactId>
</dependency>
<!-- end of apollo -->
<!-- redis -->
<!-- <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId>
</dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId>
</dependency> -->
<!-- end of redis -->
<!-- eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
<exclusions>
<exclusion>
<artifactId>
spring-cloud-starter-archaius
</artifactId>
<groupId>org.springframework.cloud</groupId>
</exclusion>
<exclusion>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<groupId>org.springframework.cloud</groupId>
</exclusion>
<exclusion>
<artifactId>ribbon-eureka</artifactId>
<groupId>com.netflix.ribbon</groupId>
</exclusion>
<exclusion>
<artifactId>aws-java-sdk-core</artifactId>
<groupId>com.amazonaws</groupId>
</exclusion>
<exclusion>
<artifactId>aws-java-sdk-ec2</artifactId>
<groupId>com.amazonaws</groupId>
</exclusion>
<exclusion>
<artifactId>aws-java-sdk-autoscaling</artifactId>
<groupId>com.amazonaws</groupId>
</exclusion>
<exclusion>
<artifactId>aws-java-sdk-sts</artifactId>
<groupId>com.amazonaws</groupId>
</exclusion>
<exclusion>
<artifactId>aws-java-sdk-route53</artifactId>
<groupId>com.amazonaws</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- end of eureka -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
</build>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apollo-configservice</artifactId>
<name>Apollo ConfigService</name>
<dependencies>
<!-- apollo -->
<dependency>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo-biz</artifactId>
</dependency>
<!-- end of apollo -->
<!-- redis -->
<!-- <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId>
</dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId>
</dependency> -->
<!-- end of redis -->
<!-- eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
<exclusions>
<exclusion>
<artifactId>
spring-cloud-starter-archaius
</artifactId>
<groupId>org.springframework.cloud</groupId>
</exclusion>
<exclusion>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<groupId>org.springframework.cloud</groupId>
</exclusion>
<exclusion>
<artifactId>ribbon-eureka</artifactId>
<groupId>com.netflix.ribbon</groupId>
</exclusion>
<exclusion>
<artifactId>aws-java-sdk-core</artifactId>
<groupId>com.amazonaws</groupId>
</exclusion>
<exclusion>
<artifactId>aws-java-sdk-ec2</artifactId>
<groupId>com.amazonaws</groupId>
</exclusion>
<exclusion>
<artifactId>aws-java-sdk-autoscaling</artifactId>
<groupId>com.amazonaws</groupId>
</exclusion>
<exclusion>
<artifactId>aws-java-sdk-sts</artifactId>
<groupId>com.amazonaws</groupId>
</exclusion>
<exclusion>
<artifactId>aws-java-sdk-route53</artifactId>
<groupId>com.amazonaws</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- end of eureka -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
</build>
</project>
......@@ -6,15 +6,15 @@ import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* Spring boot application entry point
*
*
* @author Jason Song(song_s@ctrip.com)
*/
@SpringBootApplication
@EnableEurekaServer
public class ServerApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(ServerApplication.class).web(true).run(args);
}
}
......@@ -5,13 +5,14 @@ import org.springframework.boot.context.web.SpringBootServletInitializer;
/**
* Entry point for traditional web app
*
* @author Jason Song(song_s@ctrip.com)
*/
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(ServerApplication.class);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(ServerApplication.class);
}
}
......@@ -3,11 +3,17 @@ package com.ctrip.apollo.configservice.controller;
import com.ctrip.apollo.biz.entity.Version;
import com.ctrip.apollo.biz.service.ConfigService;
import com.ctrip.apollo.core.dto.ApolloConfig;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Jason Song(song_s@ctrip.com)
......@@ -15,36 +21,38 @@ import java.io.IOException;
@RestController
@RequestMapping("/config")
public class ConfigController {
@Resource(name = "configService")
private ConfigService configService;
@RequestMapping(value = "/{appId}/{clusterName}/{versionName:.*}", method = RequestMethod.GET)
public ApolloConfig queryConfig(@PathVariable long appId,
@PathVariable String clusterName,
@PathVariable String versionName,
@RequestParam(value = "releaseId", defaultValue = "-1") long clientSideReleaseId,
HttpServletResponse response) throws IOException {
Version version = configService.loadVersionByAppIdAndVersionName(appId, versionName);
if (version == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
String.format("Could not load version with appId: %d, versionName: %s", appId, versionName));
return null;
}
if (version.getReleaseId() == clientSideReleaseId) {
//Client side configuration is the same with server side, return 304
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return null;
}
ApolloConfig apolloConfig =
configService.loadConfigByVersionAndClusterName(version, clusterName);
if (apolloConfig == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
String.format("Could not load config with releaseId: %d, clusterName: %s", version.getReleaseId(), clusterName));
return null;
}
return apolloConfig;
@Resource(name = "configService")
private ConfigService configService;
@RequestMapping(value = "/{appId}/{clusterName}/{versionName:.*}", method = RequestMethod.GET)
public ApolloConfig queryConfig(@PathVariable long appId,
@PathVariable String clusterName,
@PathVariable String versionName,
@RequestParam(value = "releaseId", defaultValue = "-1") long clientSideReleaseId,
HttpServletResponse response) throws IOException {
Version version = configService.loadVersionByAppIdAndVersionName(appId, versionName);
if (version == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
String.format("Could not load version with appId: %d, versionName: %s", appId,
versionName));
return null;
}
if (version.getReleaseId() == clientSideReleaseId) {
//Client side configuration is the same with server side, return 304
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return null;
}
ApolloConfig apolloConfig =
configService.loadConfigByVersionAndClusterName(version, clusterName);
if (apolloConfig == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
String.format("Could not load config with releaseId: %d, clusterName: %s",
version.getReleaseId(), clusterName));
return null;
}
return apolloConfig;
}
}
package com.ctrip.apollo.metaservice.controller;
import java.util.ArrayList;
import java.util.List;
import com.ctrip.apollo.core.serivce.ApolloService;
import com.ctrip.apollo.metaservice.service.DiscoveryService;
import com.netflix.appinfo.InstanceInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ctrip.apollo.core.serivce.ApolloService;
import com.ctrip.apollo.metaservice.service.DiscoveryService;
import com.netflix.appinfo.InstanceInfo;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/services")
......
package com.ctrip.apollo.metaservice.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ctrip.apollo.core.ServiceNameConsts;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.shared.Application;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class DiscoveryService {
......@@ -27,7 +27,7 @@ public class DiscoveryService {
return application != null ? application.getInstances() : new ArrayList<>();
}
public List<InstanceInfo> getAdminServiceInstances(){
public List<InstanceInfo> getAdminServiceInstances() {
Application application = eurekaClient.getApplication(ServiceNameConsts.APOLLO_ADMINSERVICE);
return application != null ? application.getInstances() : new ArrayList<>();
}
......
package com.ctrip.apollo.configservice;
import com.ctrip.apollo.ServerApplication;
import org.junit.runner.RunWith;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
......
package com.ctrip.apollo.configservice;
import com.ctrip.apollo.configservice.controller.ConfigControllerTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
import com.ctrip.apollo.configservice.controller.ConfigControllerTest;
@RunWith(Suite.class)
@SuiteClasses({
ConfigControllerTest.class
ConfigControllerTest.class
})
public class AllTests {
......
......@@ -2,8 +2,8 @@ package com.ctrip.apollo.configservice.controller;
import com.ctrip.apollo.biz.entity.Version;
import com.ctrip.apollo.biz.service.ConfigService;
import com.ctrip.apollo.configservice.controller.ConfigController;
import com.ctrip.apollo.core.dto.ApolloConfig;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
......@@ -15,98 +15,128 @@ import javax.servlet.http.HttpServletResponse;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith(MockitoJUnitRunner.class)
public class ConfigControllerTest {
private ConfigController configController;
@Mock
private ConfigService configService;
@Before
public void setUp() throws Exception {
configController = new ConfigController();
ReflectionTestUtils.setField(configController, "configService", configService);
}
@Test
public void testQueryConfig() throws Exception {
ApolloConfig someApolloConfig = mock(ApolloConfig.class);
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersion";
long someClientSideReleaseId = 1;
long someServerSideNewReleaseId = 2;
HttpServletResponse someResponse = mock(HttpServletResponse.class);
Version someVersion = mock(Version.class);
when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName)).thenReturn(someVersion);
when(someVersion.getReleaseId()).thenReturn(someServerSideNewReleaseId);
when(configService.loadConfigByVersionAndClusterName(someVersion, someClusterName)).thenReturn(someApolloConfig);
ApolloConfig result = configController.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId, someResponse);
assertEquals(someApolloConfig, result);
verify(configService, times(1)).loadVersionByAppIdAndVersionName(someAppId, someVersionName);
verify(configService, times(1)).loadConfigByVersionAndClusterName(someVersion, someClusterName);
}
@Test
public void testQueryConfigWithVersionNotFound() throws Exception {
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersion";
long someClientSideReleaseId = 1;
HttpServletResponse someResponse = mock(HttpServletResponse.class);
when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName)).thenReturn(null);
ApolloConfig result = configController.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId, someResponse);
assertNull(result);
verify(someResponse, times(1)).sendError(eq(HttpServletResponse.SC_NOT_FOUND), anyString());
}
@Test
public void testQueryConfigWithApolloConfigNotFound() throws Exception {
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersion";
long someClientSideReleaseId = 1;
long someServerSideNewReleaseId = 2;
HttpServletResponse someResponse = mock(HttpServletResponse.class);
Version someVersion = mock(Version.class);
when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName)).thenReturn(someVersion);
when(someVersion.getReleaseId()).thenReturn(someServerSideNewReleaseId);
when(configService.loadConfigByVersionAndClusterName(someVersion, someClusterName)).thenReturn(null);
ApolloConfig result = configController.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId, someResponse);
assertNull(result);
verify(someResponse, times(1)).sendError(eq(HttpServletResponse.SC_NOT_FOUND), anyString());
}
@Test
public void testQueryConfigWithApolloConfigNotModified() throws Exception {
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersion";
long someClientSideReleaseId = 1;
long someServerSideReleaseId = someClientSideReleaseId;
HttpServletResponse someResponse = mock(HttpServletResponse.class);
Version someVersion = mock(Version.class);
when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName)).thenReturn(someVersion);
when(someVersion.getReleaseId()).thenReturn(someServerSideReleaseId);
ApolloConfig result = configController.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId, someResponse);
assertNull(result);
verify(someResponse, times(1)).setStatus(HttpServletResponse.SC_NOT_MODIFIED);
verify(configService, never()).loadConfigByVersionAndClusterName(any(Version.class), anyString());
}
private ConfigController configController;
@Mock
private ConfigService configService;
@Before
public void setUp() throws Exception {
configController = new ConfigController();
ReflectionTestUtils.setField(configController, "configService", configService);
}
@Test
public void testQueryConfig() throws Exception {
ApolloConfig someApolloConfig = mock(ApolloConfig.class);
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersion";
long someClientSideReleaseId = 1;
long someServerSideNewReleaseId = 2;
HttpServletResponse someResponse = mock(HttpServletResponse.class);
Version someVersion = mock(Version.class);
when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName))
.thenReturn(someVersion);
when(someVersion.getReleaseId()).thenReturn(someServerSideNewReleaseId);
when(configService.loadConfigByVersionAndClusterName(someVersion, someClusterName))
.thenReturn(someApolloConfig);
ApolloConfig
result =
configController
.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId,
someResponse);
assertEquals(someApolloConfig, result);
verify(configService, times(1)).loadVersionByAppIdAndVersionName(someAppId, someVersionName);
verify(configService, times(1)).loadConfigByVersionAndClusterName(someVersion, someClusterName);
}
@Test
public void testQueryConfigWithVersionNotFound() throws Exception {
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersion";
long someClientSideReleaseId = 1;
HttpServletResponse someResponse = mock(HttpServletResponse.class);
when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName))
.thenReturn(null);
ApolloConfig
result =
configController
.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId,
someResponse);
assertNull(result);
verify(someResponse, times(1)).sendError(eq(HttpServletResponse.SC_NOT_FOUND), anyString());
}
@Test
public void testQueryConfigWithApolloConfigNotFound() throws Exception {
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersion";
long someClientSideReleaseId = 1;
long someServerSideNewReleaseId = 2;
HttpServletResponse someResponse = mock(HttpServletResponse.class);
Version someVersion = mock(Version.class);
when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName))
.thenReturn(someVersion);
when(someVersion.getReleaseId()).thenReturn(someServerSideNewReleaseId);
when(configService.loadConfigByVersionAndClusterName(someVersion, someClusterName))
.thenReturn(null);
ApolloConfig
result =
configController
.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId,
someResponse);
assertNull(result);
verify(someResponse, times(1)).sendError(eq(HttpServletResponse.SC_NOT_FOUND), anyString());
}
@Test
public void testQueryConfigWithApolloConfigNotModified() throws Exception {
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersion";
long someClientSideReleaseId = 1;
long someServerSideReleaseId = someClientSideReleaseId;
HttpServletResponse someResponse = mock(HttpServletResponse.class);
Version someVersion = mock(Version.class);
when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName))
.thenReturn(someVersion);
when(someVersion.getReleaseId()).thenReturn(someServerSideReleaseId);
ApolloConfig
result =
configController
.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId,
someResponse);
assertNull(result);
verify(someResponse, times(1)).setStatus(HttpServletResponse.SC_NOT_MODIFIED);
verify(configService, never())
.loadConfigByVersionAndClusterName(any(Version.class), anyString());
}
}
<?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/maven-v4_0_0.xsd">
<parent>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apollo-core</artifactId>
<name>Apollo Core</name>
<packaging>jar</packaging>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apollo-core</artifactId>
<name>Apollo Core</name>
<packaging>jar</packaging>
<dependencies>
<!-- json -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- end of json -->
<!-- util -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<!-- end of util -->
<!-- log -->
<dependencies>
<!-- json -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- end of json -->
<!-- util -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<!-- end of util -->
<!-- log -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<!-- end of log -->
</dependencies>
</dependencies>
</project>
package com.ctrip.apollo;
public class Apollo {
public final static String VERSION = "java-0.0.1-SNAPSHOT";
public static final String VERSION = "java-0.0.1-SNAPSHOT";
private static Env m_env;
public enum Env {
LOCAL, DEV, FWS, FAT, UAT, LPT, PRO, TOOLS
LOCAL, DEV, FWS, FAT, UAT, LPT, PRO, TOOLS
}
public static void initialize(Env env) {
m_env = env;
m_env = env;
}
public static Env getEnv() {
return m_env;
return m_env;
}
}
......@@ -2,6 +2,6 @@ package com.ctrip.apollo.core;
public interface Constants {
String DEFAULT_CLUSTER_NAME = "default-cluster-name";
String DEFAULT_CLUSTER_NAME = "default-cluster-name";
}
package com.ctrip.apollo.core;
import com.ctrip.apollo.Apollo.Env;
import java.util.HashMap;
import java.util.Map;
import com.ctrip.apollo.Apollo.Env;
public class MetaDomainConsts {
public static final String DEFAULT_PORT = "8080";
......
......@@ -7,6 +7,6 @@ public class ServiceNameConsts {
public static final String APOLLO_CONFIGSERVICE = "apollo-configservice";
public static final String APOLLO_ADMINSERVICE = "apollo-adminservice";
public static final String APOLLO_PORTAL = "apollo-portal";
}
......@@ -2,33 +2,33 @@ package com.ctrip.apollo.core.dto;
public class ClusterDTO {
private long id;
private long id;
private String name;
private String name;
private long appId;
private long appId;
public long getId() {
return id;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public long getAppId() {
return appId;
}
public long getAppId() {
return appId;
}
public void setAppId(long appId) {
this.appId = appId;
}
public void setAppId(long appId) {
this.appId = appId;
}
}
......@@ -7,17 +7,17 @@ import java.util.List;
public class DNSUtil {
public static List<String> resolve(String domainName) throws UnknownHostException {
List<String> result = new ArrayList<String>();
public static List<String> resolve(String domainName) throws UnknownHostException {
List<String> result = new ArrayList<String>();
InetAddress[] addresses = InetAddress.getAllByName(domainName);
if (addresses != null) {
for (InetAddress addr : addresses) {
result.add(addr.getHostAddress());
}
}
InetAddress[] addresses = InetAddress.getAllByName(domainName);
if (addresses != null) {
for (InetAddress addr : addresses) {
result.add(addr.getHostAddress());
}
}
return result;
}
return result;
}
}
......@@ -5,7 +5,7 @@
<PatternLayout pattern="[apollo-demo][%t]%d %-5p [%c] %m%n"/>
</Console>
<Async name="Async" includeLocation="true">
<AppenderRef ref="Console" />
<AppenderRef ref="Console"/>
</Async>
</appenders>
<loggers>
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册