java.lang.IllegalStateException:
项目启动的时候,抛了如下异常:
java.lang.IllegalStateException: No such application config! Please add <dubbo:application name="..." /> to your spring config.
在配置加载的过程中,<dubbo:application name="xx" />这个配置项没有读取到,配置文件使用xml+properties的配置方式,在dubbo-provider.xml中配置<dubbo service />配置项,其他的一些公共配置比如application、registry、 portocol等放到dubbo.properties文件中读取。
1.问题分析
根据异常来看,是加载配置文件的时候出问题了,首先看了一下dubbo.properties文件,这个配置项是有的,排除配置文件书写错误。那接下来考虑一下配置文件是否没读取到。
dubbo配置文件,默认有4种来源:
- JVM System Properties,-D参数
- Externalized Configuration,外部化配置
- ServiceConfig、ReferenceConfig等编程接口采集的配置
- 本地配置文件dubbo.properties
下图展示了配置覆盖关系的优先级,从上到下优先级依次降低:
参考了dubbo官网内容:
dubbo配置加载流程
2.问题解决过程
2.1 -D参数配置
首先尝试了以-Ddubbo.properties.file=dubbo.properties的方式,还是报错,我电脑的系统是windows,百度发现这篇文章,windows下指定文件路径需要加一个 /,这样才能读取到文件路径。
dubbo.properties配置文件路径修改
ConfigUtil.class类中对路径有判断,当为/开头时,为文件路径,否者就是classpath路径;文件路径前一定要加"/",否者dubbo会按classpath路径去加载。ps:此只对window路径,Linux路径是默认/开头的。
代码如下:
public static Properties loadProperties(String fileName, boolean allowMultiFile, boolean optional) {
Properties properties = new Properties();
if (fileName.startsWith("/")) {
try {
FileInputStream input = new FileInputStream(fileName);
try {
properties.load(input);
} finally {
input.close();
}
} catch (Throwable e) {
logger.warn("Failed to load " + fileName + " file from " + fileName + "(ingore this file): " + e.getMessage(), e);
}
return properties;
}
List<java.net.URL> list = new ArrayList<java.net.URL>();
try {
Enumeration<java.net.URL> urls = ClassHelper.getClassLoader().getResources(fileName);
list = new ArrayList<java.net.URL>();
while (urls.hasMoreElements()) {
list.add(urls.nextElement());
}
} catch (Throwable t) {
logger.warn("Fail to load " + fileName + " file: " + t.getMessage(), t);
}
if(list.size() == 0) {
if (! optional) {
logger.warn("No " + fileName + " found on the class path.");
}
return properties;
}
if(! allowMultiFile) {
if (list.size() > 1) {
String errMsg = String.format("only 1 %s file is expected, but %d dubbo.properties files found on class path: %s",
fileName, list.size(), list.toString());
logger.warn(errMsg);
// throw new IllegalStateException(errMsg); // see http://code.alibabatech.com/jira/browse/DUBBO-133
}
// fall back to use method getResourceAsStream
try {
properties.load(ClassHelper.getClassLoader().getResourceAsStream(fileName));
} catch (Throwable e) {
logger.warn("Failed to load " + fileName + " file from " + fileName + "(ingore this file): " + e.getMessage(), e);
}
return properties;
}
logger.info("load " + fileName + " properties file from " + list);
for(java.net.URL url : list) {
try {
Properties p = new Properties();
InputStream input = url.openStream();
if (input != null) {
try {
p.load(input);
properties.putAll(p);
} finally {
try {
input.close();
} catch (Throwable t) {}
}
}
} catch (Throwable e) {
logger.warn("Fail to load " + fileName + " file from " + url + "(ingore this file): " + e.getMessage(), e);
}
}
return properties;
}
2.2 设置系统环境变量
我用的dubbo的jar包是公司内部基于dubbo修改而来的,对配置文件读取做了一定的修改:
public static Properties getProperties() {
if (PROPERTIES == null) {
synchronized (ConfigUtils.class) {
if (PROPERTIES == null) {
String path = System.getProperty(Constants.DUBBO_PROPERTIES_KEY);
if (path == null || path.length() == 0) {
path = System.getenv(Constants.DUBBO_PROPERTIES_KEY);
if(path == null || path.length() == 0){
path = System.getenv(Constants.ZSMART_HOME) + File.separator + Constants.ZSMART_HOME_CONF;
File file = new File(path);
if (file.exists()) {
try {
Properties properties = new Properties();
FileInputStream input = new FileInputStream(path);
try {
properties.load(input);
} finally {
input.close();
}
PROPERTIES = properties;
return PROPERTIES;
} catch (Throwable e) {
logger.info("Failed to load " + path, e);
}
}else{
path = Constants.DEFAULT_DUBBO_PROPERTIES;
}
}
}
PROPERTIES = ConfigUtils.loadProperties(path, false, true);
}
}
}
return PROPERTIES;
}
我项目加的-DZSMART_HOME属于jvm变量,代码中取ZSMART_HOME是从系统环境变量中取的,所以启动一直报错。
3.总结
windows下使用-D参数指定dubbo.properties位置,一定要以"/"开头,不然还是会加载classpath路径下的配置文件
示例:
-Ddubbo.properties.file="/D:\dubbo.properties"
/D中间不能有空格
错误示范
/ D
正确示范
/D