Help

Inactive Bloggers

Earlier today I saw a transaction question targeted for a completely different audience pop up as the first headline news item on a well known java news site. Besides giving me and my colleagues a good laugh about bugs and transactions it also touched upon one of the questions that have given me a couple of free beers in bar bets and been mind-boggling for students during trainings. The question relates to the following (simplified) code:

Connection con = DriverManager.getConnection(url, name, pwd);
con.setAutoCommit(false);
Statement st = con.prepareStatement("delete VITAL_DATA");
st.executeUpdate();
con.close();

Assuming that VITAL_DATA contains data before we execute this code, will it still contain those data after the call to con.close()?

Yes or No ?

The answer is: It depends!

If this code were executed against an Oracle database VITAL_DATA will no longer contain data since Oracle implicitly calls commit() if your connection has left over changes.

It is about here people starts arguing with me and say I'm crazy! No way that is possible, because all developers who believe in the goodness of transactions and its ACID properties would state that nothing should be committed to a database without an explicit call to commit() when not running in auto-commit mode - anything else would be a sin.

Well, I guess Oracle like to be sinful, and it is even documented.

/Page 3-14, Oracle9i JDBC Developers Guide and Reference/ contains the following text:

If auto-commit mode is disabled and you close the connection
without explicitly committing or rolling back your last changes,
then an implicit <code>COMMIT</code> operation is executed.

I heard from an Oracle tech-guy that this behavior is a left over from how the old OCI library worked - whether that is true or not I don't know; but it sure is a surprise for most developers I have shown this too (including my self the first time I bumped into this issue).

After discovering this a couple of years back I went to look in the JDBC spec to see who is to blame for this behavior.

The fun part is that I have not been able to find anything about the behavior of close() in JDBC besides the following text from the /JDBC 4.0/ spec:

When auto-commit is disabled, each transaction must be explicitly committed by
calling the Connection method commit or explicitly rolled back by calling the
Connection method rollback, respectively.

The javadoc for close() states:

Releases this Connection object's database and JDBC resources
immediately instead of waiting for them to be automatically released

From a naive ACID believing person I would say Oracle are wrong on this, but notice how the specification only mentions how the transaction behaves ? It does not explicitly state that close() is not allowed to commit the data, only that it should release resources (which it does!)

Thus from my perspective Oracle is walking on an edge here, but apparently without breaking the spec. Note that it might also occur on other databases, but it has never occurred for me on the other major databases I have worked with.

Lessons learned ? Always explicitly (or declaratively) commit or rollback your transactions!

19. Oct 2005, 20:04 CET, by Max Andersen

