Specify a regular expression for LocalSessionFactoryBean mappingLocations - java

In my application, I have specified the below configuration for automatically picking up all the HBM files under a specific folder in the classpath.
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="mappingLocations">
<list>
<value>classpath:hbms/**/*.hbm.xml</value>
</list>
</property>
</bean>
Now, for a new requirement, there is a need to create multiple HBM files with named queries specific to database. The HBM file names will be of the pattern test.DB.hbm.xml. For example, test.oracle.hbm.xml and test.db2.hbm.xml. In addition to these, there are the old regular HBM files (for mapping to tables) with name format as table1.hbm.xml, table2.hbm.xml, etc. also present in the same folder.
Using the above pattern, hibernate loading of the files fails, due to duplicate named queries in the new hbm files (since the name would be same in all such files).
The requirement is now to load the regular HBM files and also the DB specific HBM files. Is it possible to achieve this by using a regular expression as below?
classpath:hbms/**/*.(.${dbType}).hbm.xml
In the above example, dbType is available as a Spring environment property. My attempt with these changes resulted in none of the HBM files being loaded (including the old ones).
Am I doing something wrong with the regular expression or is it not possible to do this via XML configuration?
Thank you.

You have two options:
You can have each database specific config files be stored in a separate folder and then your config looks like this:
classpath:hbms/**/${dbType}/*.hbm.xml
You can have them follow he pattern you provided, but change the configuration to
classpath:hbms/**/*${dbType}.hbm.xml
To load common files, you need to rename them to include something you can match, like:
one.hbm.xml
becoming:
common-one.hbm.xml
Then the configuration might look like this:
classpath:hbms/**/common-*.hbm.xml
classpath:hbms/**/*${dbType}.hbm.xml

Related

How to add external properties file to classpath in jboss 4.2

I want to read an external properties file when launching Jboss 4.2 . I want to add it to the classpath to read it from a WAR file . I have seen different solutions with Jboss 6 using modules, but I haven't seen anything related to JBoss 4.2.
I have included inside 'jboss-service.xml' the following code :
<!-- Bean for reading properties -->
<mbean code="org.jboss.varia.property.SystemPropertiesService"
name="jboss.util:type=Service,name=SystemProperties">
<!-- Load properties from each of the given comma separated URLs -->
<attribute name="URLList">
./conf/path.tmview.properties
</attribute>
</mbean>
In this file I have defined the property :
property-placeholder filepath=/var/tmview_props/tmview/tmview.properties
This property is used in the following bean definition
<bean id="tmviewConfigurerLocation" class="org.springframework.core.io.FileSystemResource">
<constructor-arg value="${property-placeholder-filepath}" />
</bean>
inside an applicationContext.xml . When I launch jboss, the file of properties is read
15:45:29,939 INFO [SystemPropertiesService] Loaded system properties
from: file:/D:/devel/projects/tmview/deployment/jboss-
...ver/tmview/conf/path.tmview.properties
So, the property is read, but I kept obtaining the following exception
2015-03-24 15:45:39,219 ERROR
[org.springframework.web.context.ContextLoader] Context
initialization failed
org.springframework.beans.factory.BeanInitializationException: Could
not load properties; nested exception is
java.io.FileNotFoundException: ${property-placeholder-filepath} (The
system cannot find the file specified)
at
org.springframework.beans.factory.config.PropertyResourceConfigurer.
postProcessBeanFactory(PropertyResourceConfigurer.java:78)
Is there any special way to read the property inside the spring bean ?
In jboss 4 you was able to drop property files in the <jboss_home>/server/<instance>/conf directory and they would be available from the classpath.
Another possibility is add your custom directory to the classpath, to do this see Adding second conf folder to JBoss 5.1.0
Ok . At the end , I solved the problem . It seems the problem was located in reading from application-context.xml .
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>file:${tmview.conf.variables}</value>
</property>
</bean>
I had to add a property placeholder reader . Regarding to jboss, you can read the parameter file either from conf/jboss-service.xml or deploy/properties-receive.xml, but it seems more appropiate to do the reading from the second one .

