Announcement Announcement Module
Collapse
No announcement yet.
sessionFactory with dynamically constructed list of mapping files Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • sessionFactory with dynamically constructed list of mapping files

    Hi all, there's my problem: I need to build different applications that configures a sessionFactory (defined in a base jar) dynamically with the mappings stored in different bean definition files found in the classpath.
    The idea behind would be construct domain models based in smaller domain models, and provide different combinations of small domain models that would be defining different big domain models.

    The scenario

    applicationContex.xml lives in base.jar and defines Hibernate sessionFactory bean

    applicationContext-a.xml lives in a.jar and have a list of hbm.xml files that defines a domain model called dma
    applicationContext-b.xml lives in b.jar and have a list of hbm.xml files that defines ANOTHER domain model called dmb

    Requirement
    Be capable of build different applications:

    1. application appa that manages the dma domain model, built from base.jar and a.jar
    2. application appb that manages the dmb domain model, built from base.jar and b.jar
    3. (THE INTERESTING PART) application appab that manages a domain model that is the combination of dma and dmb, built from base.jar, a.jar, and b.jar.

    Maybe a solution could be define a bean in a.jar, b.jar...x.jar that connects to the sessionFactory configuration (before the sessionFactory has being built, of course)?

    I appreciate your help. Thank you very much for reading!
    Emystein

  • #2
    A possible solution

    I used the following approach: create a subclass of LocalSessionFactoryBean called PackageLocalSessionFactoryBean and override postProcessConfiguration(Configuration) to search for .hbm.xml files stored in configured packages. The list of packages is a member of PackageLocalSessionFactoryBean called mappingPackages and is injected in the configuration of the sessionFactory bean.
    With this approach, any jar in the classpath that contains a .hbm.xml file in certain packages will add the .hbm.xml file to the configuration of the sessionFactory.

    In my case, I use a default package for mappings called com.mycompany.model.mapping

    The sessionFactory bean configuration:

    Code:
    	<bean id="sessionFactory"
    		class="com.mycompany.extension.spring.orm.hibernate3.PackageLocalSessionFactoryBean">
    		<property name="dataSource" ref="dataSource"/>
    		
    		<property name="hibernateProperties">
    			<props> 
    				<!-- properties of the hibernate configuration -->
    				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                    <prop key="hibernate.show_sql">${db.showSQL}</prop>
    			</props>
    		</property>
    		
    		<property name="mappingPackages">
    			<list>
    				<value>com.mycompany.model.mapping</value>
    			</list>
    		</property>
    	</bean>
    And the source code:

    Code:
    public class PackageLocalSessionFactoryBean extends LocalSessionFactoryBean {
    
    	private static final Log log = LogFactory.getLog(PackageLocalSessionFactoryBean.class);
    
    	private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
    
    	private String[] mappingPackages;
    
    	/*
    	 * (non-Javadoc)
    	 * 
    	 * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#postProcessConfiguration(org.hibernate.cfg.Configuration)
    	 */
    	@Override
    	protected void postProcessConfiguration(org.hibernate.cfg.Configuration config) throws HibernateException {
    
    		if (this.mappingPackages != null) {
    			
    			for (int i = 0; i < this.mappingPackages.length; i++) {
    				String packageName = this.mappingPackages[i];
    	
    				log.debug("Searching for Hibernate hbm.xml files in package: " + packageName);
    	
    				// Obtener todos los archivos hbm.xml encontrados en el paquete
    				try {
    					Collection<String> mappingFiles = ClassLoaderUtils.getResourcesFromPackage(packageName, ".hbm.xml");
    	
    					for (String mappingFileName : mappingFiles) {
    	
    						log.debug("Mapping file: " + mappingFileName);
    						
    						try {
    							
    							Resource resource = new ClassPathResource(mappingFileName, this.beanClassLoader);
    							config.addInputStream(resource.getInputStream());
    							
    						} catch (DuplicateMappingException dme) {
    							log.warn("Mapping file "+ mappingFileName +" was already mapped.");
    						} catch (IOException ioe) {
    							throw new HibernateException("Can't get input stream from mapping file: "+ mappingFileName, ioe);
    						}
    	
    						log.debug("Added mapping file to Session configuration");
    					}
    				} catch (IOException ioe) {
    					throw new HibernateException("Can't obtain file names from package: " + packageName, ioe);
    				}
    			}
    		}
    
    	}
    
    	/**
    	 * Set package names to be found in the class path, where the class will look for Hibernate mapping resources with
    	 * extension .hbm.xml.
    	 */
    	public void setMappingPackages(String[] mappingPackages) {
    		this.mappingPackages = mappingPackages;
    	}
    Hope this will be useful.
    Cheers!

    Comment


    • #3
      If you use ClassPathScanningCandidateComponentProvider you will simplify your code.

      Comment

      Working...
      X