I'm looking the way how to control java properties during installation procedure.
I'm have Spring Data JPA + Hibernate in my application. I've configured jpa properties in bean. And move it to property file.
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml"></property>
<property name="persistenceUnitName" value="hibernatePersistenceUnit"/>
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.hbm2ddl.auto" value="${hibernate.hbm2ddl}"/>
<entry key="hibernate.show_sql" value="${hibernate.show.sql}" />
<entry key="hibernate.dialect" value="${hibernate.dialect}" />
</map>
</property>
</bean>
property file: prop-local-override.properties where local is environment variable.
hibernate.hbm2ddl=update
#hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.show.sql=true
So, everything works fine. But I want to change hibernate.hbm2ddl during installation process. I use rpm package for installation my app. For example, I want to set this property to "create" when app is installing. And return to update after each restart.
Looks like -Dhibernate.hbm2ddl=update works fine. But it's manual work. Does anyone has some idea how to make it automatically, without big tools like Puppet?
Thanks,
Sergii K.
Never tried changing this dynamically before, but you can access that property map from your entity manager:
entityManager.getEntityManagerFactory().getProperties()
Related
I asked a similar question, but based on the responses, I did a bad job describing what I am after. I have a spring 4 webapp that loads properties from a properties file. We consume those properties both via the "${proper.name"} expressions in spring, as well as by injecting a properties object into some of our classes.
We want to move most of the properties to a database table and make them reloadable. However, a few need to stay in local properties, potentially overriding the database setting. These should also be loaded dynamically after the app is running.
I know that once a particular bean is injected, it won't get reloaded, that doesn't concern me, it's up to that module to handle that. But I am having trouble getting the behavior I want. In particular, I have implemented an AbstractConfiguration from apache commons configuration to get the dual source and overriding I am after. But while it works for injecting the properties object, expressions loaded with "${prop.name}" don't work at all.
How can I get them to work? Did I override the wrong thing? Is it just some config detail?
<bean id="sysProperties" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="databaseConfigurator" />
<property name="targetMethod" value="getProperties"/>
</bean>
<bean id="databaseConfigurator" class="my.util.config.MyDatabaseConfigurator">
<property name="datasource" ref="dataSource" />
<property name="propertyFile" value="/WEB-INF/my.properties" />
<property name="applicationName" value="ThisApp" />
</bean>
<bean id="dbConfigFactory" class="org.apache.commons.configuration.ConfigurationConverter" factory-method="getProperties">
<constructor-arg ref="databaseConfigurator" />
</bean>
I haven't tested this, but I think it might work.
<bean id="sysProperties" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="databaseConfigurator" />
<property name="targetMethod" value="getProperties"/>
</bean>
<bean id="databaseConfigurator" class="my.util.config.MyDatabaseConfigurator">
<property name="datasource" ref="dataSource" />
<property name="propertyFile" value="/WEB-INF/my.properties" />
<property name="applicationName" value="ThisApp" />
</bean>
<bean name="PropertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="CommonsConfigurationFactoryBean"/>
</bean>
<bean name="CommonsConfigurationFactoryBean" class="org.springmodules.commons.configuration.CommonsConfigurationFactoryBean">
<constructor-arg ref="databaseConfigurator"/>
</bean>
In a Java app which uses Spring (Spring version 3.2.3),
I have something like this:
<bean id="pm" class="com.test.PropertyManager">
<property name="targets">
<map>
<entry key="key01" value-ref="obj01" />
<entry key="key02" value-ref="obj02" />
<entry key="key03" value-ref="obj03" />
<entry key="key04" value-ref="obj04" />
<entry key="key05" value-ref="obj05" />
<entry key="key06" value-ref="obj06" />
</map>
</property>
</bean>
Is there any way to tell Spring to not put all entries in this map
but only some of them based on some property whose value can be
different for different environments the app is built for, and running in.
I mean, I am looking for something like:
<bean id="pm" class="com.test.PropertyManager">
<property name="targets">
<map>
<entry key="key01" value-ref="obj01" if="${env1}"/>
<entry key="key02" value-ref="obj02" if="${env1}"/>
<entry key="key03" value-ref="obj03" unless="${env1}"/>
<entry key="key04" value-ref="obj04" unless="${env1}"/>
<entry key="key05" value-ref="obj05" />
<entry key="key06" value-ref="obj06" />
</map>
</property>
</bean>
So e.g. I want two entries to be added when the app is in environment env1, two other entries to be added when the app is running in another env2, and yet two others to be always added.
Is that possible and if not, what are my alternatives?
There are different options:
If you need a different bean configuration per environment you could use profiles:
<beans profile="dev">
<bean id="pm" class="com.test.PropertyManager">
<property name="targets">
...
</property>
</bean>
</beans>
<beans profile="production">
<bean id="pm" class="com.test.PropertyManager">
<property name="targets">
...
</property>
</bean>
</beans>
More on XML profiles: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-definition-profiles-xml
If you need more flexibility use a factory (with Java config, that's straightforward):
public class PropertyManagerFactory {
public static PropertyManager getInstance() {
// Your initialization code (check env vars to build the map...)
}
}
Bean definition (notice the factory-method):
<bean id="propertyManager" class="com.test.PropertyManagerFactory" factory-method="getInstance" />
Usage (what's returned by the getInstance method will be injected here):
<bean id="accountService" class="com.test.AccountServiceImpl">
<property name="propertyManager" ref="propertyManager"/>
</bean>
More info on using factory methods: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-factory-class-static-factory-method
As far as I tried, I have to manually change the CRON_TRIGGERS table in DB. Dirty...
Any way to make more like this?:
There are 2 apps running, both have in .properties file schedule defined as "every minute" and so works the job
I stop one instance and reconfigure (change in .properties file), so the schedule is "every hour"
I start the instance. Now I would like that instace to check, that such job is already defined in DB and to update the schedule there. It is not happening now using configuration from site http://www.objectpartners.com/2013/07/09/configuring-quartz-2-with-spring-in-clustered-mode/
Or what is the typical solution?
So I guess that when you say .properties file, you actually mean the spring bean XML file(s).
It does not make any sense that you statically configure identical jobs with different schedules. If for whatever reason, one instance restarts, it will automatically apply its own schedule. If statically configured, your job triggers should be the same on all instances
If you properly set <property name="overwriteExistingJobs" value="true"/> in your SchedulerFactoryBean it should automatically updates the schedule of the job.
You should never modify the database manually. Always update the scheduler through its API.
Try sth like this:
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobDetails">
<list>
<ref bean="yourJobDetail" />
</list>
</property>
<property name="triggers">
<list>
<ref bean="yourJobTrigger" />
</list>
</property>
<property name="configLocation" value="file:${HOME}/yourProperties.properties" />
<!-- Commented, because don't work with autocommit = false on spring data source -->
<!-- <property name="dataSource" ref="mainDataSource"/> -->
<property name="transactionManager" ref="mainTransactionManager" />
<property name="autoStartup" value="true" />
<property name="applicationContextSchedulerContextKey" value="applicationContext" />
<property name="jobFactory">
<bean class="FactoryForJobWithInjectionOfSpringBbean" />
</property>
<!-- Will update database cron triggers to what is in this jobs file on each deploy. Replaces all previous trigger and job data that
was in the database. YMMV -->
<!-- dont work properly with cluster -->
<!-- <property name="overwriteExistingJobs" value="true" /> -->
</bean>
Unfortunately i think that:
<property name="overwriteExistingJobs" value="true" />
dosen't work correctly in cluster mode.
Has anyone been able to get the EclipseLink JPA povider working in WAS Liberty Profile with Container Managed Transactions? I have configured my server.xml file with the JPA Container setting to override the default OpenJPA implementations however this causes a side effect where by the EntityManager no longer participates in a Container transaction when accessed through an EJB that has a transaction propagation annotation.
I also tried setting the "eclipselink.target-server" property to "WebSpeher_7" however when I do this I get a ClassNotFoundException on the com.ibm.ws.Transaction.TransactionManagerFactory class.
Good afternoon. This looks like you're hitting Bug 407279 (https://bugs.eclipse.org/bugs/show_bug.cgi?id=407279).
You can work around this issue by modifying org.eclipse.persistence.transaction.was.WebSphereTransactionController with the following change:
public class WebSphereTransactionController extends JTATransactionController {
// Class and method to execute to obtain the TransactionManager
protected final static String TX_MANAGER_FACTORY_CLASS = "com.ibm.tx.jta.TransactionManagerFactory";
// OLD VALUE --> "com.ibm.ws.Transaction.TransactionManagerFactory";
Hope this helps! Be sure to grab EclipseLink 2.5.2 as that has another important change (Bug 412627) in order to work with Liberty!
I had to change many things with liberty 16.0.0.2, Spring 4.X and EclipseLink 5.2.X
I removed the persistence.xml file
and changed the spring xml configuration to:
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="datasource" />
<property name="persistenceUnitName" value="PERSISTENCE_UNIT"></property>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="packagesToScan">
<list>
<value>ENTITIES_PACKAGE</value>
</list>
</property>
<property name="jpaPropertyMap">
<map>
<entry key="eclipselink.weaving" value="false"/>
</map>
</property>
</bean>
And for server.xml
<jpa defaultPersistenceProvider="org.eclipse.persistence.jpa.PersistenceProvider"/>
<featureManager>
<feature>servlet-3.0</feature>
<feature>jdbc-4.0</feature>
<feature>jpa-2.0</feature>
<feature>localConnector-1.0</feature>
<feature>jsp-2.2</feature>
</featureManager>
I want to use Spring Data JPA with Hibernate mapping files and without JPA-Annotations.
But I'am facing this exception on server startup (tomcat):
java.lang.IllegalStateException: No persistence units parsed from {classpath*:META-INF/persistence.xml}
at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.obtainDefaultPersistenceUnitInfo(DefaultPersistenceUnitManager.java:547)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.determinePersistenceUnitInfo(LocalContainerEntityManagerFactoryBean.java:311)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:260)
My dispatch-servlet.xml looks like the following:
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<!--<property name="persistenceUnitName" value="BLUPP" />-->
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" />
<!-- <property name="packagesToScan" value="org.cleanyourway.server.beans" />-->
<property name="persistenceUnitPostProcessors">
<list>
<bean
class="org.springframework.data.jpa.support.ClasspathScanningPersistenceUnitPostProcessor">
<constructor-arg value="org.xxxxxx.server.beans" />
<property name="mappingFileNamePattern" value="**hbm.xml" />
</bean>
</list>
</property>
</bean>
Is it possible to use Hibernate mapping files with the ClasspathScanningPersistenceUnitPostProcessor?
I get it running with
<property name="packagesToScan" value="org.xxxxxxx.server.beans" />
and JPA Annotations.
Thanks for your help!
Briefly
Your problem probably comes from the mappingFileNamePattern you provide. Try **/*.hbm.xml instead of **hbm.xml.
Complete snippet:
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<!--<property name="persistenceUnitName" value="BLUPP" />-->
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" />
<!-- <property name="packagesToScan" value="org.cleanyourway.server.beans" />-->
<property name="persistenceUnitPostProcessors">
<list>
<bean
class="org.springframework.data.jpa.support.ClasspathScanningPersistenceUnitPostProcessor">
<constructor-arg name="basePackage" value="org.xxxxxx.server.beans" />
<property name="mappingFileNamePattern" value="**/*hbm.xml" />
</bean>
</list>
</property>
</bean>
In details
Ant path patterns
Spring uses Ant path style patterns. You can find a good documentation on those patterns on the Ant Website. Double asterisk wildcard means: recurse in subdirectories. It should be followed by a slash as it stands for a directory.
ClasspathScanningPersistenceUnitPostProcessor
The mapping file detection part of ClasspathScanningPersistenceUnitPostProcessor takes the two parameters (basePackage (your constructors args) and mappingFileNamePattern) into account. With the suggested correction, Spring will search all **.hbm.xml* in subfolders org/xxxxxx/server/beans/ of the classpath.
Rephrased, you cannot expect that your mappingFileNamePattern would be interpreted alone for the search.
Hereunder, the code snippet of ClasspathScanningPersistenceUnitPostProcessor that makes the job:
String path = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
+ basePackage.replace('.', File.separatorChar)
+ File.separator + mappingFileNamePattern;
Small limitation of ClasspathScanningPersistenceUnitPostProcessor
You cannot scan for HBM files located at the root of JAR files in your classpath. basePackage doesn't support being empty and doesn't work with just a "." value.
Moreover, the underlying PathMatchingResourcePatternResolver doesn't work with Ant style path pattern with wilcard (* in you case) without a root directory (here and here (first warning in Other notes)).
Bug of ClasspathScanningPersistenceUnitPostProcessor
This class has never worked with Hibernate.
In the pre-1.4.x releases, there was this bug.
With this pull request, it seems there is a new bug that prevents me from getting the whole thing working with HBM in JARs. I got a NullPointerException at the line 146 because resource.getURI().getPath(); doesn't seem to work with an URI with two : in the protocol (jar:file:/ in this case) and returns a null path.
(I will update my answer with a link to a bug report either when I have find one or posted one.)