On Sat, 3 Mar 2001, fractals wrote:
> Hi again Dan,
>
> And thanks so much for your patience !
No problem. I learn best by explaining what I (think I) know. And at least
you're typing the entire word 'you' 8^}).
>
> Well, this is a neat solution indeed. The fact is, I've never used
> transactions so I don't know what they cost. At the very moment, I am
> beginning an implementation using JTA. To begin with, let's say that I'll
> probably abandon this idea in favor to yours. But I'd just want to expose it
> for the sake of completeness:
>
> First off, I plan to use a centralized session management system, so I don't
> have to be concerned by the http server providing the web interface, i.e.
> there could be many http servers running servlets that access my
> application. To do this, I have a Stateful Session Bean I call a
> UserSession, which is accessed by the servlets via a Stateless Session Bean
> I call a Gatekeeper. Gatekeeper has a static Thread
That might work, but it won't be portable. According to the spec, EJB's
can't do thread things.
> with a static Hashtable
> field which holds the current active sessions. The thread part is used to
> periodically check the time-to-live fields of the UserSessions, and
> decrement them appropriately (and, again, I don't know if this is really
> needed).
Shouldn't be needed. Stateful session beans time out - take a look in
standardjboss.xml at the Standard Stateful SessionBean container config -
theres a stanza in there about the cache config that sets all that up.
Accessing stateful beans from stateless makes me nervous, but I can't give
you a reason offhand that it wouldn't work.
> By the time I was waiting to an answer to my last question, I had
> defined the following methods to the remote interface of UserSession:
>
> public int checkPinCode ( String pinCode ) throws RemoteException;
> public boolean checkPseudo ( String pseudo ) throws RemoteException;
> public boolean setPassword ( String password ) throws RemoteException;
> public void setAnnouncePrefs ( int flags ) throws RemoteException;
> public void setUserData ( String data ) throws RemoteException;
> public void finishRegistration () throws RemoteException;
Looks good.
>
> As I stated in my question, checking the pinCode is the first thing I do. So
> in UserSessionBean (the actual EJB), this is what I was doing:
>
> SessionContext context;
> UserTransaction ut;
> Connection con;
>
> public int checkPinCode ( String pinCode )
> throws RemoteException
> {
> // obtain user transaction interface
> ut = context.getUserTransaction();
> // start a transaction
> try {
> ut.begin();
> } catch ( javax.transaction.NotSupportedException e ) {
> throw new RemoteException ( "transaction not supported" );
> } catch ( javax.transaction.SystemException e ) {
> throw new RemoteException ( "transaction system exception " +
> e );
> }
> try {
> makeConnection();
> } catch (Exception ex) {
> throw new RemoteException("Unable to connect to database. " +
> ex.getMessage());
> }
>
> try {
> // do the actual mess with the database...
> con.close ();
> } catch ( Exception ex ) {
> System.out.println ( "could not check pinCode: " + ex );
> throw new RemoteException ( "checkPinCode: " + ex.getMessage
> () );
> }
> return 0;
> }
>
> Of course, when everything finishes, I'd have to call ut.commit () (in the
> finishRegistration () method) or rollback on time out, etc...
>
> I'd be interested to read any comments on this, as I am at least going to
> try out the darn thing, unless someone tells me to just not.
Well that thread thing is non-portable, and you really don't need the
gatekeeper. According to the spec, what you've done should work.
>
> regards,
>
> candide
>
>
> > You're right, you have a problem.
> >
> > Just off the cuff, here's what I'd think about doing.
> >
> > I assume this is a web app? this makes it hurt worse.
> >
> > This is an awfully long transaction. You really don't want a real
> > transaction open this long. Therefore, I'd use the HTTP Session to store
> > up all the information I need, then make a call to a stateless session
> > bean that does all of it in one transaction. I've made comments below on
> > what I'd do differently.
> >
> >
> > On Sat, 3 Mar 2001, fractals wrote:
> >
> > > Hi,
> > >
> > > This is a very simple question concerning transactions:
> > >
> > > I need to make a user-registration in multiple steps:
> > >
> > > 1. The user enters a pin code that corresponds to a certain amount of
> money
> > > he/she spent to get access to the application
> > > -> application checks the pin code, and marks a corresponding
> pinCode
> > > EJB that the pin code is now used (it cannot be used by another user at
> the
> > > same time)
> > Mark the pinCode EJB 'reserved' at this point, so that we can tell this
> > 'in process' stuff from actually used pin codes. Save the PIN in the
> > session.
> >
> > >
> > > 2. The user sets his/her pseudo
> > > -> application creates a new User EJB
> > > -> application validates pseudo
> > Just save the pseudo in the HTTP Session. Probably build a bean that holds
> > pseude, password, and preferences in the session. make that bean implement
> > the session binding listener stuff, so it knows when it times out.
> >
> > >
> > > 3. The user sets his/her password
> > > -> application validates password
> > > -> application sets the password on the User EJB
> > Put the password in the same bean. Still no access to any User EJB
> >
> > >
> > > 4. The user sets preferences and provides additional info
> > > -> application stores the data on the User EJB
> > Put this in the same bean. No User EJB yet.
> >
> > >
> > > 5. The user terminates and is prompted to log in
> > > -> everything's OK, the transaction can commit
> > Call a session bean, passing it all the stuff we have in the session that
> > creates the user, sets password and all prefs, etc, then marks the pinCode
> > EJB 'used'. Tell the bean (the session thingy) that he's done then remove
> > him from the session.
> >
> > >
> > > At any point, the user can leave is/her chair/terminal so everything has
> to
> > > be rolled back after a given amount of time. This also means that the
> > > temporary objects (rows), like the User EJB, have to be deleted.
> > Since we haven't created anything, there isn't much to do. Remember that
> > the bean in the session implemented the session binding listener
> > stuff? That means that if he gets unbound before we tell him to complete
> > (because the session timed out), he can clean up, which will consist of
> > setting the pinCode EJB to 'unused' from 'reserved'
> >
> >
> > What all this does is layers the user's logical unit of work over the top
> > of the low-level transactions. One happy result is that we have a lot less
> > transaction load hitting the EJB container, which will let it scale
> > better. An unhappy result is that we're making our HTTP sessions bigger,
> > which will effect the JSP/Servlet container's ability to scale. Make sure
> > anthing you put into the HTTP Session is serializable so it can be swapped
> > out. Consider saving session state in a temporary database (either
> > directly from the JSP/servlet or via a tempuser EJB) to conserve memory.
> >
> >
> > >
> > > I'm not sure I've well understood the transaction mechanism. In
> particular,
> > > I don't understand when the transaction really begins and ends. As far
> as I
> > > got it, the transaction is a call-level mechanism: if a method is called
> on
> > > an object and that method calls another method of another object, the
> whole
> > > call chain forms the transaction. What I really need is a client to make
> a
> > > call to an object's method, then later, when my client makes a call to
> > > another object's method, to be able, if anything goes wrong, to undo
> what
> > > was done before when the first object's method was called. I think the
> > > following settings don't allow for such a thing:
> > >
> > > <ejb-jar>
> > > ...
> > > <assembly-descriptor>
> > > ...
> > > <container-transaction>
> > > <method>
> > > <ejb-name>User</ejb-name>
> > > <method-name>*</method-name>
> > > </method>
> > > <trans-attribute>Required</trans-attribute>
> > > </container-transaction>
> > > <container-transaction>
> > > <method>
> > > <ejb-name>PinCode</ejb-name>
> > > <method-name>markUsed</method-name>
> > > </method>
> > > <trans-attribute>Required</trans-attribute>
> > > </container-transaction>
> > > </assembly-descriptor>
> > > </ejb-jar>
> > >
> > >
> > > _______________________________________________
> > > JBoss-user mailing list
> > > [EMAIL PROTECTED]
> > > http://lists.sourceforge.net/lists/listinfo/jboss-user
> > >
> >
> > --
> > Dan Christopherson (danch)
> > nVisia Technical Architect (www.nvisia.com)
> >
> > Opinions expressed are mine and do not neccessarily reflect any
> > position or opinion of nVISIA.
> >
> > --------------------------------------------------------------------------
> -
> > If you're a capitalist and you have the best goods and they're
> > free, you don't have to proselytize, you just have to wait.
> > -Eben Moglen
> >
> >
> > _______________________________________________
> > JBoss-user mailing list
> > [EMAIL PROTECTED]
> > http://lists.sourceforge.net/lists/listinfo/jboss-user
> >
>
>
> _______________________________________________
> JBoss-user mailing list
> [EMAIL PROTECTED]
> http://lists.sourceforge.net/lists/listinfo/jboss-user
>
--
Dan Christopherson (danch)
nVisia Technical Architect (www.nvisia.com)
Opinions expressed are mine and do not neccessarily reflect any
position or opinion of nVISIA.
---------------------------------------------------------------------------
If you're a capitalist and you have the best goods and they're
free, you don't have to proselytize, you just have to wait.
-Eben Moglen
_______________________________________________
JBoss-user mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-user