PDA

View Full Version : Contribute to 'mappingResources' from multiple files?


jbisotti
Aug 5th, 2005, 02:41 PM
We have a core piece of software, and then several components that can be bolted onto it. Currently, the core and each component each have their own applicaitonContext.xml. Currently, the applicationContext.xml of the core piece declares the Hibernate "sessionFactory" mapping along with its "mappingResources" list. However, each component also has *.hbm.xml mappings to contribute to the application. Can I declare another "sessionFactory" in each component applicationContext.xml and only list its *.hbm.xml entries? Will Spring merge it all together? Or, is there some other way of doing this? Or, do I just have to add the entries to the core applicationContext.xml manually?

Thanks!

Colin Yates
Aug 8th, 2005, 05:27 AM
Is each component stand alone, or can they only ever be run in another package?

If they can only be run in another package, then I wouldn't let each one contain an applicationContext.xml. Rather, I would create a "purposeOfComponent-context.xml", and then in your main package have an applicationContext.xml that includes all the component specific context.xml. That seems to be a better architectual fit, and also will prevent the inevitable name clashes ;)

I know spring is quite happy loading files from classpath, and I am pretty sure (99%) that the sessionFactory will to. Bear in mind that Spring has a Resource, which can be a file, classpath, url??? etc.

HTH, sorry I cannot answer your question directly ;)

jbisotti
Aug 10th, 2005, 08:04 AM
The two pieces of code are "framework" and "componentA"; "componentA" can only ever run with "framework". However, "componentA" is optional so it will not always be there; thus, the applicationContext.xml of "framework" cannot just include "purposeOfComponent-context.xml".

Basically, my framework/applicationContext.xml looks like this:
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFact oryBean"
>
<property name="dataSource">
<ref local="dataSource" />
</property>

<property name="mappingResources">
<list>
<value>com/foo/bar/Blah1.hbm.xml</value>
<value>com/foo/bar/Blah2.hbm.xml</value>
<value>com/foo/bar/Blah3.hbm.xml</value>
...
</list>
</property>

<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
${hibernate.dialect}
</prop>

<prop key="hibernate.hbm2ddl.auto">
${hibernate.hbm2ddl.auto}
</prop>
</props>
</property>

</bean>


Will having my componentA/applicationContext-compA.xml looking like this work?:
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFact oryBean"
>
<property name="mappingResources">
<list>
<value>com/foo/bar/Blah4hbm.xml</value>
<value>com/foo/bar/Blah5.hbm.xml</value>
<value>com/foo/bar/Blah6.hbm.xml</value>
...
</list>
</property>
</bean>

If not, how can I contribute to the List of "mappingResources" dynamically (i.e. outside the main applicationContext.xml)?

Thanks,
Jamie

Colin Yates
Aug 10th, 2005, 09:00 AM
If componentA can never run standalone, I would suggest it shouldn't have it's own sessionFactory.

Hmm, I still think *conceptually* the main applicationContext importing the componentA-context.xml would be the best solution ;)

Looking at LocalSessionFactoryBean, you can specify multiple jars which contain the hbm.xml, so you would add a componentA.hbm.jar etc.

jbisotti
Aug 10th, 2005, 10:41 AM
> If componentA can never run standalone, I would suggest it shouldn't have it's own sessionFactory.

I agree completely. I do not want it to have it's own sessionFactory; I want it to append its *.htm.xml entries to the "mappingResources" List of the sessionFactory defined in framework/applicationContext.xml. The point of this topic is trying to find out how to go about doing that.

> Hmm, I still think *conceptually* the main applicationContext importing the componentA-context.xml would be the best solution

Fine, but what would componentA-context.xml look like? I know what the bean definitions would look like; again, it's the "mappingResource" that I am questioning.

>Looking at LocalSessionFactoryBean, you can specify multiple jars which contain the hbm.xml, so you would add a componentA.hbm.jar etc.

