There are a similar threads without a concrete solution and I thought it was better to start a new one.
I am facing a situation where I have a WebApp hosted in RESIN (just like Tomcat I guess). So far I have been developing the app using db4o since I'm alone and I needed to complete the app ASAP, I have a DB for users and another DB for app data for a single user (me), now that the app is almost done I'm about to move to postgresql and I am thinking seriously about a DB per user even if the DB holds data for multiple apps since it will handle kinda confidential data and I thought having separate DB will be the best (security wise). There is already a rudimentary session management that stores user data like an ID in the browser. But I was wondering how can I expand it to multiple users/db.
I was thinking to expand the listener class that keeps the context data to pass the right db object to the app instance, or maybe set a filter for that purpose.
.UPDATE.
I wanted to give some more insight of what I currently have.
I have:
Context that holds a reference to some objects, one of those objects connects to a DB and checks for the user and password.
Presentation servlet (HttpServlet) mapped to "/" that has the login form that POST to /login.
Login servlet (HttpServlet) mapped to "/login" that checks the httpSession user password attributes against the respective object that rests in the Context, if there is a match sets an httpSession attribute that holds the USERID and redirects the user to the app itself located at /index-debug.html if not it creates a new html page with a login form again.
Authorization and authentication filters mapped to /index-debug.html that verifies the httpServletRequest for the USERID attribute and checks whether or not the user has permission to access the app.
Finally a DB bean that is in charge of reading and writing to the webApp user data DB. When I execute certain method in the webApp CP2JAVAWS matches that method to the respective method in the bean, the problem is that this bean has a static database and so far it only allows one user at the time.
What I would like to do is somehow allow this DB bean to instantiate once per user and read and store the corresponding data depending of the current logged user.
The idea of one DB per user is currently discarded but I don't know how exactly pull that off.
You mentioned Postgres as the database backend and that has the feature called schemas. This is something where you have one physical database and multiple schemas inside the database. My experience with this comes from Rails, but the concepts are the same. This method avoids mashing people's data together in the same set of tables which sounds like your primary concern. I know you're using Java, but watch this talk on Multi-tenant apps in Rails to get a background from Guy Naor on how this works, trade-offs, etc.
Here are some concrete steps to get you started down this path of using Postgres schemas:
Come up with a naming convention for each schema you will create (e.g. user_001, user_002, etc.). Pre-allocate a bunch of empty schemas with all the tables setup and when the user registers or logs in for the first time, you assign them a schema and store the schema name in their user record in the public schema and in the user object that you have in HttpSession. There would be no need to run table creation scripts for a first time user - that would be a performance drag in a web app. You just need to stay ahead of the rate of new users. For example you could have a bunch of empty user_standby_1 ... user_standby_100 schemas and then when someone logs in or registers, you would run this sql:
myquery = "ALTER SCHEMA user_standby_? RENAME TO user_?";
myquery.setString(1,standby_id);
myquery.setString(2,user_id);
When you create your DB bean (use a superclass for this, see below), pass in the schema name from the User object from the HttpSession, then execute this SQL before every operation to isolate them to their schema only:
myquery2 = "SET search_path TO ?";
myquery2.setString(1,user.search_path);
If you have an empty full schema in public, then you want to omit public from the search path otherwise you will have 2 tables with the same name in the search path. If you want the users search path to include SET search_path TO user_001,public
then after creating tables, drop all the data tables from public other than users and any meta-info you need.
If you go the alternative route and have all users data in one set of tables, then the best approach is to have user_id in every table and write your SQL to use that every time. If you use traditional normalization and do joins to get your user_id, then you better make sure you don't accidentally miss a join or users will start seeing each others data.
The Postgres schema feature allows you to lock users access to only their own data. After figuring out the basics, use a superclass in Java to write step 3 above so every MyTableDBBean extends from MasterDBBean and uses the super class constructor to isolate the search path to the user's schema. Then you only have 1 place in your code where this is done and you don't have to remember for every table or query to do anything more than the business logic.