Help

Inactive Bloggers
24. Apr 2006, 23:07 CET, by Max Andersen

Hibernate Tools 3.1.0.beta5 (http://tools.hibernate.org) have been made available.

The tools are for both Eclipse and ANT.

This version is where the template functionallity is finally based on FreeMarker.

As an extra treat the tools now bundle a FreeMarker plugin to help out when writing custom templates (Thanks to Joe Hudson).

ANT users also get a most-wanted feature, namely removal of the old requirement of having to specify all mapped classes in hibernate.cfg.xml when e.g. generating the schema based on EJB3 annotated classes.

The new <ejb3configuration> support in the ant task allows standard EJB3 persistence packaged projects to be automatically scanned for mappings and then used like any other Hibernate compatible configuration.

See screenshots and other noteworthy news at here for more information.

10. Apr 2006, 22:45 CET, by Gavin King

I, for one, welcome our new penguin overlords.

The last couple of months have been pretty nerve wracking. The various rumors floating about generated a fair amount of uncertainty for our customers, employees and user community at large (nevertheless, despite the uncertainty, March was a record month for sales!). In the end, Marc chose to sell to Red Hat. This is the combination that offers the greatest synergies to both companies, is most reassuring to our customers, and causes the least disruption to our overall business and technology strategy. Most of all, it clearly signals our continued commitment to Free Software. The two companies have similar business models, similar licenses and a similar record of successful evangelization and commercialization of open source.

The planned acquisition of JBoss by Red Hat will revitalize the middleware market - expect a more competitive marketplace, with all major products based on open source codebases. And expect us to be leaders in SOA. No other software company offers an open source enterprise software platform of comparable depth and maturity.

Obviously, Marc deserves all the congratulations he's getting today. He's delivered on basically everything he promised when I joined the company two and a half years ago (back when there were three people working out of our Atlanta headquaters). He's changed the middleware market for good. He's built a company where technical people have the freedom to pursue their ideas. And he's made a whole bundle of money for himself and his employees.

For a technical guy like me, JBoss is Camelot. Three years ago I was dragging myself out of bed each morning to go to my depressing job building boring web applications for organizations run by risk-averse middle managers and clueless architects. I was thoroughly frustrated with the lack of productivity of the technology platform - always WebSphere - that was forced down my throat by these guys. And I knew I was wasting most of my life sitting in a cube reading blogs (the dirty secret is that when you sit them in a cube farm, very few developers are actually productive for more than about three of the eight hours in a workday). That was a world where an idea - however unoriginal - was valued on the basis of how many grey hairs were in evidence on the head of the person expressing the idea. But the hair was not the only thing that needed to be grey. In the world of professional services, only the greyest personalities succeed. Passion, creativity, vision - all liabilities. Knowing no other world, I believed that that world was the whole world. At night I'd work on Hibernate, hoping that perhaps - if Hibernate became wildly successful - I might get just an ounce more respect in that world, despite my obvious lack of greyness.

My first visit to America was for a conference in Massachusetts. JBoss sent Bill Burke and Ben Sabrin to meet and recruit me. These guys are the perfect metaphor for the culture of JBoss: a culture driven equally by technology and sales. Bill is a technology guy through and through. Ben is my perfect ideal of a fast-talking American salesman. If Ben tries to sell you something, you can't possibly not buy it. Ben sold me JBoss. A few weeks later I was back in the states to meet Marc Fleury. I was expecting a difficult relationship here. I'd been warned by a several people that Marc was a difficult guy. I'm a difficult guy myself. And indeed, for a while, there were many difficult issues to work through. This was all happening during what were undoubtedly the darkest days for JBoss. A month or two earlier, three people had very noisily left the company and, through clever PR, created the impression that JBoss Group had split down the middle. The rest of the company felt deeply betrayed, angry and distrustful. But as memories of those events faded, what remained was a more unified, more motivated company. Bitterness was transformed into purposeful determination. The company grew from a headcount of less than 20 to almost 200. To my knowledge, not a single developer has left the company in the period since I joined. If you're creative, self-motivated, thick-skinned, this is perhaps the best software company in the world to work for. I look forward to seeing the continuation of this culture at Red Hat.

20. Mar 2006, 20:00 CET, by Gavin King

Recently, Simon Brown put together a set of requirements for a very simple blogger application that could be used to compare Java web frameworks. I have my reservations about the actual requirememts he put together (in particular, there is no form submission!) but since some other framework authors have bitten, I've gone ahead and ported the example to Seam. I want to put a massive caveat around this post: Seam is absolutely not designed for applications like blogs or web forums; these kind of problems are very easy to solve using something like PHP or Ruby on Rails and there is no really good reason to use Java for a problem like this (unless Java is all you know). We have a set of requirements here with /no conversations/ and /no business processes/, so all the sophisticated state management machinery of Seam is redundant. Nevertheless, frameworks need to make simple things easy, and you'll see how little Java code we need to write to solve this simple problem using Seam.

To begin, I copied the standard Seam web.xml, faces-config.xml, application.xml and build.xml files from the Seam booking demo, changing names in a couple of places, and removing all the JSF navigation rules from faces-config.xml. None of this stuff is interesting, and it is always almost identical in every Seam application. I also copied Simon's screen.css stylesheet.

Simon started out with a domain model with Blog and BlogEntry classes that in a real application would be mapped to the database via Hibernate or EJB3, along with a BlogService class, which implements a static singleton containing some test data. The static variable and static initializer is an incredibly ugly way to implement a singleton in Seam, so I took the liberty of rewriting this class as an application-scope Seam component.

@Name("blog")
@Startup
@Scope(APPLICATION)
public class BlogService 
{

   private Blog blog;

   @Create
   public void initBlog()
   {
      blog = new Blog();
      blog.setName("Webapp framework blog");
      blog.setDescription("Comparison of J2EE web application frameworks");
      blog.setLocale(new Locale("en", "AU"));
      blog.setTimeZone(TimeZone.getTimeZone("PST"));
      blog.addBlogEntry(new BlogEntry(...);
      blog.addBlogEntry(new BlogEntry(...);
      blog.addBlogEntry(new BlogEntry(...);
   }
  
  @Unwrap
  public Blog getBlog()
  {
     return blog;
  }

}

I left Blog and BlogEntry the way I found them and just copied them across.

That's all we need to start work on the first page of the web application.

There is some common header information on all pages of the application, so we'll use a facelets template, template.xhtml, to define the common stuff.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
                      "[=>http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd]">
<html xmlns="[=>http://www.w3.org/1999/xhtml]"
      [=>xmlns:ui=]"=>http://java.sun.com/jsf/facelets"
      [=>xmlns:h=]"=>http://java.sun.com/jsf/html"
      [=>xmlns:f=]"=>http://java.sun.com/jsf/core"
      [=>xml:lang=]"en"  
      lang="en">
      
<f:view>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
      <title>#{blog.name}</title>
      <link href="screen.css" rel="stylesheet" type="text/css" />
   </head>
   
   <body>
      <div id="container">
         <h1>#{blog.name}</h1>
         <h2>#{blog.description}</h2>
         <[=>ui:insert] name="content"/>
      </div>
   </body>
</f:view>

</html>

Note that this is all plain XML with namespaces, no wierd tags.

The index page, index.xhtml, in the example application displays a list of the three latest blog entries.

<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
                             "[=>http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd]">
<[=>ui:composition] xmlns="=>http://www.w3.org/1999/xhtml"
    [=>xmlns:ui=]"=>http://java.sun.com/jsf/facelets"
    [=>xmlns:h=]"=>http://java.sun.com/jsf/html"
    [=>xmlns:f=]"=>http://java.sun.com/jsf/core"
    template="template.xhtml">

<[=>ui:define] name="content">
   <h:dataTable value="#{blog.recentBlogEntries}" var="blogEntry" rows="3">
      <h:column>
         <div class="blogEntry">
            <h3>#{blogEntry.title}</h3>
            <div>
               #{blogEntry.excerpt==null ? blogEntry.body : blogEntry.excerpt}
            </div>
            <p>
               <h:outputLink value="entry.seam" rendered="#{blogEntry.excerpt!=null}">
                  <f:param name="blogEntryId" value="#{blogEntry.id}"/>
                  Read more
               </h:outputLink>
            </p>
            <p>
               Posted on 
               <h:outputText value="#{blogEntry.date}">
                  <f:convertDateTime timeZone="#{blog.timeZone}" locale="#{blog.locale}" type="both"/>
               </h:outputText>
            </p>
         </div>
      </h:column>
   </h:dataTable>
</[=>ui:define]>

</[=>ui:composition]>

This is of course also plain XML.

(Usually I would not need to explicitly define locales in my templates. JSF and Seam use the request locale by default. But Simon's requirements say that I have to use the locale of the Blog.)

Now, if we hit http://localhost:8080/seam-blog/index.seam, this is the result:

http://hibernate.org/~gavin/blog_index.png

Now for the blog entry page (which we get to by clicking Read more). Assuming I've understood them correctly, Simon's requirements say that if a nonexistent entry is requested, we are supposed to send a 404 error and forward to an error page. Now, this is not the most natural thing to do in JSF or Seam. Usually, JSF applications use pull-style MVC when handling GET requests. Normally I would write the entry page to be able to handle the case of a nonexistent entry (this is easy). But Simon is the boss here, and his requirements call for a push-style design. We'll use a Seam /page action/.

@Name("entryAction")
public class EntryAction
{
   @In private Blog blog;
   @In private FacesContext facesContext;
 
   @RequestParameter
   private String blogEntryId;
   
   @Out(scope=EVENT, required=false)
   private BlogEntry blogEntry;

   public void getBlogEntry() throws IOException
   {
      blogEntry = blog.getBlogEntry(blogEntryId);
      if (blogEntry==null)
      {
         HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
         response.sendError(HttpServletResponse.SC_NOT_FOUND);
         facesContext.responseComplete();
      }
   }

}

This action is meant to run before the entry page is rendered. It retrieves the requested BlogEntry from the singleton instance of Blog and outjects it to the event context. If no BlogEntry matches the request parameter, it sends a 404 error.

We need to list the page action in WEB-INF/pages.xml.

<pages>
   <page view-id="/entry.xhtml" action="#{entryAction.getBlogEntry}"/>
</pages>

Now we can write the entry page, entry.xhtml:

<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
                             "[=>http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd]">
<[=>ui:composition] xmlns="=>http://www.w3.org/1999/xhtml"
                [=>xmlns:ui=]"=>http://java.sun.com/jsf/facelets"
                [=>xmlns:h=]"=>http://java.sun.com/jsf/html"
                [=>xmlns:f=]"=>http://java.sun.com/jsf/core"
                template="template.xhtml">

<[=>ui:define] name="content">
   <div class="blogEntry">
      <h3>#{blogEntry.title}</h3>
      <div>#{blogEntry.body}</div>
      <p>
         Posted on 
         <h:outputText value="#{blogEntry.date}">
            <f:convertDateTime timezone="#{blog.timeZone}" locale="#{blog.locale}" type="both"/>
         </h:outputText>
      </p>
   </div>
</[=>ui:define]>

</[=>ui:composition]>

Along with the 404 error page, 404.xhtml:

<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
                             "[=>http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd]">
<[=>ui:composition] xmlns="=>http://www.w3.org/1999/xhtml"
                [=>xmlns:ui=]"=>http://java.sun.com/jsf/facelets"
                [=>xmlns:h=]"=>http://java.sun.com/jsf/html"
                [=>xmlns:f=]"=>http://java.sun.com/jsf/core"
                template="template.xhtml">

<[=>ui:define] name="content">
   <h3>Page not found</h3>
</[=>ui:define]>

</[=>ui:composition]>

This page needs to be listed in web.xml:

<error-page>
   <error-code>404</error-code>
   <location>/404.seam</location>
</error-page>

Now if I click the Read more link, I get to the URL http://localhost:8080/seam-blog/entry.seam?blogEntryId=3 and see the following:

http://hibernate.org/~gavin/blog_entry.png

If I edit the URL and change the id to 6, I'll get a 404:

http://hibernate.org/~gavin/blog_404.png

And so we're done :-)

People using the Criteria API have either transparently or knowingly used a ResultTransformer . A ResultTransformer is a nice and simple interface that allows you to transform any Criteria result element. E.g. you can make any Criteria result be returned as a java.util.Map or as a non-entity Bean.

Criteria Transformers

Imagine you have a StudentDTO class:

public class StudentDTO {
  private String studentName;
  private String courseDescription;
  
  public StudentDTO() { }
      
  ...
} 

Then you can make the Criteria return non-entity classes instead of scalars or entities by applying a ResultTransformer:

List resultWithAliasedBean = s.createCriteria(Enrolment.class)
  .createAlias("student", "st").createAlias("course", "co")
  .setProjection( Projections.projectionList()
                   .add( Projections.property("st.name"), "studentName" )
                   .add( Projections.property("co.description"), "courseDescription" )
          )
          .setResultTransformer( Transformers.aliasToBean(StudentDTO.class) )
          .list();

 StudentDTO dto = (StudentDTO)resultWithAliasedBean.get(0);  

This is how ResultTransformer have been available since we introduced projection to the Criteria API in Hibernate 3.

It is just one example of the built in transformers and users can provide their own transformers if they so please.

Jealous programming

Since I am more a HQL/SQL guy I have been jealous on Criteria for having this feature and I have seen many requests for adding it to all our query facilities.

Today I put an end to this jealousy and introduced ResultTransformer for HQL and SQL in Hibernate 3.2.

HQL Transformers

In HQL we already had a kind of result transformers via the (select new http://www.hibernate.org/hib_docs/v3/reference/en/html/queryhql.html#queryhql-select) syntax, but for returning non-entity beans it only provided value injection of these beans via its constructor. Thus if you used the same DTO in many different scenarios you could end up having many constructors on this DTO purely for allowing the select new functionality to work.

Now you can get the value injected via property methods or fields instead, removing the need for explicit constructors.

List resultWithAliasedBean = s.createQuery(
  "select e.student.name as studentName," +
  "       e.course.description as courseDescription" +
  "from   Enrolment as e")
  .setResultTransformer( Transformers.aliasToBean(StudentDTO.class))
  .list();

StudentDTO dto = (StudentDTO) resultWithAliasedBean.get(0);

SQL Transformers

With native sql returning non-entity beans or Map's is often more useful instead of basic Object[]. With result transformers that is now possible.

List resultWithAliasedBean = s.createSQLQuery(
  "SELECT st.name as studentName, co.description as courseDescription " +
  "FROM Enrolment e " +
  "INNER JOIN Student st on e.studentId=st.studentId " +
  "INNER JOIN Course co on e.courseCode=co.courseCode")
  .addScalar("studentName")
  .addScalar("courseDescription")
  .setResultTransformer( Transformers.aliasToBean(StudentDTO.class))
  .list();

StudentDTO dto =(StudentDTO) resultWithAliasedBean.get(0);

Tip: the addScalar() calls were required on HSQLDB to make it match a property name since it returns column names in all uppercase (e.g. STUDENTNAME). This could also be solved with a custom transformer that search the property names instead of using exact match - maybe we should provide a fuzzyAliasToBean() method ;)

Map vs. Object[]

Since you can also use a transformer that return a Map from alias to value/entity (e.g. Transformers.ALIASTOMAP), you are no longer required to mess with index based Object arrays when working with a result.

List iter = s.createQuery(
  "select e.student.name as studentName," +
  "       e.course.description as courseDescription" +
  "from   Enrolment as e")
  .setResultTransformer( Transformers.ALIAS_TO_MAP )
  .iterate();

String name = (Map)(iter.next()).get("studentName");

Again, this works equally well for Criteria, HQL and native SQL.

Reaching Nirvana of native sql

We still miss a few things, but with the addition of ResultTranformer support for SQL and the other additions lately to the native sql functionality in Hibernate we are close to reach the Nirvana of native sql support.

Combined with StatelessSession you actually now got a very flexible and full powered sql executor which transparently can map to and from objects with native sql without any ORM overhead.

...and when you get tired of managing the sql, objectstate, lifecycles, caching etc. of your objects manually and want to benefit from the power of an ORM then you got it all readily available to you ;)

06. Mar 2006, 02:13 CET, by Steve Ebersole

A bug report was recently opened in Hibernate's JIRA stating that Hibernate incorrectly handles deadlock scenarios. The basis for the report was an example in the /Pro Hibernate 3/ book (Chapter 9). For those perhaps not familiar with the term deadlock, the basic gist is that two processes each hold resource locks that the other needs to complete processing. While this phenomena is not restricted to databases, in database terms the idea is that the first process (P1) holds a write lock on a given row (R1) while the second process (P2) holds a write lock on another row (R2). Now, to complete its processing P1 needs to acquire a write lock on R2, but cannot do so because P2 already holds its write lock. Conversely, P2 needs to acquire a write lock on R1 in order to complete its processing, but cannot because P1 already holds its write lock. So neither P1 nor P2 can complete its processing because each is indefinitely waiting on the other to release the needed lock, which neither can do until its processing is complete. The two processes are said to be deadlocked in this situation.

Almost all databases have support to circumvent this scenario by specifying that locks should be timed-out after a certain period of time; after the time-out period, one of the processes is forced to rollback and release its locks, allowing the other to continue and complete. While this works, it is not ideal as it requires that the processes remained deadlocked until the underlying timeout period is exceeded. A better solution is for the database to actively seek out deadlock situations and immediately force one of the deadlock participants to rollback and release its locks, which most databases do in fact also support.

So now back to the /Pro Hibernate 3/ example. Let me say up front that I have not read the book and so do not understand the background discussion in the chapter nor the authors' intent/exceptations in regards to the particular example code. I only know the expectations of a (quite possibly mis-guided) reader. So what this example attempts to do is to spawn two threads that each use their own Hibernate Session to load the same two objects in reverse order and then modify their properties. So the above mentioned reader expects that this sould cause a deadlock scenario to occur. But it does not. Or more correctly, in my running of the example, it typically does not, although the results are inconsistent. Sometimes a deadlock is reported; but the vast majority of runs actually just succeed. Why is that the case?

So here is what really happens in this example code. As I mentioned before, the example attempts to load the same two objects in reverse order. The example uses the entities Publisher and Subscriber. The first thread (T1) loads a given Publisher and modifies its state; it is then forced to wait. The second thread (T2) loads a given Subscriber and modified its state; it is then forced to wait. Then both threads are released from their waiting state. From there, T1 loads the same Subscriber previously loaded by T2 and modifies its state; T2 loads the same Publisher previously loaded by T1 and modifies its state. The thing you need to keep in mind here is that so far neither of these two Sessions have actually been flushed, thus no UPDATE statements have actually occurred against the database at this point. The flush occurs on each Session after each thread's second load and modify sequence. Thus, until that point neither thread (i.e. the corresponding database process) is actually holding any write locks on the underlying data. Clearly, the outcome here is going to depend upon the manner in which the two threads are actually allowed to re-awaken by the underlying threading model, and in particular whether the UPDATE statements from the two sessions happen to get interleaved. If the two threads happen to interleave their requests to the database (i.e. T1's UPDATE PUBLISHER happens first, T2's UPDATE SUBSCRIBER hapens second, etc) then a deadlock will occur; if not interleaved, then the outcome will be success.

There are three ways to inequivocally ensure that lock acquisition errors in the database force one of these two transactions to fail in this example:

  • use of SERIALIZABLE transaction isolation in the database
  • flushing the sesssion after each state change (and the end of the example code's step1() and step2() methods)
  • use of locking (either optimistic or pessimistic)

Seems simple enough. Yet apparently not simple enough for the reader of the /Pro Hibernate 3/ book that opened the previously mentioned JIRA case. After all this was explained to him, he wrote me some ill-tempered, misconception-laden replies in private emails. I am not going to go into all the misconceptions here, but one in particular I think needs to be exposed as many developers without a lot of database background seem to stumble over various concepts relating to transactions. Isolation and locking are not the same thing. In fact, to a large degreee, they actually have completely opposite goals and purposes. Transaction isolation aims to isolate or insulate one transaction from other concurrent transactions, such that operations performed in one transaction do not effect (to varying degrees, based on the exact isolation mode employed) operations performed in others. Locking, on the other hand, has essentially the exact opposite goal; it seeks to ensure that certain operations performed in a transaction do have certain effects on other concurrent transactions. In fact locking really has nothing to do with transactions at all except for the fact that their duration is typically scoped to the transaction in which they are acquired and that their presence/absense might affect the outcome of the different transactions. Perhaps, although I cannot say for sure, this confusion comes from the fact that a lot of databases use locking as the basis for their isolation model. But that is just an implementation detail and some databases such as Oracle, Postgres, and the newest SQL Server have very sophisticated and modern isolation engines not at all based on locking.

Showing 1041 to 1045 of 1129 blog entries