Question

Je développe une application web de servlet java qui gère les informations de plusieurs bases de données (tous structurellement identiques) correspondant chacun à un autre « entreprise ». L'utilisateur sélectionne « les affaires courantes » qui est stockée dans la session et l'application peut afficher ou modifier que « affaires courantes ».

Je voudrais utiliser des ressources tomcat d'une manière dynamique pour avoir accès à ces entreprises qui utilisent JNDI. De cette façon, je peux utiliser les balises SQL jstl ou de contexte dans les recherches servlets. Je ne peux pas définir chaque ressource dans le fichier web.xml car ils sont stockés dans une table SQL. Le résultat final est de pouvoir écrire jsp simple qui a des lignes comme celles-ci:

<%@ 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>

ou servlets qui peuvent avoir des lignes comme celles-ci

String request.getSession().getAttribute("currentBusiness");

Context initial = new InitialContext();
Context context = (Context) initial.lookup("java:comp/env");
DataSource source = (DataSource) context.lookup("sources/" + currentBusiness);

où je peux obtenir la source de données correcte pour le « affaires courantes ».

Je l'ai expérimenté à écrire mes propres ObjectFactories dérivés de javax.naming.spi.ObjectFactory sans succès. Tous les conseils sur la façon de le faire facilement cela?

Était-ce utile?

La solution

Je finalement réglé pour la solution suivante consistant à un SessionListener et Servlet qui fonctionnent comme suit. Le SessionListener a la forme suivante:

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); 

  }

}

Chaque fois est créé un utilisateur se connecte à une session et, la liste des sources de données disponibles, et l'actuel, sont placés dans la session. Cela se fait au niveau de la session parce DataSources Il est maintenant possible d'avoir accès à eux dépendent de la connexion de l'utilisateur. A partir de l'application. Pour changer la source de données actuelle j'ai créé un Servlet avec cette version simplifiée:

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

  }

}

Avec cette implémentation, il est désormais possible de créer les jsps suivants:

<%@ 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>

it helps quelqu'un d'autre.

Autres conseils

Créer des sources de données dans un ServletContextListener et placez-les dans le ServletContext .

Cette approche va certainement « travailler », mais la notion d'une base de données séparée, identique pour chaque entreprise semble mal pour moi. Certes, être en mesure de délimiter des affaires quelque part dans le schéma semble possible. Les séparer de cette façon nécessite une nouvelle base de données par entreprise, où un schéma ne nécessiterait un nouvel identifiant d'affaires.

Je dirais également que toute possibilité d'exploration de données inter-entreprises est perdu, à moins que vous les données de processus ETL bases de données distinctes dans un cube dimensions pour des rapports ad hoc et l'interrogation.

JSTL balises ne doit être utilisé dans les applications web les plus simples. Vous vous laisser ouvert à la possibilité d'attaques par injection SQL lorsque vous renoncez à la validation sur un niveau intermédiaire.

Mise à jour:

Vous devez déclarer les ressources dans votre web.xml autant que je sache, donc chaque fois que vous avez une nouvelle base de données que vous devez arrêter l'application, configurer la nouvelle source JNDI et redémarrez Tomcat. J'espère que vous êtes en cluster, parce que tous les anciens clients seront touchés par l'application étant à chaque fois que vous ajoutez une nouvelle entreprise / base de données.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top