これまでのアプリケーションで同様のニーズがありました。私たちが思いついた解決策は、リソース(Logger、Configファイルなど)をClassLoader(コンテキスト)で取得するResourceManagerでした。
通常、EARとしてデプロイされたアプリケーションはすべて独自のClassLoaderを取得し、ライブラリはResourceManager.getLogger()を呼び出して、現在のスレッド/アプリケーションに関連付けられたLoggerを取得できます。そうすれば、ライブラリ内のすべてのメソッド呼び出しで渡す必要はありません(ライブラリを変更する必要があります)。
Logger logger = Logger.getLogger([Application Logger Name]);
ResourceManager.registerLogger(logger);
は、ライブラリ内のロガーを取得する(ユーティリティメソッド):
private Logger getLogger()
{
return ResourceManager.getLogger();
}
EJB/WebAppのの初期化フェーズで
import java.util.*;
import java.util.logging.*;
public class ResourceManager
{
private static final Map<ClassLoader, Map<String, Object>> resources =
Collections.synchronizedMap(new WeakHashMap<ClassLoader, Map<String, Object>>());
public static final String LOGGER = Logger.class.getName();
static
{
// adjust for log4j or other frameworks
final Logger logger = Logger.getLogger("logging.default");
logger.setLevel(Level.ALL);
logger.addHandler(new ConsoleHandler()
{
{
setOutputStream(System.out);
setLevel(Level.ALL);
}
});
registerResource(null, LOGGER, logger);
}
private static ClassLoader getApplicationScope()
{
return Thread.currentThread().getContextClassLoader();
}
public static void registerResource(final String name, final Object resource)
{
registerResource(getApplicationScope(), name, resource);
}
public static synchronized void registerResource(final ClassLoader scope, final String name, final Object resource)
{
Map<String, Object> hm = null;
hm = resources.get(scope);
if (hm == null)
{
hm = Collections.synchronizedMap(new HashMap<String, Object>());
resources.put(scope, hm);
}
hm.put(name, resource);
}
public static Object getResource(final String name)
{
for(ClassLoader scope = getApplicationScope();;scope = scope.getParent())
{
final Map<String, Object> hm = resources.get(scope);
if ((hm != null) && hm.containsKey(name))
{
return hm.get(name);
}
if (scope == null) break;
}
return null;
}
public static void registerLogger(final Logger logger)
{
registerResource(LOGGER, logger);
}
public static Logger getLogger()
{
return (Logger)getResource(LOGGER);
}
}
登録ロガー(のgetLoggerへの呼び出しの前に登録する必要があります)
これは、現在のスレッドに関連付けられているアプリケーション(EAR)のロガーを返します。
Loggerに限らず、共有したい他のリソースにも使用できます。
制限:デプロイEAR
のResourceManagerとロギングライブラリごとに複数のアプリケーション/ EJBをパッケージ化する場合
注釈として、このソリューションは、ロガーだけでなく、あらゆる種類のリソースを共有するためにも使用できます。 – Stefan
あなたの答えにコードの関連セクションを貼り付け、将来リンクが消滅する場合があります。 – rouble
このメソッドについてもう1つ注意する点は、ライブラリがインスタンス化される前にResourceManager.registerLogger()を呼び出さなければならないことです。それ以外の場合、クラスロガーはすべてデフォルトロガーを使用して設定されます。これは、いくつかの実装では、ディール・ブレーカになる可能性があります。 – rouble