Help

Inactive Bloggers
10. Feb 2006, 04:08 CET, by Gavin King

Seam 1.0 beta 2 has been released:

http://sourceforge.net/project/showfiles.php?group_id=22866&package_id=163777

There are too many changes and new features for me to list them all here, but I'll talk briefly about the three most interesting things.

The first is the idea of workspace management. You can see this feature in action by trying out the Seam Issue Tracker demo application that is included in the Seam distribution. Workspace management is like a Windows taskbar for web applications: the user can view a list of active workspaces (Seam conversations), switch between them and manage them, all within a single browser window. The list of workspaces may be represented as a drop down menu or clickable list. If you use Seam's powerful new nested conversation model, you can even have Seam automatically manage a meaningful trail of breadcrumbs.

You don't have to write any Java code to take advantage of workspace management in Seam, just include some standard JSF fragments in your JSP or Facelets pages.

For more information about this stuff, refer to the Seam documentation:

http://docs.jboss.com/seam/reference/en/html/conversations.html#d0e2374

The second new feature is tight integration with jBPM. In Seam, jBPM can fill two distinctly different roles.

The first role is traditional business process management (workflow). In this case, jBPM and Seam provide management of task lists, task assignment, business process execution, and business process state without any need to write any Java code. You can call Seam components from your jPDL file in exactly the same way that you call Seam components from a JSF page: by writing a JSF EL expression.

For example, the following trivial Seam/jPDL workflow definition might be used to describe a TODO list.

<process-definition name="todo">
  
  <start-state name="start">
     <transition to="todo"/>
  </start-state>
  
  <task-node name="todo">
     <task name="todo" description="#{todoList.description}">
        <assignment actor-id="#{actor.id}"/>
     </task>
     <transition to="done">
        <action expression="#{todoList.sendEmail}"/>
     </transition>
  </task-node>
  
  <end-state name="done"/>
  
</process-definition>

Check out the Seam DVD Store or Todo List examples to see exactly how this stuff fits together, or refer to the Seam documentation:

http://docs.jboss.com/seam/reference/en/html/jbpm.html#d0e2696 The second application of jBPM in Seam is pageflow definition. A Seam jPDL pageflow defines the navigation for a particular conversation. Just like a business process definition, we use JSF EL to define the interaction between the pageflow and the Seam components. This lets us centralize all information about the flow of the user interaction, and how the different components and pages fit together to implement the user interaction in one place.

Here is an example pageflow for a number guessing game:

<pageflow-definition name="numberGuess">
  
  <start-state name="start">
     <transition to="displayGuess"/>
  </start-state>
  
  <page name="displayGuess" view-id="/numberGuess.jsp" redirect="true">
     <transition name="guess" to="evaluateGuess">
     	<action expression="#{numberGuess.guess}" />
     </transition>
  </page>
  
  <decision name="evaluateGuess" expression="#{numberGuess.correctGuess}">
     <transition name="true" to="win"/>
     <transition name="false" to="evaluateRemainingGuesses"/>
  </decision>
  
  <decision name="evaluateRemainingGuesses" expression="#{numberGuess.lastGuess}">
     <transition name="true" to="lose"/>
     <transition name="false" to="displayGuess"/>
  </decision>
  
  <page name="win" view-id="/win.jsp" redirect="true">
     <end-conversation />
  </page>
  
  <page name="lose" view-id="/lose.jsp" redirect="true">
     <end-conversation />
  </page>
  
</pageflow-definition>

Notice how easy it is to get an understanding how the pages and Seam components fit together to solve the business problem.

For more information, refer to the Seam DVD Store or Number Guess examples in the Seam distribution, or to the Seam documentation:

http://docs.jboss.com/seam/reference/en/html/jbpm.html#d0e2530

The final interesting new feature is the application reverse engineering functionality provided by the latest release of Hibernate Tools. It takes just minutes to create a pretty full-featured application with CRUD, Search screens and full association navigation. This is a great way to get started with Seam.

More information (including screenshots) here:

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

Over the past few months, Seam has developed a vibrant community and so I've enjoyed working on this project more than anything since the early days of Hibernate. Thanks to everyone who has been involved!

03. Feb 2006, 23:44 CET, by Max Andersen

I have been fed up with Velocity ís ability to ignore and even hide errors and exceptions occurring in the templates used in Hibernate Tools .

This blog tells about why and how FreeMarker became my new interest. If you just want to see the results then go and fetch the code in the TOOLS_FREEMARKER branch...read on to get the full story.

The problems with Velocity

I started to see more and more forum postings and bug reports about issues that were caused by typoís in users templates or even worse errors in the Hibernate Tools. Many of these issues would be solvable within seconds if Velocity would actually tell where in the templates the error occurred and unit tests would have failed if underlying exceptions were exposed; but Velocity simply does not.

