Announcement Announcement Module
Collapse
No announcement yet.
Hibernate - Maven schema generation Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Hibernate - Maven schema generation

    I was wondering if it would make sense to allow access to Configuration object that LocalSessionFactoryBean creates internally. See below to see why it is needed.

    I was trying to patch the maven hibernate plugin to generate DDL based on spring context and LocalSessionFactoryBean bean instance.

    The biggest problem was that LocalSessionFactoryBean clears the ThreadLocal variable that hold DataSource instance. As a result, by the time SchemaExport is executed DataSource has been cleared out.

    My hack was to duplicate the LocalDataSourceConnectionProvider inside the plugin so that it uses its own thread local variable rather than LocalSessionFactoryBean's and extract data source through reflection from the dataSource.

    Proof of concept hack (cannot even call that mess a patch) against the maven CVS follows.

    Thank you,
    Vladimir

  • #2
    The hack against maven hibernate plugin

    Index: plugin.jelly
    ================================================== =================
    RCS file: /home/cvspublic/maven-plugins/hibernate/plugin.jelly,v
    retrieving revision 1.8
    diff -u -r1.8 plugin.jelly
    --- plugin.jelly 6 Nov 2004 21:52:23 -0000 1.8
    +++ plugin.jelly 8 Dec 2004 15:53:26 -0000
    @@ -52,7 +52,10 @@
    outputFile="${maven.hibernate.output.file}"
    basedir="${maven.hibernate.input.dir}"
    includes="${maven.hibernate.input.includes}"
    - excludes="${maven.hibernate.input.excludes}"/>
    + excludes="${maven.hibernate.input.excludes}"
    + springContext="${maven.hibernate.spring.context}"
    + springBean="${maven.hibernate.spring.localsessionf actorybean}"
    + />
    </goal>

    <goal name="hibernate:schema-update" prereqs="hibernate:init" description="Update Hibernate schema">
    Index: plugin.properties
    ================================================== =================
    RCS file: /home/cvspublic/maven-plugins/hibernate/plugin.properties,v
    retrieving revision 1.4
    diff -u -r1.4 plugin.properties
    --- plugin.properties 2 Jul 2004 07:32:53 -0000 1.4
    +++ plugin.properties 8 Dec 2004 15:53:26 -0000
    @@ -15,6 +15,8 @@
    # -------------------------------------------------------------------

    #maven.hibernate.properties=
    +maven.hibernate.spring.context=
    +maven.hibernate.spring.localsessionfactorybean=
    maven.hibernate.quiet=yes
    maven.hibernate.text=no
    maven.hibernate.drop=no
    Index: project.xml
    ================================================== =================
    RCS file: /home/cvspublic/maven-plugins/hibernate/project.xml,v
    retrieving revision 1.40
    diff -u -r1.40 project.xml
    --- project.xml 7 Nov 2004 00:40:31 -0000 1.40
    +++ project.xml 8 Dec 2004 15:53:26 -0000
    @@ -1,5 +1,4 @@
    <?xml version="1.0" encoding="UTF-8"?>
    -
    <!--
    /*
    * Copyright 2001-2004 The Apache Software Foundation.
    @@ -17,14 +16,14 @@
    * limitations under the License.
    */
    -->
    -
    <project>
    - <extend>../plugin-parent/project.xml</extend>
    + <!-- <extend>../plugin-parent/project.xml</extend> -->
    <pomVersion>3</pomVersion>
    + <artifactId>maven-hibernate-plugin</artifactId>
    + <groupId>maven-hibernate-plugin</groupId>
    <id>maven-hibernate-plugin</id>
    <name>Maven Hibernate Plug-in</name>
    - <currentVersion>1.3-SNAPSHOT</currentVersion>
    - <description/>
    + <currentVersion>1.3-SNAPSHOT-SIUH</currentVersion>
    <shortDescription>Work with Hibernate classes</shortDescription>
    <url>http://maven.apache.org/reference/plugins/hibernate/</url>
    <issueTrackingUrl>http://jira.codehaus.org/browse/MPHIBERNATE</issueTrackingUrl>
    @@ -49,7 +48,7 @@
    <id>1.2</id>
    <name>1.2</name>
    <tag>MAVEN_HIBERNATE_1_2</tag>
    - </version>
    + </version>
    </versions>
    <developers>
    <developer>
    @@ -57,9 +56,6 @@
    <id>michal</id>
    <email>[email protected]</email>
    <organization>Dimatics</organization>
    - <roles>
    - <role>Java Developer</role>
    - </roles>
    <timezone>+1</timezone>
    </developer>
    <developer>
    @@ -67,32 +63,26 @@
    <id>epugh</id>
    <email>[email protected]</email>
    <organization>OpenSource Connections</organization>
    - <roles>
    - <role>Java Developer</role>
    - </roles>
    - </developer>
    + </developer>
    <developer>
    <name>Felipe Leme</name>
    <id>felipeal</id>
    <email>[email protected]</email>
    <organization>Falcon Informatica</organization>
    - <roles>
    - <role>Java Developer</role>
    - </roles>
    <timezone>-3</timezone>
    - </developer>
    + </developer>
    </developers>
    <contributors>
    <contributor>
    <name>Alex Shneyderman</name>
    <email>[email protected]</email>
    </contributor>
    - </contributors>
    + </contributors>
    <dependencies>
    <dependency>
    <groupId>hibernate</groupId>
    <artifactId>hibernate</artifactId>
    - <version>2.1.3</version>
    + <version>2.1.7c</version>
    <type>jar</type>
    </dependency>
    <dependency>
    @@ -179,5 +169,64 @@
    <version>1.4</version>
    <type>jar</type>
    </dependency>
    + <dependency>
    + <groupId>springframework</groupId>
    + <artifactId>spring</artifactId>
    + <version>1.1.2</version>
    + <type>jar</type>
    + </dependency>
    </dependencies>
    -</project>
    + <build>
    + <sourceDirectory>src/main</sourceDirectory>
    + <unitTestSourceDirectory>src/test</unitTestSourceDirectory>
    +
    + <unitTest>
    + <includes>
    + <include>**/*Test.java</include>
    + </includes>
    + </unitTest>
    +
    + <resources>
    + <resource>
    + <directory>..</directory>
    + <targetPath>META-INF</targetPath>
    + <includes>
    + <include>NOTICE.txt</include>
    + </includes>
    + </resource>
    + <resource>
    + <directory>src/plugin-resources</directory>
    + <targetPath>plugin-resources</targetPath>
    + </resource>
    + <resource>
    + <directory>.</directory>
    + <includes>
    + <include>plugin.jelly</include>
    + <include>plugin.properties</include>
    + <include>project.properties</include>
    + <include>project.xml</include>
    + </includes>
    + </resource>
    + </resources>
    + </build>
    +
    + <reports>
    + <report>maven-jdepend-plugin</report>
    + <report>maven-checkstyle-plugin</report>
    + <report>maven-changes-plugin</report>
    + <report>maven-changelog-plugin</report>
    + <report>maven-file-activity-plugin</report>
    + <report>maven-developer-activity-plugin</report>
    + <report>maven-javadoc-plugin</report>
    + <report>maven-jxr-plugin</report>
    + <report>maven-junit-report-plugin</report>
    + <report>maven-tasklist-plugin</report>
    + <report>maven-jellydoc-plugin</report>
    + <report>maven-pmd-plugin</report>
    + <report>maven-simian-plugin</report>
    + <report>maven-faq-plugin</report>
    + <report>maven-multiproject-plugin</report>
    + <report>maven-multichanges-plugin</report>
    + </reports>
    + </project>
    +
    Index: src/main/org/apache/maven/hibernate/beans/CommonOperationsBean.java
    ================================================== =================
    RCS file: /home/cvspublic/maven-plugins/hibernate/src/main/org/apache/maven/hibernate/beans/CommonOperationsBean.java,v
    retrieving revision 1.1
    diff -u -r1.1 CommonOperationsBean.java
    --- src/main/org/apache/maven/hibernate/beans/CommonOperationsBean.java 2 Jul 2004 07:32:53 -0000 1.1
    +++ src/main/org/apache/maven/hibernate/beans/CommonOperationsBean.java 8 Dec 2004 15:53:27 -0000
    @@ -18,15 +18,30 @@
    */

    import java.io.File;
    +import java.lang.reflect.Field;
    +import java.sql.Connection;
    +import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    +import java.util.Properties;
    import java.util.StringTokenizer;

    +import javax.sql.DataSource;
    +
    +import net.sf.hibernate.HibernateException;
    +import net.sf.hibernate.cfg.Configuration;
    +import net.sf.hibernate.cfg.Environment;
    +import net.sf.hibernate.connection.ConnectionProvider;
    +import net.sf.hibernate.util.JDBCExceptionReporter;
    +
    import org.apache.commons.lang.StringUtils;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.apache.tools.ant.DirectoryScanner;
    +import org.springframework.context.ApplicationContext;
    +import org.springframework.context.support.ClassPathXmlAp plicationContext;
    +import org.springframework.orm.hibernate.LocalSessionFact oryBean;

    /**
    *
    @@ -38,6 +53,8 @@
    private String includes = null;
    private String excludes = null;
    private String basedir = null;
    + private String springContext = null;
    + private String springBean = null;

    private static final Log LOG = LogFactory.getLog(CommonOperationsBean.class);

    @@ -70,7 +87,23 @@
    {
    this.includes = includes;
    }
    +
    + public String getSpringBean() {
    + return springBean;
    + }

    + public void setSpringBean(String springBean) {
    + this.springBean = springBean;
    + }
    +
    + public String getSpringContext() {
    + return springContext;
    + }
    +
    + public void setSpringContext(String springContext) {
    + this.springContext = springContext;
    + }
    +
    protected String[] getBaseDirNames()
    {
    LOG.debug("Bases string: " + getBasedir());
    @@ -142,7 +175,99 @@
    return (File[])files.toArray(new File[0]);
    }

    + protected Configuration getSpringConfiguration() {
    + if(getSpringContext() == null || getSpringContext().trim().length() < 1) {
    + return null;
    + }
    +
    + ApplicationContext context = new ClassPathXmlApplicationContext(org.springframework .util.StringUtils.commaDelimitedListToStringArray( getSpringContext()));
    + LocalSessionFactoryBean bean = (LocalSessionFactoryBean) context.getBean(getSpringBean());
    + Field dataSourceField;
    + DataSource dataSource;
    + Class clazz = bean.getClass();
    + try
    + {
    + dataSourceField = clazz.getDeclaredField("dataSource");
    + }
    + catch (SecurityException e)
    + {
    + throw new RuntimeException(e);
    + }
    + catch (NoSuchFieldException e)
    + {
    + throw new RuntimeException(e);
    + }
    + dataSourceField.setAccessible(true);
    + try
    + {
    + dataSource = (DataSource) dataSourceField.get(bean);
    + }
    + catch (IllegalArgumentException e)
    + {
    + throw new RuntimeException(e);
    + }
    + catch (IllegalAccessException e)
    + {
    + throw new RuntimeException(e);
    + }
    +
    + Configuration config = bean.getConfiguration();
    + if(dataSource == null)
    + {
    + LOG.warn("DataSource is null");
    + }
    + SpringConnectionProvider.setDataSource(dataSource) ;
    + config.setProperty(Environment.CONNECTION_PROVIDER , SpringConnectionProvider.class.getName());
    + return config;
    + }
    +
    + public static class SpringConnectionProvider implements ConnectionProvider {
    +
    + private static ThreadLocal configTimeDataSourceHolder = new ThreadLocal();
    +
    + public static void setDataSource(DataSource dataSource) {
    + configTimeDataSourceHolder.set(dataSource);
    + }
    +
    + public static DataSource getDataSource() {
    + return (DataSource) configTimeDataSourceHolder.get();
    + }
    +
    + private DataSource dataSource;
    +
    +
    + public void configure(Properties arg0) throws HibernateException {
    + this.dataSource = SpringConnectionProvider.getDataSource();
    + // absolutely needs thread-bound DataSource to initialize
    + if (this.dataSource == null) {
    + throw new HibernateException("No local DataSource found for configuration - " +
    + "dataSource property must be set on LocalSessionFactoryBean");
    + }
    + }

    + public Connection getConnection() throws SQLException {
    + try {
    + return this.dataSource.getConnection();
    + }
    + catch (SQLException sqle) {
    + JDBCExceptionReporter.logExceptions(sqle);
    + throw sqle;
    + }
    + }

    + public void closeConnection(Connection conn) throws SQLException {
    + try {
    + conn.close();
    + }
    + catch (SQLException sqle) {
    + JDBCExceptionReporter.logExceptions(sqle);
    + throw sqle;
    + }
    + }
    +
    + public void close() throws HibernateException {
    + }
    +
    + }

    }
    Index: src/main/org/apache/maven/hibernate/beans/SchemaBeanBase.java
    ================================================== =================
    RCS file: /home/cvspublic/maven-plugins/hibernate/src/main/org/apache/maven/hibernate/beans/SchemaBeanBase.java,v
    retrieving revision 1.1
    diff -u -r1.1 SchemaBeanBase.java
    --- src/main/org/apache/maven/hibernate/beans/SchemaBeanBase.java 6 Nov 2004 21:50:38 -0000 1.1
    +++ src/main/org/apache/maven/hibernate/beans/SchemaBeanBase.java 8 Dec 2004 15:53:27 -0000
    @@ -129,6 +129,7 @@

    Thread currentThread = Thread.currentThread();
    ClassLoader oldClassLoader = currentThread.getContextClassLoader();
    +
    try
    {
    File [] baseDirs = getBaseDirs ();
    @@ -139,9 +140,11 @@

    URLClassLoader newClassLoader =
    new URLClassLoader(urls, getClass().getClassLoader());
    +
    currentThread.setContextClassLoader(newClassLoader );

    Configuration cfg = getConfiguration();
    + LOG.debug(cfg);
    executeSchema( cfg );

    }
    @@ -161,7 +164,13 @@
    */
    private Configuration getConfiguration() throws HibernateException
    {
    - Configuration cfg = new Configuration();
    + Configuration cfg = getSpringConfiguration();
    +
    + if(cfg != null)
    + {
    + return cfg;
    + }
    + cfg = new Configuration();
    if (getConfig() != null)
    {
    File f = new File(getConfig());
    Index: src/main/org/apache/maven/hibernate/beans/SchemaExportBean.java
    ================================================== =================
    RCS file: /home/cvspublic/maven-plugins/hibernate/src/main/org/apache/maven/hibernate/beans/SchemaExportBean.java,v
    retrieving revision 1.8
    diff -u -r1.8 SchemaExportBean.java
    --- src/main/org/apache/maven/hibernate/beans/SchemaExportBean.java 6 Nov 2004 21:50:38 -0000 1.8
    +++ src/main/org/apache/maven/hibernate/beans/SchemaExportBean.java 8 Dec 2004 15:53:27 -0000
    @@ -62,7 +62,7 @@
    {
    Properties properties = new Properties();
    properties.load(new FileInputStream(getProperties()));
    - schemaExport = new SchemaExport(cfg, properties);
    + schemaExport = new SchemaExport(cfg);
    }
    LOG.debug("Output file:" + getOutputFile());
    schemaExport.setOutputFile(getOutputFile());
    Index: src/main/org/apache/maven/hibernate/jelly/SchemaExportTag.java
    ================================================== =================
    RCS file: /home/cvspublic/maven-plugins/hibernate/src/main/org/apache/maven/hibernate/jelly/SchemaExportTag.java,v
    retrieving revision 1.5
    diff -u -r1.5 SchemaExportTag.java
    --- src/main/org/apache/maven/hibernate/jelly/SchemaExportTag.java 6 Nov 2004 21:50:38 -0000 1.5
    +++ src/main/org/apache/maven/hibernate/jelly/SchemaExportTag.java 8 Dec 2004 15:53:27 -0000
    @@ -62,5 +62,13 @@
    {
    return bean.getDelimiter();
    }
    +
    + public void setSpringBean(String springBean) {
    + bean.setSpringBean(springBean);
    + }
    +
    + public void setSpringContext(String springBean) {
    + bean.setSpringContext(springBean);
    + }

    }

    Comment


    • #3
      project.xml

      Before anyone asks. The project.xml has dependencies changes + mangling/updating by mevenide eclipse plugin.

      Comment


      • #4
        It looks like I am the only one that wants to build schema files through maven using spring context files. Ths lead me to beleive there is a better way. Anyone is willing to share their process's details?

        Comment

        Working...
        X