I can't find a good sollution for this problem:
I need some instances of the same object, with different initialisation, that need to be accessible simultaneously be many clients.
It's important to minimize the nb of instances because it takes a while before it is created, and it thread-safe.
In concrete, it's about 3 databases having the same table structure, but each one containing the data of a specific group of users.
DB db1 = new DB("MS");
DB db2 = new DB("SUN");
DB db3 = new DB("BE");
The DB object knows about the table structure.
things i tried:
- deploy same stateless session bean with different deploy-time env settings for the same env-parameters:
does not work when the two instances are deployed on the same computer
- stateless session bean:
no way to make different initialisations
- entity bean:
it's getting clear to me that one entity bean may have many instances to represent the same object (pk). You cannot control it, because the container decides it.
- statefull session bean:
i did not try this but it feels strange; i would have to store my statefull session bean in the application context (or a global cache), because all the clients need to be able to access each of the three instances of that one object.
Which option seems best, or are there other alternatives?
You don't say what the DB class does, but if you want to have a J2EE application which works simultaneously on three different databases *of_identical_structure* then all you need to do is lookup the appropriate datasource for each request. (I don't know if you can do this for entity beans, but I don't use them)
So when you want to get a DB connection you have code which says:
DataSource ds = (DataSource)s_initCtx.lookup(getDSNameForCurrentUser(...));
Where getDSNameForCurrentUser() decides which datasource you want to use for this request.
You define a datasource for each DB in your EJB server configuration.
Does that help?
yes that's right, but the exact problem is this:
i don't talk to a connection, but i do talk to an object (called storage) that encapsulates a database.
So, in your sollution, i would have to add a line
Storage bla = new Storage(ds.getConnection())
This is ok, but constructing the storage over and over is waste of time and memory, because the only thing that changes is the actual connection to use.
That's why i made abstraction of the connection, and in stead i give my storage a connection factory, and that factory is responsible for handing the right connection, just in time.
If i had one database, the connectionfactory could have been a DataSource. But i want many databases, and many simultaneous threads, all working in the same Storage. Therefore i made a mapping between threads and connections.
So far so good. Now i want to make an ejb that will allow the databases to be accessed remote.
The remote interface of my ejb
void add(String s)
void remove(String s)
I realize, if i want to be able to work with many databases, then either
1) i have to pass the db name along in every call
2) or i find out which db to use by looking in some context
3) or i make different instances representing different db's
1) is not nice, i will not add a String database_name (or a parameter indicating the datbase) to every method of my interface. I won't because it propagates into my Storage object (i would have to pass the parameter along in every method there).
2) this can not be done in ejb. The context you have only contains the principal name and it's roles. You can not add anything there.
3) this is the only option left. Here comes my question; what can i do to achieve this: a fixed limited nb of instances of the same ejb, each with it's own initialisation data (the datasource jndi name).
now, go back to my first question to see the options there.
So you want to do something like:
RemoteIf i = lookup("MS"); // this is a function which finds the EJB for 'MS'
Collection c = i.getData();
Connection c = getDataSource("MS").getConnection();
Without passing "MS" from the client to the server?
Is that right?
yes! i only want to pass "MS" when i look up the server. Because i have many methods, i don't want to pass "MS" with every method.
I think you should bite the bullet and pass the context.
Any other way is going to require either code changes or deployment changes if you introduce a new DB.
This really feels like simply another parameter to your methods, given that the behaviour is no different.
yuk :( I hate the idea. ugly! ugly! ugly! no! ;)
I think you also mean i'ld have a statless session ejb.
When i introduce a new DB, of course the deployment will change. I think that's not a good point.
I'm still wondering what a statefull session ejb would do: i mean, i make in the client (= web app), for each DB one statefull session bean, and i share those beans over all incomming web requests (for example by putting those ejb references in the application context). The thing is, what happens when two threads access the same session bean at the same time? That's not really a natural situation...
Only one thread can access a stateful session bean at a time.
so if two threads try to access the same instance then the second thread will get a RemoteException.
I think this approach might not work.....