A new updated version of the Hibernate Tools (http://tools.hibernate.org) project have been made available.

The tools are for both Eclipse and ANT, the ANT related docs are at http://www.hibernate.org/hib_docs/tools/ant/index.html

The biggest new feature is that you can now use your annotated classes in the query console (require JDK 5) and thus be able to prototype EJB3 queries.

We also added support for named parameters in the query console making it very easy to test existing queries from your application since you do not need to replace the parameters with inplace values.

See the screenshots and other noteworthy news at http://www.hibernate.org/hib_docs/tools/eclipse/newandnoteworthy/hibernate-eclipse-news-3.1.0.beta1.html for more information.

As always feedback, ideas, contributions, patches, bug-reports are more than welcome by the usual means at http://forum.hibernate.org and JIRA.

Steve just committed a new interface and extension point to Hibernate Core. We can finally plug-in custom Session context management into Hibernate. For those of you who already know getCurrentSession() in Hibernate 3.0, this new extension enables the same without a JTA environment.

But how does it work? In a J2EE container we can rely on the scope of the current JTA transaction to bind the Hibernate Session. So whenever you call getCurrentSession() you get exactly that. Outside of a container, however, we don't really know when a Session ends (starting it is easy: the first time you request one).

So, a new interface was needed to allow Hibernate users to provide a current Session. In fact, the interface CurrentSessionContext has exactly this single method you can implement. But you don't have to, there are two default implementations distributed with Hibernate 3.1:

  • The usual behavior for JTA environments, binding the current Session to the current system transaction This works without any extra configuration, just set up Hibernate for managed J2EE use (transaction manager, etc.), and call sessionFactory.getCurrentSession(). No need to flush or close the Session. If you use CMT, transaction demarcation is declarative, if you use BMT, call the methods beginTransaction(), getTransaction().commit(), and getTransaction().rollback() on the current Session. If you want to you can enable JTA context management in your Hibernate configuration by setting the new property current_session_context_class to "jta", but again, it is the default if Hibernate is configured for J2EE.
  • An implementation for typical Hibernate deployment in non-managed environments, binding the current Session to the current thread. However, this implementation needs a little help from you to mark the end of a unit of work (we can't wait for the thread to end). You have to call the static method ThreadLocalSessionContext.unbind().close() to remove the current Session from the thread, and to close it. To enable this context handler, set the current_session_context_class configuration property to "thread".

Of course you can implement your own CurrentSessionContext and name the class in configuration, for example, to implement a Long Session (or in new terms: extended persistence context) pattern with EJBs, storing the disconnected Session in a SFSB between requests and JTA transactions.

The traditional HibernateUtil class can now finally be reduced to a simple startup helper, used to initialize a SessionFactory. This is how a typical data access routine now looks like in CMT, BMT, and non-JTA environments:

Session s = HibernateUtil.getSessionFactory().getCurrentSession();
s.beginTransaction();
    
s.save(item); // or
HibernateUtil.getSessionFactory().getCurrentSession().save(item);
    
s.getTransaction().commit();

ThreadLocalSessionContext.unbind().close(); // Only needed for non-JTA

With HibernateUtil we don't really care where the SessionFactory is coming from, either static singleton or from JNDI. The last line is only needed for the built-in thread context handling outside of an application server, as explained above. The rest of the code is the same everywhere, in all deployment situations. Usually you would unbind and close the Session in some kind of interceptor and encapsulate the last line in some system class that knows when request processing completes. The two lines of code saving an item are equivalent, the purpose here is to show you that you can call getCurrentSession() as many times and in as many different (DAO) classes as you like.

For all of you who don't want to build Hibernate from CVS to try this new feature: I've prepared an updated CaveatEmptor release that includes a snapshot of Hibernate 3.1 from CVS, updated HibernateUtil, and updated DAO/unit test classes. The other Hibernate documentation (and the popular Wiki pages about Session handling) will be updated later, when an actual 3.1 release is available.

21. Sep 2005, 13:07 CET, by Gavin King

One of the distinctive features of Seam is that a lot more things are treated as components than what you might be used to from other architectures. In fact, pretty much every object you write will be treated as a Seam component.

For example, it is not normal in other frameworks to think of entity objects as components. But in Seam, we would typically treat User as a session-scope component (to model the currently logged in user) and entities like Order and Document as conversation-scope components (most conversations are centric to some entity instance).

Objects that listen for events are also components. Just like JSF, Seam does not have any notion of an Action class. Rather, it lets events be bound to methods of any Seam component. This means, in particular, that one Seam component can model a whole conversation, with the attributes of the component holding conversational state, and the methods of the component defining the functionality that occurs for each step in the conversation. (Note that this would be possible in plain JSF, except for the fact that JSF does not define a conversation context.)

The vision for Seam is that the notion of event will also be a unifying one. An event might be a UI event, it might be Web Services request, a transition event for the long-running business process, a JMS message, or something else we havn't thought of yet.

Again like JSF, an event listener method never takes any argument. This is quite in contrast to GUI frameworks like Swing, or Action based web frameworks like Struts where there is some Event object passed as a paremeter to the action method (a Servlet HttpRequest is an example of this pattern). Alternatively, some other frameworks will expose some thread-bound context object to the action listener. Both JSF and Seam offer thread-bound contexts as a secondary mechanism, but in the case of Seam, this mechanism is for exceptional cases only.

JSF has the right idea here. Ideally, the whole state of the system can be represented by components, that are assembled together automatically by the container. This eliminates the event object or context object from the view of the application, resulting in tidier and more naturally object-oriented code. Under the covers, the JSF implementation locates dependent beans of a managed bean using named context variables, and automagically instantiates a new instance of the needed managed bean if the context variable is empty.

Unfortunately, JSF is limited in three ways.

First, initilizing or modifying the value of a context variable requires direct access to the context object, FacesContext, breaking the abstraction. Seam fixes this problem by introducing outjection.

@In @Out Document document;

public void updateDocument() {
    document = entityManager.merge(document);
}

@Out User user;

public void login() {
    user = entityManager.createQuery("from User user ....")
           .setParameter("username", username)
           .setParameter("password", password)
           .getSingleResult();
}

Second, assembly (dependency injection) is performed when a managed bean is instantiated, which means that, (a) a component in a wide scope (the session, say) cannot have a reference to a component in a narrow scope (the request, for example) and (b) if we modify the value of a context variable, components which were already assembled will not see the new value, and will keep working with the obsolete object. Seam fixes this problem by making assembly (injection/outjection) a process that occurs at component invocation time.

@Entity @Scope(REQUEST)
public class OrderLine { ... }

@Stateful @Scope(CONVERSATION)
public class CreateOrderConversation {
   @In OrderLine orderLine;

   public addOrderLine()
   {
       order.addOrderLine(orderLine);
   }
}

At this time, most other IoC frameworks have the same two limitations, and this is perfectly defensible in the case of something like Spring where the components being injected are understood to be stateless, and hence any two instances of a component are interchangeable. It's not so good if components are stateful, as they are in JSF.

Third, JSF has just three contexts (request, session, application). So, if I want to hold state relating to a particular user across several requests, I have to put it in a session scoped component. This makes it effectively impossible to use JSF managed beans to create an application where the user can be doing two different things, concurrently, working in two windows at once! It also leaves it up to you to clean up state when you're finished with it, by manually removing session context variables via the context object (FacesContext).

Seam is the first attempt to create a truly uniform and unifying model of contexts which are meaningful to the /application/. The five basic contexts are event, conversation, session, business process and application. There is also the stateless psuedo-context.

The conversation context is a logical (application demarcated) context scoped to a particular view (browser window). For example, in an insurance claims application, where user input is collected over several screens, the Claim object might be a conversation scoped component.

The business process context holds state associated with the long running business process being orchestrated by jBPM. If review and approval of the insurance claim involves interaction with several different users, the Claim could be a business process scoped component, and would be available for injection during each user interaction.

You might object that an object might have one scope some of the time, and another scope at other times. Actually, I think this happens /much/ less frequently than you might expect, and if it does occur, Seam will support the idea of the same class having multiple roles in the system.

For applications with /extremely/ complex workflows, nested conversations and nested business processes are almost certainly needed, which opens the possibility for an /arbitrary/ set of scopes. Seam does not currently implement this, but the context model of Seam is designed for eventual extension to cover this kind of thing.

We've even discussed introducing more exotic contexts. Do transaction scoped components make sense? Probably not for application components, but possibly for infrastructural components. (Yes, the Seam component model has uses beyond application component management.) For now I'd prefer not to add things like this until we see a very clear need.

So, by this stage you're probably asking what this idea of contextual components actually /buys/ you? Well, for me there are three key things.

First, it allows us to bind stateful components, expecially entity beans, directly to the webpage. (Note that if you are going to bind your entities directly to JSF forms, you will also need some nice way to do validation, which is where Seam's integration with Hibernate Validator comes into the picture.) So, you can build a whole application from just pages, session-beans bound to events produced by the page, and entity beans bound to the page. It is this possibility for an unlayered architecture which makes Seam such a potentially productive environment. (Of course, if you want to introduce extra layers yourself, you can certainly do that, but it is not forced upon you.)

Second, it means that the container (Seam) can guarantee cleanup of state from ended or abandoned conversations. In the case of abandoned conversations, Seam gives you a choice: for server-side conversations, there is a conversation timeout that is independent of the session timeout. Alternatively, you can use client-side conversations.

Finally, the model allows stateful components to interact in a relatively loosly coupled way. Clients of a component need not to be aware of its lifecycle, or of its relationships to other components. All they need to know is what /kind/ of thing it is, and what are its operations.

19. Sep 2005, 13:28 CET, by Gavin King

We released Seam today.

http://jboss.com/products/seam

I feel like this is something I'm obligated to blog about. Unfortunately, I've just spent the past two weeks writing docs and webpages and blurbs and I feel if I sit down now and try to describe what Seam is all about, then I'll just be saying the same stuff, yet again, in another slightly different way. (And I'm afraid I get more grandiose each time.)

So let me just link to this page instead:

http://docs.jboss.com/seam/reference/en/html/pr01.html

Hopefully, I'll find the time to get a bit deeper into specific bits of Seam in future posts.

Thanks to everyone who made this release possible.

Showing 1176 to 1180 of 1245 blog entries