web-dev-qa-db-ja.com

JARにプロパティファイルをロードしますか?

Webアプリが依存するjarファイルの1つが、jarファイル内からプロパティファイルを読み込もうとすると、問題が発生します。 jarのコードは次のとおりです。

static
{
    Properties props = new Properties();
    try 
    {
        props.load(ClassLoader.getSystemResourceAsStream("someProps.properties"));
    } catch (IOException e) 
    {
        e.printStackTrace();
    }
    someProperty = props.getProperty("someKey");
}

プロパティファイルは、Mavenプロジェクトの「src/main/resources」ディレクトリにあります。 Eclipseのjunitテストからこのコードを実行すると、問題なく実行されます。 Mavenを使用してプロジェクトをjarにビルドし、Webアプリに依存関係として含めると、プロパティファイルが見つかりません。プロパティファイルが依存するjarのベースディレクトリにあることは知っていますが、これを修正する方法はわかりません。

58
Andy

問題は、getSystemResourceAsStreamを使用していることです。単にgetResourceAsStreamを使用します。システムリソースは、システムクラスローダーからロードします。これは、ほぼ確実に、webappとして実行するときにjarがロードされるクラスローダーではありません。

Eclipseで動作します。これは、アプリケーションを起動すると、クラスパスの一部としてjarでシステムクラスローダーが設定されるためです。 (たとえばJava -jar my.jarはシステムクラスローダーでmy.jarをロードします。)これはWebアプリケーションには当てはまりません。アプリケーションサーバーは複雑なクラスロードを使用してWebアプリケーションを相互に分離します。アプリケーションサーバーの内部から、たとえば、 Tomcat classloader how-to 、および使用されるクラスローダー階層の図を参照してください。

編集:通常、getClass().getResourceAsStream()を呼び出してクラスパス内のリソースを取得しますが、静的イニシャライザーでリソースをフェッチしているため、目的のクラスローダーにあるクラスに明示的に名前を付ける必要がありますからロードします。最も簡単なアプローチは、静的初期化子を含むクラスを使用することです。

[public] class MyClass {
  static
  {
    ...
    props.load(MyClass.class.getResourceAsStream("/someProps.properties"));
  }
}
74
mdma

レコードについては、これは JARにリソースを追加するにはどうすればよいですか? (単体テストに示されていますが、「通常の」リソースにも同じことが言えます)に記載されています。

ユニットテストのクラスパスにリソースを追加するには、リソースをJARに追加する場合と同じパターンに従いますが、リソースを配置するディレクトリは${basedir}/src/test/resources。この時点で、プロジェクトディレクトリ構造は次のようになります。

my-app
|-- pom.xml
`-- src
    |-- main
    |   |-- Java
    |   |   `-- com
    |   |       `-- mycompany
    |   |           `-- app
    |   |               `-- App.Java
    |   `-- resources
    |       `-- META-INF
    |           |-- application.properties
    `-- test
        |-- Java
        |   `-- com
        |       `-- mycompany
        |           `-- app
        |               `-- AppTest.Java
        `-- resources
            `-- test.properties

単体テストでは、次のような簡単なコードスニペットを使用して、テストに必要なリソースにアクセスできます。

...

// Retrieve resource
InputStream is = getClass().getResourceAsStream("/test.properties" );

// Do something with the resource

...
14
Pascal Thivent