As a follow up to http://in.relation.to/Bloggers/SimultaneouslySupportingJDBC3AndJDBC4WithMaven, I wanted to point out that I uploaded some example projects to the design discussion. There are 2 different approaches as Maven projects and one Gradle project.
At some point between August and September there appears to have been a number of incorrect auto-unsubscriptions against some of the Hibernate mailing lists (hibernate-dev for sure). I am not going to point fingers as to who is to blame in this. I do however apologize for any inconvenience this might have caused. If you find yourself part of this group, the current direction I am receiving is that you will just have to re-subscribe :( if you happen to still have the unsubscribe notification email I would be very interested in getting it to pass along to our mailman admins; you can forward them to me directly.
Per HHH-2412 and its design discussion I have been working on supporting JDBC4 in Hibernate. Initially I had planned on adding this in 3.6, but now leaning toward 3.5 Anyway, as outlined on the design wiki, I initially thought to add this support as separate modules. However, I quickly came to the realization that using separate modules would actually require users make an explicit choice wrt an
extra jar. Especially considering that I could make Hibernate code make this determination programatically, I really did not like that aspect to using modules here. So I started looking for alternatives.
As I normally do, I started by thinking of just the ideal outside of any build structure or tool. So to my mind the best option here seemed to include compiling JDBC4 support targeting JDK 1.6 and JDBC3 support targeting JDK 1.4 and then bundling all that code into a single jar. The code which decides which feature-set to use uses reflection anyway, so there is no issue with having both in the same jar as long as only the correct classes actually get loaded (and anything else would be a bug in this determination code).
Well unfortunately it turns out that Maven does not really support such a setup. In the common case I think you'd set up multiple source directories within that main module and run different compilation executions against them with different compiler settings (source/target). This Maven explicitly disallows (see MCOMPILER-91 and its discussion for details).
workable solutions were presented to me (workable in that Maven could handle these):
- Use a single source directory, but configure 2 executions of the compiler plugin taking advantage of includes/excludes to define what to compile targeting 1.6 and 1.4. The issue here is that this is not good fit for IDEs.
- Split this into 3 modules (one each for JDB3 and JDBC4 support plus another for
commonalityto avoid circular dependencies with core). Core would then pull the compiled classes from these 3 modules into its jar. Seems overly complicated to me just to work around a self-imposed limitation of Maven. And sorry, I just don't see how this constitutes a
messed up systemas indicated in that Maven discussion.
Anyway, I really hope someone has other suggestions on better ways to handle this with Maven. Anyone?
This is the first release towards supporting JPA 2. Most of the APIs are implemented. Some know limitations for this beta include:
- Some of the 'metamodel' APIs are still unimplemented, specifically differentiating between declared attributes and attributes (same wording as java.lang.reflect). The getDeclaredXYZ methods simply return null in this release.
- 'criteria' query building is fully implemented aside from defining subquery correlations, to the best of my knowledge and current state of the spec. However, compiling criteria queries is unimplemented scheduled for the next release.
Additionally, initial support for
fetch profiles has been added in this release. Currently only join-fetching is supported as a strategy in fetch profiles.
The artifacts have all been published to the JBoss Maven repository. Additionally the release bundles have been uploaded to SourceForge.
This is also the first version bundling annotations, entitymanager and envers together with the other core modules. Moving forward all will be versioned and released together.
Let me preface this by saying up front that, yes, I am fed up with Maven. In the 2 years since I decided to switch Hibernate over to use Maven for its build tool I don't think that Maven has lived up to making builds any easier. Quite the contrary, in fact. Previously though there was not really been any other option. At that time ant/ivy combo was just starting to gain traction. Not to mention that I do like the notion of build-by-convention which Ant just does not provide.
Bugs aside, most of the problems I have with Maven in dealing with Hibernate stem from Maven's assumption that all projects are independently releasable. The problem here is that this extends to sub-projects or
modules as well. With Hibernate, the decision to utilize sub-projects was made solely for the purpose of isolating dependencies to various pieces of optional Hibernate functionality. For example, we have a sub-project specific to dealing with c3p0 as a provider of JDBC connections. The dependency in Hibernate on the c3p0 artifact is isolated completely in this module. So as a user you can simply tell maven that you are using hibernate-core and hibernate-c3p0 and have the transitive dependencies set up correctly. I did not set up these sub-projects so that I could release hibernate-c3p0 independently at some time. I have no desire do go that route as it causes nothing but confusion IMO. Even if nothing were to change in the classes in hibernate-c3p0 I would much rather have that get bumped to the new standardized version.
So anyway, what are the issues with this assumption? Well the first is that I cannot simply 'change directory' into a sub-project directory and build it and expect Maven to build the other projects upon which this sub-project depends for me automatically. For example, I cannot 'cd' into the hibernate-c3p0 project directory and run 'mvn compile' and expect Maven to first compile the hibernate-core project for me even though hibernate-c3p0 depends upon it. This may not sound like a big deal, but Hibernate is a big project with 14 jar-producing projects (not to mention numerous support projects like documentation and distribution-builders). Having to 'cd' around all those different projects just to compile a dependency graph that Maven already know about seems silly. But again, Maven must do this because of this assumption of
The other issue has to do with the notoriously bad support for performing releases. This has bitten me every time I have tried to do a Hibernate release with Maven using it's release plugin. In fact it just caused a 3 day delay in the Hibernate 3.5.0.Beta-1 release. I know the release plugin is just a wrapper around a few mvn commands you can run yourself (in fact that's how I finally ended the 3 day 3.5.0.Beta-1 release marathon); the issue is again back to Maven's
support for multi-project builds. The release plugin is the only current plugin which offers support for managing the numerous version declarations that are required throughout all the sub-projects. So when releasing a project with multiple sub-projects you have 2 options: (1) use the release plugin or (2) (a) update the pom versions manually (b) commit (c) r-tag (d) update the pom versions manually (e) commit (f) checkout the tag (g) perform the mvn deploy. Sure would be nice if the
version management stuff from the release plugin were usable separately.
The other build tools I have been looking at briefly are (1) gradle, (2) buildr and (3) simple-build-tool. Anyone have practical experience with any of these, or suggestions on others we should look at?
<queue-voice-of-god>In the beginning there was jdocbook-styles...</queue-voice-of-god>
jDocBook styles were meant to represent common styling elements that could be developed on their own, built into bundles and used as dependencies to DocBook builds using the jDocBook plugin. The contents of the styles (css and images) were staged to a special directory within the DocBook project's target directory for use within the XSLT formatting.
Recently I have been working on extending that concept to an idea from the world of publican. For those not familiar with it, publican is the DocBook build system used by Fedora and many Red Hat related projects. The idea I was looking at including into the world of jDocBook is what publican terms brands. These brands really provide two somewhat complimentary things:
- fallback content
Much like jdocbook-styles, publican brands allow providing css and images that should be used in the output formatting. The big difference is that brands allow for them to be localized to the particular translations. The notion of 'fallback content' allows common pieces of content (DocBook XML) to be developed and then used throughout various documentation projects. For example, the publican brands generally define fallback content for things like legal notices and document conventions. Again, allows for localization to the various translations in terms of appropriate POT/PO files.
The localization aspect brings up a question wrt jdocbook-styles and the staging of those resources. Currently the resources within a jdocbook-styles are staged into the target/docbook/staging directory by the jdocbook plugin itself (the later formatting phase simply points to them from there for each translation since they are implicitly shared for all translations). Staging of the brands, however, would require that each translation have its own staging directory (ala target/docbook/staging/en-US, etc). So either the jdocbook-styles could be repeatedly exploded into each translation's staging directory or we could make the move to have localized jdocbook-styles as well.
Initially the idea was to have the jDocBook plugin itself perform all these stagings (especially since it does so already for jdocbook-styles). But today another thought crossed my mind: separate out the notions of staging. The basic principle would be to simplify jDocBook to focus on a core competency, namely taking some DocBook XML, some resources, some XSLT and generating some formatted output. This would allow projects not using styles and not using brands to have a very simple jDocBook setup; essentially it would build directly from the controlled sources. For projects with styles and/or brands we would stage everything to the staging directories and configure jDocBook itself to use the staged directories as its input.
Quite a few folks have asked about the new Hibernate Core modules introduced with the 3.3 release: what each is for, when to use which, etc. I wanted to take a bit to describe what each of the main modules is for and when/how you would use certain combinations. (These modules also define maven artifacts; all Hibernate Core artifacts use org.hibernate groupId).
- hibernate-core - defines the basic functionality of Hibernate. It is expected that this module will be split up further in future releases.
- hibernate-jmx - defines the functionality for Hibernate to integrate with JMX servers. Both the org.hibernate.jmx.HibernateService and org.hibernate.jmx.StatisticsService are defined in this module.
- hibernate-ehcache - defines the integration for using EhCache as Hibernate's second level cache
- hibernate-jbosscache - defines the integration for using JBossCache as Hibernate's second level cache, based on the 1.x versions of JBossCache. This integration should be considered deprecated in favor of the newer 2.x based integration...
- hibernate-jbosscache2 - defines the integration for using JBossCache as Hibernate's second level cache, based on the 2.x versions of JBossCache
- hibernate-oscache - defines the integration for using OSCache as Hibernate's second level cache
- hibernate-swarmcache - defines the integration for using SwarmCache as Hibernate's second level cache
- hibernate-c3p0 - defines the integration for using the c3p0 connection pool as Hibernate's ConnectionProvider
- hibernate-proxool - defines the integration for using the proxool connection pool as Hibernate's ConnectionProvider
- hibernate-parent - this acts as the parent pom for all the Hibernate modules. Users will generally never use nor need to know about this module. I wanted to mention it here simply because it might be useful for folks developing extensions to Hibernate.
- hibernate-testing - defines the basic infastructure used by the Hibernate testsuite for building SessionFactories and managing Sessions. Was broken out as a separate module because I thought users might find it useful as well for testing Hibernate-related code.
There are other modules, but the above ones are the ones developers will usually need to use (the others include things like DocBook sources).
The minimum dependency set-up with Javassist and using log4j as logging library would be:
<dependencies> <!-- the dependency on the hibernate-core module (see above) --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>3.3.1.GA</version> </dependency> <!-- want to use Javassist as Hibernate's bytecode provider, so we depend on it here. --> <dependency> <groupId>javassist</groupId> <artifactId>javassist</artifactId> <version>3.4.GA</version> </dependency> <!-- Logging set up --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.5.2</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.14</version> </dependency> </dependencies>
To use cglib instead of Javassist, we would have this instead:
<dependencies> <!-- the dependency on the hibernate-core module (see above) --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>3.3.1.GA</version> </dependency> <!-- Here we are using cglib instead of Javassist (Hibernate 'repackages' cglib to avoid name clashes) --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-cglib-repack</artifactId> <version>2.1_3</version> </dependency> <!-- Logging set up --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.5.2</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.14</version> </dependency> </dependencies>
Now, lets add support for second level caching with EhCache:
<dependencies> <!-- the dependency on the hibernate-core module (see above) --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>3.3.1.GA</version> </dependency> <!-- Here we are using cglib instead of Javassist (Hibernate 'repackages' cglib to avoid name clashes) --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-cglib-repack</artifactId> <version>2.1_3</version> </dependency> <!-- Logging set up --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.5.2</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.14</version> </dependency> <!-- Here is the bit enabling EhCache support --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-ehcache</artifactId> <version>3.3.1.GA</version> </dependency> </dependencies>
As we stated above, we said that the hibernate-ehcache module defines the integration with EhCache. It also defines a dependency on EhCache itself, which maven pulls into our dependencies here
transitively. See the maven documentation for information about how this all works. The point is simply that we just need to depend on the hibernate-ehcache module and the other deps need to use EhCache are handled for us.
Hibernate Core 3.3.1 has just been released with its artifacts published to the JBoss Maven Repository. This release fixed a serious issue with CurrentSessionContext (SessionFactory.getCurrentSession()) when running on IBM WebSphere. It also includes quite a few improvements to the enhanced id generators. For details about all the changes in this release, check out it's changelog