Spring Framework4のClassPathXmlApplicationContextで存在するはずのサービス定義ファイルが読み込めない場合の解決策
Spring FrameworkでDependency Injectionを使いたい。
でも、Spring Framworkで絶対パスを指定しているはずなのに、
というか、File.exists()で存在確認しているはずなのに、ファイルが読み込めない。
なんてことでハマったので、解決策を記しておく。
Springは2014年現在最新のSpring4.1.2。
Mavenの依存関係は以下。
pom.xml
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.2.RELEASE</version> <scope>runtime</scope> </dependency>
ダメな場合のJavaはこちら。
package twitter.action; import java.io.File; import java.util.List; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import twitter.analyze.PublicTimeLineSearch; import twitter4j.Status; import twitter4j.Twitter; import twitter4j.TwitterException; import twitter4j.TwitterFactory; public class Main { public static void main(String[] args) throws TwitterException { Twitter twitter = new TwitterFactory().getInstance(); //本当は外部から渡す File serviceFile = new File("services.xml"); if (!serviceFile.exists()) { System.err.println("サービス定義ファイルが存在しません:" + serviceFile.getPath()); System.exit(1); } else { System.out.println("サービス定義を読み込みます:" + serviceFile.getAbsolutePath()); } ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { serviceFile.getAbsolutePath()}); //ApplicationContext context = new FileSystemXmlApplicationContext( serviceFile.getAbsolutePath()); PublicTimeLineSearch pSearch = context.getBean("publicTimeLineAnalyzor",PublicTimeLineSearch.class); List<Status> list = pSearch.getQuerySearchResult(twitter); } }
これを実行すると、こんなエラーが出る。
サービス定義を読み込みます:C:\eclipse\pleiades\eclipse\workspace_mine\twitter-analyzor\services.xml 11 27, 2014 1:55:38 午後 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh 情報: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@742cb491: startup date [Thu Nov 27 13:55:38 JST 2014]; root of context hierarchy 11 27, 2014 1:55:38 午後 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 情報: Loading XML bean definitions from class path resource [C:/eclipse/pleiades/eclipse/workspace_mine/twitter-analyzor/services.xml] Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [C:/eclipse/pleiades/eclipse/workspace_mine/twitter-analyzor/services.xml]; nested exception is java.io.FileNotFoundException: class path resource [C:/eclipse/pleiades/eclipse/workspace_mine/twitter-analyzor/services.xml] cannot be opened because it does not exist at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:344) at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304) at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:181) at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:217) at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:188) at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:252) at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:127) at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:93) at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:129) at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:537) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:452) at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139) at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93) at twitter.action.Main.main(Main.java:27) Caused by: java.io.FileNotFoundException: class path resource [C:/eclipse/pleiades/eclipse/workspace_mine/twitter-analyzor/services.xml] cannot be opened because it does not exist at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:172) at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:330) ... 13 more
そういうときのもっとも簡単な解決策は、FileSystemXmlApplicationContextを使ってサービス定義を読み込むことだ。
以下のようにすると、サービス定義を読み込むことができる。
package twitter.action; import java.io.File; import java.util.List; import org.springframework.context.ApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; import twitter.analyze.PublicTimeLineSearch; import twitter4j.Status; import twitter4j.Twitter; import twitter4j.TwitterException; import twitter4j.TwitterFactory; public class Main { public static void main(String[] args) throws TwitterException { Twitter twitter = new TwitterFactory().getInstance(); //本当は外部から渡す File serviceFile = new File("services.xml"); if (!serviceFile.exists()) { System.err.println("サービス定義ファイルが存在しません:" + serviceFile.getPath()); System.exit(1); } else { System.out.println("サービス定義を読み込みます:" + serviceFile.getAbsolutePath()); } //ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { serviceFile.getAbsolutePath()}); ApplicationContext context = new FileSystemXmlApplicationContext( serviceFile.getAbsolutePath()); PublicTimeLineSearch pSearch = context.getBean("publicTimeLineAnalyzor",PublicTimeLineSearch.class); List<Status> list = pSearch.getQuerySearchResult(twitter); } }
ClassPathXmlApplicationContextを使って読み込みたい場合は、書き方に工夫がいる。
new ClassPathXmlApplicationContext("file:src/main/resources/beans.xml");
のように、file:を接頭辞につけなければいけない。
以下の例だとうまいこと読み込むことができた。
package twitter.action; import java.io.File; import java.util.List; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import twitter.analyze.PublicTimeLineSearch; import twitter4j.Status; import twitter4j.Twitter; import twitter4j.TwitterException; import twitter4j.TwitterFactory; public class Main { public static void main(String[] args) throws TwitterException { Twitter twitter = new TwitterFactory().getInstance(); //本当は外部から渡す File serviceFile = new File("services.xml"); if (!serviceFile.exists()) { System.err.println("サービス定義ファイルが存在しません:" + serviceFile.getPath()); System.exit(1); } else { System.out.println("サービス定義を読み込みます:" + serviceFile.getAbsolutePath()); } ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"file:" + serviceFile.getAbsolutePath()}); //ApplicationContext context = new FileSystemXmlApplicationContext( serviceFile.getAbsolutePath()); PublicTimeLineSearch pSearch = context.getBean("publicTimeLineAnalyzor",PublicTimeLineSearch.class); List<Status> list = pSearch.getQuerySearchResult(twitter); } }
- 作者: 掌田津耶乃
- 出版社/メーカー: 秀和システム
- 発売日: 2014/08/01
- メディア: 単行本
- この商品を含むブログ (2件) を見る