I have added every safety-precaution I have been able to apply to Velocity error handling. I have created my own UberSpect and EventHandler implementation that will not allow you to invoke methods that does not exist and I have tweaked the logging settings to be more informative; but it does not (hardly) solve all the problems that can occur.

Logging is excessive in Velocity even at WARN and INFO level, one good reason for this is most likely that the developers know that Velocity is ignoring situations where it should actually fail, thus since there is no easy other way implemented in Velocity they put it in the log for users to discover by accident!

The choice originally fell on Velocity since it was the biggest player around, and I added it naively thinking that the error and log handling could not be that bad if so many people were using it and if there were an issue it would be fixed soon.

As time went by I learned that it was definitely not the case.

The beauty of FreeMarker

Last week I decided to look around for alternatives, the only real alternative I found were FreeMarker; everything else looked either too simple or way to complex for the Hibernate Tools needs. Now that I have spent just 1,5 day converting the existing Velocity templates to FreeMarker Iím more than happy I did.

Here are some examples of the beauty of FreeMarker:

Assume we have the following bean:

public class Table {
 String getName();
}

The bean is available via table in the following code:

${table.namee}

That typo will just be ignored by default in Velocity, with a custom EventHandler it can be convinced to throw an exception which comes out like this:

Caused by: java.lang.IllegalArgumentException: $table.namee is not a valid reference.
at org.hibernate.tool.hbm2x.HibernateEventHandler.referenceInsert([=>HibernateEventHandler.java:11])
        at org.apache.velocity.app.event.EventCartridge.referenceInsert([=>EventCartridge.java:131])
        ... 19 more

No information about which template nor where in the temmplate it went wrong.

In FreeMarker I get the following with no special configuration and custom code:

Expression table.namee is undefined on line 15, column 14 in doc/tables/table.ftl.
The problematic instruction:
----------
==> ${table.namee} [on line 15, column 12 in doc/tables/table.ftl]
----------

Java backtrace for programmers:
----------
freemarker.core.InvalidReferenceException: 
 Expression table.namee is undefined on line 15, column 14 in doc/tables/table.ftl.
    at freemarker.core.TemplateObject.assertNonNull([=>TemplateObject.java:124])
    at freemarker.core.Expression.getStringValue([=>Expression.java:118])
    at freemarker.core.Expression.getStringValue([=>Expression.java:93])
    ...

Nice! And even better, the on line 15, ... works like a link in e.g. Eclipse Console view. Clicking it brings you to the location of the error in the table.ftl. file.

Similar and precise error messages you get if you refer to non existing methods, Just brilliant! The great thing is that if I really wanted FreeMarker to ignore this I could do so by installing a different Exception handler. But that is my choice, not a hard to change behavior.

The built in primitives in FreeMarker is also great, e.g. <#assign> that allows me to store any generated output in a variable for later usage.

${pojo.getPackageDeclaration()}
// Generated ${date} by Hibernate Tools ${version}
<#assign classbody>
 <#include "PojoTypeDeclaration.ftl"/> {
  ..more template code..
 }
</#assign>

${pojo.generateImports()}
${classbody}

This allows me to remove the need to have a magically second-pass which I did with Velocity. There are more gems like these to be found in the excellent FreeMarker documentation .

Another big plus in FreeMarker's favor is the Configuration API . Let us compare, here is our Velocity setup:

engine = new VelocityEngine();
context = new VelocityContext();

EventCartridge ec = new EventCartridge();
ec.addEventHandler(new HibernateEventHandler()); // stricter evaluation
ec.attachToContext( context );
            
Properties p = new Properties();
p.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, 
              "org.apache.velocity.tools.generic.log.CommonsLogLogSystem");
p.setProperty(CommonsLogLogSystem.LOGSYSTEM_COMMONS_LOG_NAME, 
              "org.hibernate.tool.hbm2x.template");

p.setProperty( RuntimeConstants.UBERSPECT_CLASSNAME, HibernateUberspect.class.getName() ); // stricter evaluation

p.setProperty("velocimacro.library",""); // make it shut up about VM_global_library blah
      
p.setProperty("resource.loader", "file, class");
p.setProperty("file.resource.loader.path", directory );
p.setProperty("class.resource.loader.class", ClasspathResourceLoader.class.getName() );

engine.init(p);

Here is the corresponding FreeMarker config:

engine = new Configuration();
context = new SimpleHash(ObjectWrapper.BEANS_WRAPPER);

//Logger.setCategoryPrefix("org.hibernate.tool.hbm2x.template"); 
// Not really needed since the logging is much more sensible.

