Domanda

Sto sviluppando un'applicazione web servlet Java che gestisce le informazioni provenienti da più database (tutti strutturalmente uguali) ciascuno corrispondente ad un diverso "business".L'utente seleziona "l'attività corrente" che viene memorizzata nella sessione e l'applicazione può visualizzare o modificare tale "attività corrente".

Vorrei utilizzare Tomcat Resources in modo dinamico per avere accesso a queste attività utilizzando jndi.In questo modo posso utilizzare i tag jstl sql o le ricerche di contesto nei servlet.Non riesco a definire ciascuna risorsa nel file web.xml perché sono archiviate in una tabella SQL.Il risultato finale è quello di poter scrivere una semplice jsp che abbia righe come queste:

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

o servlet che possono avere righe come queste

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

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

dove posso ottenere l'origine dati corretta per il "business attuale".

Ho sperimentato la scrittura dei miei ObjectFactory derivati ​​da javax.naming.spi.ObjectFactory senza successo.Qualche indicazione su come farlo facilmente?

È stato utile?

Soluzione

Alla fine ho optato per la seguente soluzione composta da un SessionListener e un Servlet che funzionano come segue.Il SessionListener ha la seguente forma:

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

  }

}

Ogni volta che un utente accede e viene creata una sessione, l'elenco dei DataSource disponibili e quello corrente vengono inseriti nella sessione.Questo viene fatto a livello di sessione perché le origini dati dipendono dall'accesso dell'utente.Ora è possibile accedervi dall'interno dell'applicazione.Per modificare l'attuale DataSource ho creato una Servlet con questa versione semplificata:

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

  }

}

Con questa implementazione è ora possibile creare i seguenti jsps:

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

Spero che aiuti qualcun altro.

Altri suggerimenti

Creare le origini dati in a ServletContextListener e posizionarli nel ServletContext.

Questo approccio "funzionerà" sicuramente, ma l'idea di un database separato e identico per ciascuna azienda mi sembra sbagliata.Sicuramente essere in grado di delineare il business da qualche parte nello schema sembra possibile.Separarli in questo modo richiede un nuovo database per azienda, mentre uno schema richiederebbe solo un nuovo identificatore aziendale.

Direi anche che ogni possibilità di data mining interaziendale viene persa, a meno che non si trasferiscano i dati ETL da database separati in un cubo dimensionale per reporting e query ad hoc.

E i tag JSTL <sql> dovrebbero essere utilizzati solo nelle app Web più semplici.Ti lasci aperto alla possibilità di attacchi SQL injection quando rinunci alla convalida su un livello intermedio.

AGGIORNAMENTO:

Devi dichiarare le risorse nel tuo web.xml AFAIK, quindi ogni volta che hai un nuovo database devi arrestare l'applicazione, configurare la nuova origine JNDI e riavviare Tomcat.Spero che tu sia in cluster, perché tutti i client precedenti saranno interessati dall'inattività dell'app ogni volta che aggiungi una nuova attività/database.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top