It's not a problem of JARs or *.htm.xml files...it's strictly an issue with defining the *.hbm.xml entries under "mappingResources". Framework has it's own *.hbm.xml files and those are defined in it's applicationContext.xml as one would expect. No problem there. Now, the deployment contains componentA too. Getting the appropriate JARs/*.hbm.xml files is no problem. The problem is providing Spring with the mapping of those componentA *.hbm.xml files. I'd rather not have to manually (or have the installer) edit framework/applicationContext.xml to add those entries, if componentA is present. I'm hoping to find a means whereby some sort of componentA XML file can just contribute its entries to those already defined framework entires.

Is this making any sense???

Jamie

s100w
Aug 10th, 2005, 11:59 AM
I can't see a way to do what you want by importing multiple application content XML files. Have you considered a custom implementation of LocalSessionFactoryBean? You could implement a more complex strategy for finding Hibernate mappings: list all possible files and silently ignoring missing ones, or look in the classpath for *.hmb.xml, or read a property file ....

Another thought (that I haven't validated with code): could you pass in a custom POJO as an argument to LocalSessionFactoryBean.setMappingResources()? That could implement your "mapping finding" strategy. Along the lines of:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFac toryBean">
<property name="mappingResources">
<list>
<ref local="myCustomMappingsFinder" />
</list>
</property>

BTW, you can programatically configure your Hibernate SessionFactory as well:
http://www.hibernate.org/hib_docs/v3/reference/en/html/session-configuration.html#configuration-programmatic

katentim
Aug 11th, 2005, 06:07 AM
I do not want it to have it's own sessionFactory; I want it to append its *.htm.xml entries to the "mappingResources" List of the sessionFactory defined in framework/applicationContext.xml. The point of this topic is trying to find out how to go about doing that.
I think the other posters have covered this, but it looks like your session factory should be defined in the core, but instead of using mappingResources, use mappingLocations with the classpath prefix. See below:
<property name="mappingLocations"><value>classpath*:com/foo/bar/*.hbm.xml</value></property>

When you add other JARs to the classpath, the mapping files will be loaded (in the example above according to the packe structure com.foo.bar you specified earlier).

Fine, but what would componentA-context.xml look like? I know what the bean definitions would look like; again, it's the "mappingResource" that I am questioning.
componentA-context.xml won't need any mappingResource or sessionFactory definition. They will be picked up by the core.

Colin Yates
Aug 11th, 2005, 08:09 AM
katentim; you are the man :) (unless you are female, in which case you are the female ;))

Didn't know resources could do that ;)

heymjo
Sep 5th, 2006, 03:23 AM
for reference, the <property name="mappingLocations" value="classpath*:**/*.hbm.xml" /> syntax seems troublesome under weblogic 81sp5 with the application deployed as an EAR. By troublesome i mean that it works on my local instance (winxp) but when i move the same EAR to the managed server instance it fails. In both cases i deployed the same packaged EAR.

Caro_Systems_Inc
Nov 29th, 2006, 11:27 AM
This is now possible using Spring framework ver 2 with Hibernate ver 3.2.0.cr2

As an example in a "fw-application-context-hibernate.xml"
the following beans could be defined.

------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">


<util:list id="frameWorkMappingResources">
<value>com/company/components/component/persistence/dao/hibernate/Address.hbm.xml</value>
<value>com/company/components/component/persistence/dao/hibernate/Party.hbm.xml</value>
</util:list>

<bean id="mappingResources" class="org.springframework.beans.factory.config.ListFacto ryBean" parent="frameWorkMappingResources">
<property name="sourceList">
<list merge="true">

</list>
</property>
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFac toryBean">
<property name="mappingResources">
<ref bean="mappingResources" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.Oracle9Dialect
</prop>

...etc ...

</props>
</property>
</bean>
</beans>
------------------------------------------------------------------------
Now in a core project that uses the framework project...
As an example in a "proj001-application-context-hibernate.xml" the following beans could be defined.


<bean id="proj001MappingResources" class="org.springframework.beans.factory.config.ListFacto ryBean" parent="frameWorkMappingResources">
<property name="sourceList">
<list merge="true">
<value>com/company/project/components/component/persistence/dao/hibernate/Demo.hbm.xml</value>
<value>com/company/project/components/component/persistence/dao/hibernate/Comment.hbm.xml</value>
</list>
</property>
</bean>

<bean id="mappingResources" class="org.springframework.beans.factory.config.ListFacto ryBean" parent="proj001MappingResources">
<property name="sourceList">
<list merge="true">

</list>
</property>
</bean>

------------------------------------------------------------------------

Furthermore, we recently came across the issue where we needed to redefine a object mapped in the framework to be more complex to use in the core.

Let say - Party had simple fields in the framework it now requires relationships to other objects found in the core...for example Comment.

You could define the exact same package structure in your core project as the framework and Overload the object found in the framework.
You also need to overload the framework defined hbm.xml file with the changes to define the relationship in the core project.

As an example:
You want to have a relationship between Party and Comment

You have two Party Objects defined - 1 under each project.. found in the same package structure.
The one in the Framework is the simple definition and the one under core is more complex.

You also have two Party.hbm.xml files - 1 under each project.. found in the same package structure.
The one in the Framework is the simple definition and the one under Core is more complex defining the Comment relationship.

Our framework can be a stand alone project and can also be used in other projects.
We didn't want to change the framework just to appease 1 subprojects requirements.

This was our simple solution to the problem .. if you have another possible solution .. I'd love to hear it.

baroncelli
Dec 9th, 2006, 12:09 PM
This is now possible using Spring framework ver 2 with Hibernate ver 3.2.0.cr2


Wow, thank you, this has been bugging me for quite some time and your solution seems exactly what I felt the need for. Just one question: why are you explicitly referring to hibernate 3.2? Is there something I can't see in your solution that wouldn't work with, for example, hibernate 2?

Thanks,
Davide.

karldmoore
Dec 9th, 2006, 03:39 PM
I don't see why it wouldn't work with Hibernate 2.0, you'd just need to use the applicable version of the LocalSessionFactoryBean.

Caro_Systems_Inc
Dec 12th, 2006, 10:52 AM
Right, I didn't mean to imply it would not work with another version.

I am fairly new to Spring/Hibernate and my working knowledge of past release capabilities of both products is limited. I do know the above works with the configuration I mentioned.
Without researching, I thought spring 2 was where the merge property was introduced on the list element and that Spring 2 was not used with previous versions of hibernate.
If I was wrong with those assumptions, then by all means, this should work with earlier versions of hibernate.

I am glad you found the solution useful though! Thanks.