Hibernate 3.2.5 with Play Framework 1.2.5

I am trying to use Hibernate 3.2.5 with Play framework 1.2.5
In Hibernate I am having two files:
1) cfg.xml file (containing the db config details along with some additional properties
2) hbm.xml file (containing the mapping between the java bean and the db table
For getting connected to the oracle 10g db, I am providing the db details in the application.config files like this and the connection is successful also when I start the server:
db.url=jdbc:oracle:thin:#localhost:1521/orcl
db.driver=oracle.jdbc.OracleDriver
db.user=system
db.pass=tiger
I want to know Where will I place the hbm.xml file (for mapping details) and the cfg.xml file for the remaining properties other than db connecion details?
Please let me know about this.
Regards,
Starting from the root directory of your application:
the hibernate.cfg.xml must be placed inside the app directory
the mapping files (the hbm files) where your models classes are defined, usually inside the app/models/ directory
Inside your hibernate.cfg.xml the mapping attributes should be something like:
<mapping class="models.yourHmbFile1"/>
<mapping class="models.yourHmbFile2"/>
Btw, I find easy to use the hibernate annotations instead of the hbm - xml mapping. Easier to write and to mantain.
If you prefer to annotate your model classes, you can delete the hbm files and directly map your annotated classes in your hibernate.cfg.xml.
In the application.conf you've to specify the data you have already added:
db.url=jdbc:oracle:thin:#localhost:1521/orcl
db.driver=oracle.jdbc.OracleDriver
db.user=system
db.pass=tiger
Also in the hibernate.cfg.xml you need to specify the connection data:
<property name="hibernate.dialect">...</property>
<property name="hibernate.connection.driver_class">...</property>
<property name="hibernate.connection.url">...</property>
<property name="hibernate.connection.username">...</property>
<property name="hibernate.connection.password">...</property>

Dynamic Change of files directory for jdbc.properties and log4j.properties

I'm working in a Java Web Project.
I need to change the folder of the files "jdbc.properties" and "log4j.properties" depending of the environment, because testing, demo and release have diferent values for those files.
I have this folders and subfolders:
c:\myProject\conf\dev
c:\myProject\conf\test
c:\myProject\conf\demo
I need to put diferent jdbc.properties and log4j.properties files in each of those folders
c:\myProject\conf\dev\log4j.properties
c:\myProject\conf\dev\jdbc.properties
c:\myProject\conf\test\log4j.properties
c:\myProject\conf\test\jdbc.properties
c:\myProject\conf\demo\log4j.properties
c:\myProject\conf\demo\jdbc.properties
The three project are in the same Server and in the same Apache (It is a Web Project)
First i made some changes to use a windows system variable to get the parent folder (c:\myProject). To do that, i made this on Spring appContext file:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>file:${PARENT_FOLDER}/conf/dev/jdbc.properties</value>
</property>
</bean>
"PARENT_FOLDER" is defined on Windows environment variables/system variable
Those changes works OK.
But, as you can see, I always loking for file on "/conf/dev"
I need to make dynamic the "dev" part of the path.
I Can't use Windows environment variables/system variable because the 3 environments are deployed on the same Server.
I'm trying to use a "property" (using ) on web.xml, but I don't know how to find the property in my Spring appContext file.
I definy the property like this:
<env-entry>
<env-entry-name>ENVIRONMENT</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>Dev</env-entry-value>
</env-entry>
But I don't know how to access "ENVIRONMENT" property on Spring
I don't know what to do. I a little desperate
Can someone help me?
Thanks and sorry for my poor english
Have you considered using JNDI?
With JNDI you will define the db connection properties inside tomcat itself. This way your spring configuration is independent of the environment and you can deploy the same war on all environments. See also this.
If you need to run it locally that you can always use the 'new' spring environment profiles feature.
Other option (if JNDI is not an option and assuming you use maven) is the maven replacer plugin where you will generate the db.properties at build time.

Can I Specify hibernate annotated classes in hibernate.properties?

Most or all the core hibernate configuration properties can be specified in a startup properties file, as an alternative to specifying mappings in hibernate.cfg.xml.
Is there an easy way to specify mappings of annotated classes in a properties file?
You can map annotated classes like this in the hibernate.cfg.xml configuration:
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
...
<mapping class="com.annotated.classes.EntityOne"/>
</session-factory>
Similar configuration can be written using a properties file i.e. hibernate.properties
hibernate.connection.driver_class = com.mysql.jdbc.Driver
hibernate.mapping = ???
What I haven't figured out is how to specify the mapping of annotated classes (entities) using the properties configuration, if this is possible.
I don't think there is any way to specify entities in the properties file.
I suppose you could create your own custom initialization code using Configuration to accomplish what you are looking for. The problem with using a properties file, though, is that you cannot specify a property with a list of values unless you identify a way to split the value into a list. You would then need to write code that parses the value accordingly.

Elegant ways to separate configuration from WAR in Tomcat

I am trying to find the best way to pass complex configurations in a Spring webapp running in Tomcat. Currently I use JNDI to pass data sources and strings from the Tomcat context into the webapp, and this works well.
But, lets say I need to select the implementation of a notification service. There is no way that Spring can conditionally select which bean to instantiate (although in the past I have used a JNDI string to import a predefined configuration of beans by setting contextConfigLocation).
I've also seen many webapps which supply a configuration tool which will create a custom WAR file. In my opinion this is bad form, if for no other reason than it prevents the redeployment of WARs from upstream without many checks to ensure all the configuration has been re-applied.
Ideally I would be able to supply a Spring XML file which existed on the filesystem, outside of the webapp. But, the spring import directive does not seem to resolve ${} variables, making it impossible to supply customisations.
Are there any techniques I can employ here to properly separate complex configuration from the webapp?
If I have a specific set of beans that I'd like to configure, and this configuration must be separated from the WAR file, I usually do the following:
In applicationContext.xml:
<!-- here you have a configurer based on a *.properties file -->
<bean id="configurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="file://${configDir}/configuration.properties"/>
<property name="ignoreResourceNotFound" value="false" />
<property name="ignoreUnresolvablePlaceholders" value="false" />
<property name="searchSystemEnvironment" value="false" />
</bean>
<!-- this is how you can use configuration properties -->
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="${smtp.host}"/>
</bean>
In configuration.properties:
smtp.host=smtp.your-isp.com
You also need to start Tomcat with -DconfigDir=/path/to/configuration/directory
If you are using Spring 3, you can take advantage of the Spring Expression Language. Let's say you have two applications app1.war and app2.war and they require a properties file named config.properties. The applications will be deployed with context paths /app1 and /app2.
Create two directories app1 and app2 in a common directory, eg. C:\myConfig\app1 and C:\myConfig\app2.
Put config.properties inside app1 and another config.properties inside app2.
Then create a file ${CATALINA_HOME}/conf/[enginename]/[hostname]/context.xml.default with the contents:
context.xml.default:
<Context>
<Parameter name="myConfigDirectory" value="C:/myConfig" override="false"/>
</Context>
The parameter myConfigDirectory will be available to all the applications on the host. It is better to create this parameter in context.xml.default rather than in server.xml, because the file can be changed later without restarting tomcat.
In the applicationContext.xml inside war you can access config.properties using the SpEL expression: "#{contextParameters.myConfigDirectory + servletContext.contextPath}/config.properties", so for example you can write:
applicationContext.xml:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="file:#{contextParameters.myConfigDirectory + servletContext.contextPath}/config.properties" />
</bean>
The expression will get expanded to C:/myConfig/app1 for application with contextPath /app1, and C:/myConfig/app2 for application with contextPath /app2. This will make the applications access the config.properties file based on their contextPath.
If you want to be fully portable between web containers you cannot rely on anything outside your WAR-file. In Tomcat the SecurityManager allows you to discover the physical location on disk where your code is deployed, and you can then use that knowledge to navigate the disk to a location where your configuration file is placed.
See e.g. Determine location of a java class loaded by Matlab

Categories