The correct contract of a Session is the Threading usage. a Session is supposed to be the interaction of the application with its session.
So, so, not trying to educate everybody on the contract of Session.. just stating the reasoning out loud... (please correct me or add your own reasoning also)
I have two big points on why this is needed:
- Session represents the interaction with threading, as well as transactionality. Which creates a lot of confusion: First objects created from the session can leak into other threads by "user's misuse".
- Things get even more complex with modern systems using reactive mode and transactionality, making it even more complex to manage.
A better explanation:
back then (20 years ago ;) ), you would do something like this:
Connection connection = connection.createConnection(..... whatever goes in here...);
Session session1 = connection.createSession(.... transaction mode, ack modes... whatever else goes in here...);
Thread thread1 = new MyThread(session1);
thread1.start();
Session session2 = connection.createSession(.... transaction mode, ack modes... whatever else goes in here...);
Thread thread2 = new MyThread(session2);
thread2.start();
If users wrote code like that, it would all work fine.. but it's not that simple any more:
You could create multiple consumers from a single session and send all of them into multiple threads... which is an "against the spec" usage.. and there is no boundaries in the API preventing that type of use. I lost count of how many times I had to tell users to not do that... and that still happens from time to time.
Session session = connection.createSession(true, Session.SESSION_TRANSACTED); // a transacted session
Consumer consumer1 = session.createConsumer(session.createQueue("destination1"));
Consumer consumer2 = session.createConsumer(session.createQueue("destination2"));
MyThread thread = new MYThread(session, consumer1);
thread.start();
MyThread thread2 = new MYThread(session, consumer2);
thread2.start();
class MyThread extends Thread {
Session session;
Consumer consumer;
MyThread(Session session, Consumer consumer) {
this.session = session;
this.consumer = consumer;
}
public void run () {
consumer.receive();
if (Random.randomBoolean()) {
session.commit();
} else {
session.rollback();
}
}
}
On this example before... things will get sketchy... And there's no way to prevent that from the API.. you have to tell users to read a book before they use it.
If we make the Session gone, we could make this more tidy up.
And I had seen cases like this all the time from users on different messaging systems (JBoss Messaging, then HornetQ, ActiveMQ5, Artemis.... ) I have not seen it in other systems but I'm sure that will happen.
And this also represents a big challenge for API suppliers as it's a big incognito on what to do.