サーブレット・コンテキストのための複数の動的データ・ソース
質問
私は、それぞれ異なる「ビジネス」に対応する(構造的に同じすべての)複数のデータベースからの情報を管理するJavaサーブレットのWebアプリケーションを開発しています。ユーザーがセッションに格納され、アプリケーションがその「現在のビジネス」を表示または変更することができ、「現在のビジネス」を選択します。
私は、JNDIを使用してこれらの事業へのアクセス権を持っているために、動的な方法でTomcatのリソースを使用したいと思います。このように、私は、サーブレットでJSTLのSQLタグまたはコンテキスト検索を使用することができます。これらはSQLテーブルに格納されているので、私は、web.xmlファイル内の各リソースを定義することはできません。最終結果は、これらのような行があり、単純なJSPを書くことができるようにすることです。
<%@ taglib uri="http://java.sun.com/jstl/sql" prefix="sql" %>
<sql:query var = "users" dataSource="sources/${sessionScope.currentBusiness}">
select id, firstName, lastName FROM user
</sql:query>
やサーブレットこれらのような行を持つことができます。
String request.getSession().getAttribute("currentBusiness");
Context initial = new InitialContext();
Context context = (Context) initial.lookup("java:comp/env");
DataSource source = (DataSource) context.lookup("sources/" + currentBusiness);
ここで私は、「現在のビジネス」の正しいデータソースを取得することができます。
私は成功せずにはjavax.naming.spi.ObjectFactory由来自分ObjectFactoriesを書いて実験してきました。簡単にこれを行う方法上の任意のポインタ?
解決
私は最終的にSessionListenerと、次のように動作するサーブレットに成る以下のソリューションを解決しました。 SessionListenerは次の形式を持っています:
public class SessionListener implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent event) {
HttpSession session = event.getSession();
// get list of possible data sources available to this session
List<DataSource> sources = new ArrayList<DataSource>();
... code to get the available sources
// get the current data source
DataSource source = null;
... code to get the current source
source = sources.get(0); // for example
// setup the session attributes
session.setAttribute("availableSources", sources);
session.setAttribute("currentSource", source);
}
}
ユーザがログインすると、セッションが作成されるたびに、、利用できるデータソースのリスト、および現在のものは、セッションに配置されています。データソースは、ユーザーのログインに依存しているためこれは、セッション・レベルで行われます。アプリケーション内からそれらにアクセスすることができるようになりました。現在のデータソースを変更するには、私は、この簡易版でサーブレットを作成します:
public abstract class BoxletServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession(true);
String s = request.getParameter("source");
// based on 's' choose from the available DataSource
List<DataSource> sources = (List<DataSource>) session.getParameter("availableSources");
Source source = chooseFrom(sources, s);
session.setParameter("currentSource", source);
// forward to a page saying that the DataSource changed
}
}
この実装では、以下のJSPを作成することが可能になりました。
<%@ taglib uri="http://java.sun.com/jstl/sql" prefix="sql" %>
<sql:query var = "users" dataSource="${sessionScope.currentSource}">
select id, firstName, lastName FROM user
</sql:query>
それは他の誰かを助けることを望みます。
他のヒント
のServletContextListener とのServletContextするに配置しますます。
このアプローチは確かに「仕事」になるが、各事業の個別の、同じデータベースの概念は、私には間違っているようです。確かにスキーマのどこかにビジネスを描くことができることが可能と思われます。それらをこのように分離することで、スキーマが唯一の新しいビジネス識別子を必要とする業務ごとに新しいデータベースを、必要とします。
私はまた、アドホックレポート作成およびクエリのための次元の立方体に別々のデータベースからでない限り、あなたETLデータ、クロスビジネスデータマイニングの可能性が失われたと主張していると思います。
そして、JSTL
UPDATE:
あなたは私の知る限り、あなたのweb.xmlにリソースを宣言する必要があり、その新しいデータベースを持っている時はいつでもあなたは、アプリケーションを停止し、新たなJNDIソースを設定し、Tomcatを再起動する必要があります。以前のすべてのクライアントアプリは、あなたが新しいビジネス/データベースを追加するたびにダウンしているの影響を受けることになるので、私は、クラスタ化している願っています。