Spring Batch - Load properties from database table - spring

I have a requirement in my spring batch where I have to load few key value properties from a database table. Is this possible? The job runs in a stand alone environment and not in a container.
Please let me know if you have a solution for this. `I am in a secured environment and that is the reason I have not shared the code initially. Anyways below is what I have. Below are my properties
<bean id="properties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath:EnvConfig.properties</value>
<value>classpath:DatabaseConfig.properties</value>
<value>classpath:WebServiceConfig.properties</value>
</list>
</property>
</bean>
<bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="properties" />
</bean>
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties">
<bean class="org.apache.commons.configuration.ConfigurationConverter"
factory-method="getProperties">
<constructor-arg>
<bean class="org.apache.commons.configuration.DatabaseConfiguration">
<constructor-arg>
<ref bean="sam-datasource" />
</constructor-arg>
<constructor-arg value="PTTMCDB.PROPERTY" /> <!-- DB Table -->
<constructor-arg value="PROPERTYNAME" /> <!-- DB Key Column -->
<constructor-arg value="PROPERTYVALUE" /> <!-- DB Value Column -->
</bean>
</constructor-arg>
</bean>
</property>
</bean>
This is where I am reading the properties fetched from DB.
<bean id="emailReaderUtil"
class="mailreader.pop3.EmailReaderUtil">
<property name="popServerHost" value="${pop3.popServerHost}"/>
</bean>

Related

spring bean optional property

I am using a data source defined in tomcat in my spring configuration as shown in the below xml.
It can happen sometimes that this data source may not be defined in the context.xml of tomcat.
In such cases , the context initialization fails since myDS is not found.
Is it possible to configure the datasource as optional so that application initialisation is not impacted ?
There can be a run time error when this data source is accessed , which is acceptable
<bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/myDS"/>
</bean>
<bean id="myEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
<property name="packagesToScan" value="com..XX.XX" />
<property name="persistenceUnitName" value="myPU" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="#{systemProperties['showSql'] == null ? 'true' : systemProperties['showSql'] }" />
</bean>
</property>
<property name="persistenceUnitPostProcessors">
<list>
<ref bean="wrkflw-punitpostprocessor" />
</list>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">#{systemProperties['dbDialect']}</prop>
</props>
</property>
</bean>
Thanks
Muhad
You may check the DelegatingDataSource, you could encapsulate the logic to load the datasource from JNDI within its instantiation. For your application there will be always a DataSource there, but in some cases (whenever its not able to load the DataSource from JNDI) there is no delegation.

Spring+ Hibernate :How to map single session factory in multiple modules (deployed as jar)

I am working on Spring + Struts2 and Hibernate currently, My requirement is :
I have Master module which will make DB connection, shared by all other modules (deployed as Jar) in the system.
All Module specific .hbm and persistence classes will exists in Module itself
So for example My master module will have Hibernate connection file (through spring) will all .hbm mapping files, Below is the sample of Hibernate connection made through Spring.
<bean id="dataSourceErik" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="testWhileIdle" value="true" />
<property name="minEvictableIdleTimeMillis" value="120000" />
<property name="timeBetweenEvictionRunsMillis" value="30000" />
</bean>
<bean id="sessionFactoryErik"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSourceErik" />
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.generate_statistics=true
hibernate.show_sql=false
hibernate.jdbc.batch_size=10
hibernate.bytecode.use_reflection_optimizer=true
hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
hibernate.cache.use_second_level_cache=true
hibernate.cache.use_query_cache=true
net.sf.ehcache.configurationResourceName=configuration/ehcache.xml
</value>
</property>
<property name="mappingLocations">
<list>
<value>classpath:configuration/hibernate/Abc.hbm.xml</value>
<value>classpath:configuration/hibernate/Xyz.hbm.xml</value>
</list>
</property>
</bean>
<bean id="AbcActionDAO" class="au.com.master.persistance.dao.AbcDbSession">
<constructor-arg ref="sessionFactoryErik" />
</bean>
<bean id="XyzActionTypeDAO"class="au.com.master.persistance.dao.XyzDbSession">
<constructor-arg ref="sessionFactoryErik" />
</bean>
if i add below code in above xml i can access '''sessionFactory''' and can connect with the DB. as i am giving the path of deployed subModule jar file, see below code :
<property name="mappingJarLocations">
<list>
<value>WEB-INF/lib/subModule.jar</value>
</list>
</property>
All above .hbm and DAO/DbSession classes exists in Master module. Now i want to use this '''sessionFactoryErik''' in my Sub modules deployed as jar. so for that i created another xml file in Sub module which will take reference of above '''sessionFactoryErik''' and will have mappings of this module specific .hbm and DAO/DbSession. Refer below code:
<bean id="sessionFactoryMonitor" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="sessionFactoryErik" ref="sessionFactoryErik" />
<property name="mappingLocations">
<list>
<value>classpath:configuration/hibernate/DDDType.hbm.xml</value>
</list>
</property>
</bean>
<bean id="testActionDAO" class="au.com.java.subModule.persistance.dao.DddActionDbSession">
<constructor-arg ref="sessionFactoryMonitor" />
</bean>
if i deployed the project and reboot the server i am getting below error.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactoryMonitor' defined in URL [jar:file:/home/developer/Project/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/webapps/erik/WEB-INF/lib/erik-monitor-1.0-SNAPSHOT.jar!/configuration/spring-monitor-dao.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'sessionFactoryErik' of bean class [org.springframework.orm.hibernate4.LocalSessionFactoryBean]: Bean property 'sessionFactoryErik' is not writable or has an invalid setter method.
Can anyone help me for this. How can i get the same session object in sub module as only Master module can make connection as it will not have any knowledge of its deployed (deployed as jar) module.
Thanks.
Tapan
the class org.springframework.orm.hibernate4.LocalSessionFactoryBean doesn't have a property called sessionFactoryErik. I am guessing that you are injecting your datasource to LocalSessionFactoryBean. if so Change this
<bean id="sessionFactoryMonitor" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="sessionFactoryErik" ref="sessionFactoryErik" />
<property name="mappingLocations">
<list>
<value>classpath:configuration/hibernate/DDDType.hbm.xml</value>
</list>
</property>
</bean>
to this
<bean id="sessionFactoryMonitor" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="sessionFactoryErik" />
<property name="mappingLocations">
<list>
<value>classpath:configuration/hibernate/DDDType.hbm.xml</value>
</list>
</property>
</bean>
sessionFactoryErik bean returns org.hibernate.internal.SessionFactoryImpl object,
so you should specify org.hibernate.internal.SessionFactoryImpl or its super class
(SessionFactory) type in au.com.master.persistance.dao.XyzDbSession constructor
reference.

spring jndi values from JNDI tree

I am working with spring 3.0 and within our JBoss application server I perform a JNDI lookup to a remote WebLogic application server. The properties to connect to the WebLogic JNDI server are contained in a properties file called soa.properties. Here is what the spring-config.xml looks like to initialize the JndiTemplate bean
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:app.properties</value>
<value>classpath:soa.properties</value>
</list>
</property>
</bean>
<bean id="soaJndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">${soa.provider.initial}</prop>
<prop key="java.naming.provider.url">${soa.provider.url}</prop>
<prop key="java.naming.security.principal">${soa.security.principal}</prop>
<prop key="java.naming.security.credentials">${soa.security.credentials}</prop>
</props>
</property>
</bean>
This works fine for pulling my values out of the soa.properties file, but what I would rather do is pull the WebLogic JNDI connection values out of the JBoss JNDI tree.
My problem appears to be with the initialization of the InitialContext object that requires Properties for initialization.
I put all of my JNDI String values for WebLogic JNDI connection into the JBoss JNDI. Below is the code I am using to pull the values out and initialize JndiTemplate bean.
<bean id="soaUrl" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="soa/provider/url" />
</bean>
<bean id="soaFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="soa/provider/connection/factory" />
</bean>
<bean id="soaInitial" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="soa/provider/initial" />
</bean>
<bean id="soaPrincipal" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="soa/security/principal" />
</bean>
<bean id="soaCredential" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="soa/security/credential" />
</bean>
<bean id="testsoaJndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<map>
<entry key="java.naming.factory.initial" value-ref="soaUrl" />
<entry key="java.naming.provider.url" value-ref="soaFactory" />
<entry key="java.naming.provider.initial" value-ref="soaInitial" />
<entry key="java.security.principal" value-ref="soaPrincipal" />
<entry key="java.security.credential" value-ref="soaCredential" />
</map>
</property>
</bean>
My application comes up with these beans created, but when I use testsoaJndiTemplate with say soaConnectionFactory like so it boms.
<bean id="soaConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="testsoaJndiTemplate" />
<property name="jndiName" value="${soa.provider.connection.factory.name}" />
</bean>
The error is so cryptic it does make any sense.
Thanks

Hibernate temporary datastore

I doing unit testing on spring-hibernate DAOs... configured using
#ContextConfiguration(
locations = {
"classpath:test-applicationContext.xml"
})
but it looks like its transacting with the actual database.
How do I use a temporary datastore with out working on actual database
Define your data store on a separate file and include that xml file with your mail application xml. When testing, include a separate xml file to hold your data store pointing to another database such as hsql. Then this will be the data source referred to by your main applicationContext.xml.
Thanks Guys I used H2 and got it working:
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url"
value="jdbc:h2:mem:processdb;INIT=RUNSCRIPT FROM 'classpath:create.sql'" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="stateDAO" class="com.tutorial.jquery.dao.impl.StateDAOImpl"></bean>
<bean id="stateService" class="com.tutorial.jquery.service.impl.StateServiceImpl"></bean>

jackson jaxb annotations support in Spring

i'm looking for the simplest way of adding jaxb annotations support to jackson.
Jackson is added now to Spring by <mvc:annotation-driven/>. I need that by #ResponseBody annotation the Object is converted to xml or json dependently to the media type.
I'm new in spring-mvc so doesn't understand well yet how things work. Thanks.
Okay, I assume you want to be able to return both XML and JSON. To do this you need to create MessageConverters for both formats.
The XML message converter:
<bean id="xmlConverter"
class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<constructor-arg>
<oxm:jaxb2-marshaller id="jaxb2Marshaller">
<!-- you must either bind your JAXB annotated classes here -->
<!-- OR provide a jaxb.index and use contextPath -->
<oxm:class-to-be-bound name="com.mycompany.MyClass"/>
</oxm:jaxb2-marshaller>
</constructor-arg>
<property name="supportedMediaTypes">
<list>
<bean class="org.springframework.http.MediaType">
<constructor-arg index="0" value="application"/>
<constructor-arg index="1" value="xml"/>
<constructor-arg index="2" value="UTF-8"/>
</bean>
</list>
</property>
</bean>
The JSON message converter, which uses the JAXB annotations:
<bean id="jaxbAnnotationInspector"
class="org.codehaus.jackson.xc.JaxbAnnotationIntrospector"/>
<bean id="jacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper">
<property name="annotationIntrospector" ref="jaxbAnnotationInspector"/>
</bean>
<bean id="jsonConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper">
<bean ref="jacksonObjectMapper"/>
</property>
<property name="supportedMediaTypes">
<list>
<bean class="org.springframework.http.MediaType">
<constructor-arg index="0" value="application"/>
<constructor-arg index="1" value="json"/>
<constructor-arg index="2" value="UTF-8"/>
</bean>
</list>
</property>
</bean>
And finally, the AnnotationMethodHandlerAdapter, which will convert the responses to the appropriate content type, depending upon the accept headers:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="xmlConverter"/>
<ref bean="jsonConverter"/>
</list>
</property>
</bean>
Note that the JAXB support in jackson isn't 100% complete or correct all the time, but the developers are really good at fixing bugs and responding to error reports.

Resources