Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipselink-users] SessionCustomizer to modify/detect database platform: impossible

On Thu, Feb 21, 2013 at 5:46 AM, Tom Ware <tom.ware@xxxxxxxxxx> wrote:
  It looks like the use-case where you want auto-detection of database platform for all but a single platform is not well covered by the current code base.

Hi, Tom; thanks.  The use cases involved go really more like this (similar, but not matching :-)):

Database platforms/dialects will always be buggy.  Some databases will get more attention than others.  Therefore users need to be able to easily subclass and override and replace these platforms.  [EclipseLink has this part covered.  All JPA providers do.]

Java EE configuration is hard.  End users taking delivery of a .war or an .ear file with a .jar file inside it that contains the JPA persistence.xml file rarely if ever "crack open" these containers.  Expecting an end user to specify a property that varies by database platform is onerous.  Instead, the JPA provider should feature an auto detection mechanism for the underlying platform.  [So far so good; EclipseLink has this too.]

What EclipseLink *doesn't* have is the ability to *mix* these two cases.  By contrast, Hibernate does have this: you can plug in/pick up your own autodetection mechanism with a single property (http://docs.jboss.org/hibernate/orm/4.1/javadocs/org/hibernate/service/jdbc/dialect/spi/DialectResolver.html).
 
 I see you've filed bug 401388 for this issue.  The easiest way for us to address your specific issue is to make the isInformixOuterJoin flag a boolean on the InformixPlatform that could be set in your customizer, this could be done quickly, but would not help you for your 2.3.2 deployment.

Right.
 
  The possible workarounds I see are:

1. Pass the new platform as a property when your EntityManagerFactory is created

Yep; that works, but we build big hairy .ear files and then test them on a variety of databases.  The unpack, unzip, rezip etc. steps are beyond annoying.  The QA folks aren't used to it, because when we were pinned to Hibernate we supplied our own DialectResolver that let us programmatically install our own platforms (to work around the legions of Hibernate platform bugs) without any intervention by the end user.  Now the QA department has to be told all this.  :-)
 
2. Try to override the auto-detection yourself.  This would involve roughly the following steps 
  - Use the eclipselink.target-database property in your persistence.xml to set a platform... Any platform. (this setting will make EclipseLink avoid it's own auto-detection code)

Yep, did that.
 
  - In a prelogin event use the code from our DatabaseSessionImpl.loginAndDetectDatasource method to use our auto-detection code and then override the InformixPlatform if it is detected.

I did this originally.  The very next thing that happens is DatabaseSessionImpl.loginAndDetectDatasource blows the platform away.  See line 687 (on the trunk) of DatabaseSessionImpl.java and preceding.  :-(
 
 Here is the code as it exists.  You could override the platformName if it was the InformixPlatform:

--
                try {
                    String vendorNameAndVersion = conn.getMetaData().getDatabaseProductName() + conn.getMetaData().getDatabaseMajorVersion();
                    platformName = DBPlatformHelper.getDBPlatform(vendorNameAndVersion, getSessionLog());
                    getLogin().setPlatformClassName(platformName);
                } catch (EclipseLinkException classNotFound) {
                    if (platformName.indexOf("Oracle") != -1) {
                        // If we are running against Oracle, it is possible that we are running in an environment where
                        // the OracleXPlatform class can not be loaded. Try using OraclePlatform class before giving up

getLogin().setPlatformClassName(OraclePlatform.class.getName());
                    } else {
                        throw classNotFound;
                    }
                }

Yep.  I did that:

...in a preLogin() event (that caused my work to be erased; see above),

...in a SessionCustomizer#customize() call (that worked fine, but then was erased again downstream somehow; haven't traced that through--although to be fair I don't think I explicitly set a "wrong" target-database property as well),

...and then thinking I was clever, in a *postLogin()* event (to get around the line 687 problem).  This latter approach worked, but then led to discovering the bug where table-generator-sequenced entities can no longer "see" their QuerySequence (the QuerySequence is handed a null query at some point).  I wasn't sure which of these approaches therefore was the best or the worst.
 
Sorry this is so involved.

That's fine; I also have a cooler head this morning.  :-)

Best,
Laird
 
--
http://about.me/lairdnelson

Back to the top