freeMarkerEngine.setTemplateLoader(new MultiTemplateLoader( 
                                    new FileTemplateLoader(directory), 
                                    new ClassTemplateLoader(this.getClass(),"/"));

Notice the difference? FreeMarker has good practice defaults and actually allows me to use java code to configure it; what a neat concept.

The only two bad things I have found yet with FreeMarker is that itís syntax is based on <#..> which does not compute very well when trying to show it in an XML editor. This has been fixed in the latest release by also allowing [#...] syntax.

Another bigger issue is that ${} and #{} is not escapable. This syntax collides in templates that generates ant build and jsp files.

In Velocity they were just ignored (the only place were it were useful to ignore them). FreeMarker complains because the values are undefined and unfortunately there is no easy-on-the-eyes method to escape these characters. The following show the methods that I found to allow the me to output ${..}:

${r"${build.dir}"}  
${'$í}{build.dir} 
<#noescape>${build.dir}</noescape>

Still the brilliant exception handling, powerful template language and configuration API makes FreeMarker a much better choice for Hibernate Tools.

What now ?

Velocity served me well and is probably serving many projects well; it just did not cut it well for Hibernate Tools. Today I am convinced that I could have saved myself and the Hibernate world from a lot of trouble if I had decided to use FreeMarker from the beginning.

Come and see for your self in the TOOLS_FREEMARKER branch. The code in there will be merged into the main development in the near future unless someone steps up with a very good reason for not doing so ;)

To be fair, I must tell you that Velocity 1.5 is being worked on right now, and it does seem to solve some of these issues, but not completely and Velocity has some external dependencies I would rather not add to the tools project.

30. Jan 2006, 06:42 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. In this release the documentation for both ANT and Eclipse have been extensively updated and merged into a reference documentation, see http://www.hibernate.org/hib_docs/tools/reference/en/html_single/

See screenshots and other noteworthy news at http://www.hibernate.org/hib_docs/tools/eclipse/newandnoteworthy/hibernate-eclipse-news-3.1.0.beta4.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.

Currently we are discussing wether FreeMarker should replace the current Velocity template engine used in the tools or if something can be done to make the Velocity templates more userfriendly. Come and join at http://forum.hibernate.org/viewtopic.php?t=954602

I found a posting from Emmanuel with the following link to the JDK bug tracking system .

Let's say you annotated a class with Hibernate Annotations and made it an EJB 3.0 @Entity bean. Let's also assume that you wrote your own annotations, for whatever metadata you might need in your system. If you now try to discover your annotations through Reflection, you will also need the EJB 3.0 interfaces in your classpath, even if you don't access the EJB 3.0 annotations.

It looks like this was fixed and will soon be included in a JDK update release.

In the past few months I got the impression that something in our explanation of object/relational mapping has gone a little wrong. I'm still not sure that this is the fault of any documentation or presentation slide, it's just something that naturally happened...

It seems to me that many many users of Hibernate (and very likely other similar tools) think that they absolutely have to map a collection. Basically, many developers, especially if they have not been exposed to some data management basics and have survived with a purely object-oriented view of the world, seem to think that persistent collections are an absolute must-have. Sometimes it's quite a surprise when I explain how you can write a sophisticated and complete Hibernate application without ever mapping a single collection!

This is even more important if you are only starting to learn Hibernate; mapping a collection right is definitely the biggest step in the learning curve. I want to clear up some of the confusion around collection mappings (the actual reason is a guy who wants us to declare unusable on the Hibernate Annotations website because the current beta doesn't allow you to map a Map of entities across a join table...)

Every time you think you have to map a collection you have to ask yourself /Why/. A mapped persistent collection is a /feature/, not a requirement. What does this feature give you:

  • You no longer have to retrieve the data you are looking for with a query, you can just iterate through a collection. Naturally, this iteration can always, no exception, be replaced with a query.
  • You no longer have to maintain a relationship (please, stop calling it relation) between two pieces of data manually. For example, you can just put a child object into a collection of a parent object (I really hate this explanation but it's a convenient lie) and have it saved automatically. Naturally, this cascading persistence can always, no exception, be replaced with an explicit call of the persistence manager.
  • An object/relational mapping software can make optimizations when you access the collection, such as batch fetching or /extra/ lazy behavior if you just call size() on it. These are goodies that might make your life easier, but they can always, no exception, be replaced with a query. (Actually, this is conceptually true, but doesn't work for batch and subselect collection fetching in Hibernate 3.1 - addition of these features to the query API is on the list.)

So, you map a collection if you want one of these features. You don't map it if these features are of no advantage to you! In other words: a relational database has foreign keys (copies of keys and constraints to hold it together) and nothing else. All foreign key relationships can be represented in Java with many-to-one associations. Everything else is sugar, features, convenience. Yes, you often want this convenience and you are right to expect it from an object/relational mapping software. But you don't have to force a collection mapping, especially if you don't know how to do it right or what you really get from it.

Showing 1176 to 1180 of 1256 blog entries