how to pass values dynamically in config file - database

I want to pass the value in the value tag of the property dynamically from the DB. Is this possible in Spring? And how ?
For example in the configuration below.
<bean id="proxyFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
<property name="serviceClass" value="WSDLURL"/>
<property name="address" value="WSDLURL"/>
<property name="username" value="username"/>
<property name="password" value="password"/>
</bean>
I want the properties mentioned above for the bean with id "proxyFactory", i.e. <WSDLURL> and <username> and <password> to be taken from the DB and passed here dynamically.

You can write a another Java class and make it as a bean in Application context and using Spring Expression Language, you have evaluate and get output of the method call.
XML configuration:
<property name="serviceClass"
value="#{webServiceInfoFromDB.wsdlUrl}" />
<property name="username"
value="#{webServiceInfoFromDB.username}" />
WeServiceInfoFromDB.java class:
class WebServiceInfoFromDB {
public String getWsdlUrl() {
// Get the Wsdl URL from DB.
return wsdlUrl;
}
public String getUsername(){
// get the username from DB
return username;
}
XML configuration in application context:
<bean id="webServiceInfoFromDB" class="WebServiceInfoFromDB">
<property name="dataSource" ref="dataSource"/>
</bean>

You can setup property Place Holder with your properties file name that contains key-value pair.
<context:property-placeholder location="config.properties" />
The config.properties file looks like:
wsdl.url = http://server:8080/ServiceAccessPoint
webservice.username = guest
webservice.passward = guest123
Now you can modify your bean definition with ${key}
<bean id="proxyFactory"
class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
<property name="serviceClass" value="${wsdl.url}"/>
<property name="address" value="${wsdl.url}"/>
<property name="username" value="${webservice.username}"/>
<property name="password" value="${webservice.password}"/>

Related

Spring batch, unable to write on oracle database

this is my xml file configuration.
<batch:job id="pdgRecallJob">
<batch:step id="stepTmpRecall">
<batch:tasklet>
<batch:chunk reader="readFileRecall" processor="" writer="tmpRecallWriter" commit-interval="10000">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="tmpRecall" class="it.mef.pdg.batch.model.TmpRecall" scope="prototype" />
<bean id="readFileRecall" class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="strict" value="false" />
<property name="resource" value="classpath:/properties/RECALLPDG_*.txt"/>
<property name="lineMapper">
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer">
<bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="delimiter" value=";"/>
<property name="names" value="appNomeFile, appCodFisc, appRata, appImporto, appIscrizione, appNumTitolo,
appProgQuota, appAnnoEmissione, appCodEnte, appEsitoMef, appStatoFile, appDpt, appPostazione, appNLotto,
appDLotto, appNomeFileOrigine" />
</bean>
</property>
<property name="fieldSetMapper">
<bean class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
<property name="prototypeBeanName" value="tmpRecall" />
</bean>
</property>
</bean>
</property>
</bean>
<bean id="tmpRecallWriter" class="org.springframework.batch.item.database.JdbcBatchItemWriter">
<property name="dataSource" ref="dataSource" />
<property name="sql">
<value>
<![CDATA[
INSERT INTO APP_TMP_RECALL(APP_NOME_FILE,APP_COD_FISC,APP_RATA,APP_IMPORTO,APP_ISCRIZIONE,APP_NUM_TITOLO,APP_PROGR_QUOTA,APP_ANNO_EMISSIONE,APP_COD_ENTE,APP_ESITO_MEF,APP_STATO_FILE,APP_DPT,APP_POSTAZIONE,APP_NLOTTO,APP_DLOTTO,APP_NOME_FILE_ORIGINE)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
]]>
</value>
</property>
<property name="itemPreparedStatementSetter">
<bean class="it.mef.pdg.batch.items.TmpRecallPreparedStatementSetter" />
</property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.user}" />
<property name="password" value="${db.pass}" />
</bean>
Then my itemPreparedStatementSetter Class:
final class TmpRecallPreparedStatementSetter implements ItemPreparedStatementSetter<TmpRecall>{
public void setValues(TmpRecall tmp, PreparedStatement ps) throws SQLException {
ps.setString(1, tmp.getAppNomeFile());
ps.setString(2, tmp.getAppCodFisc());
ps.setInt(3, tmp.getAppRata());
ps.setDouble(4, tmp.getAppImporto());
ps.setString(5, tmp.getAppIscrizione());
ps.setInt(6, tmp.getAppNumTitolo());
ps.setString(7, tmp.getAppProgQuota());
ps.setInt(8, tmp.getAppAnnoEmissione());
ps.setString(9, tmp.getAppCodEnte());
ps.setString(10, tmp.getAppEsitoMef());
ps.setString(11, tmp.getAppStatoFile());
ps.setString(12, tmp.getAppDpt());
ps.setInt(13, tmp.getAppPostazione());
ps.setInt(14, tmp.getAppNLotto());
ps.setDate(15, tmp.getAppDLotto());
ps.setInt(16, tmp.getAppNLotto());
}
}
My batch seems to work then I have final status COMPLETED, but it doesn't write no record inside my table.
I'm using jdk 1.5, ojdbc5-11.2.0.3.jar.
Either is there something I'm missing in my xml conf or any bean is not ok?
I was thinking that might be even a mismatch in Date field in table.
You don't currently have an item processor, which (I think) is needed to pass records from the reader to the writer. Since you are not doing any processing (that is, your reader produces the same type that your writer consumes), I think you could use a PassThroughItemProcessor here.

Spring : How to manually reset connection pool's connection?

I am trying to validate the database health manually using #Aspect.
And if something happened in DatabaseA (in my case is DatabaseA have no more write permission) the application will switch to DatabaseB.
How can I manually re-initialize the connection pool so that I can ensure all connection is going to DatabaseB?
#Aspect
#Component
#Order(value=1)
public class PostServiceAspect extends BaseService {
#Before("execution(* com.some.class.execute(..))")
public void databaseHealthCheck() {
try {
databaseDao.excuteHealthCheckSQL(); // execute "UPDATE table SET field = 1;"
} catch (Exception ex) {
databaseDao.switchTargetDatabase(); // switch to databaseB
// How to re-initialize the connection pool
}
}
//DataSource config
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://testinghost:3306/devgpayment" />
<property name="username" value="root" />
<property name="password" value="password" />
<property name="defaultAutoCommit" value="false" />
<property name="maxTotal" value="40" />
<property name="maxIdle" value="40" />
<property name="maxWaitMillis" value="10000" />
<property name="validationQuery" value="SELECT 1" />
<property name="testWhileIdle" value="true" />
<property name="timeBetweenEvictionRunsMillis" value="5000" />
</bean>

Can I hide Database connectivity details from hibernate cfg file?

Just need to check, If there is the the way to hide Database connectivity details like username or password from hibernate configuration file:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="url" value="jdbc:oracle:thin:#localhost:1521:xe"></property>
<property name="username" value="system"></property>
<property name="password" value="tiger"></property>
</bean>
You have 2 options
1) Use JNDI
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd">
<jee:jndi-lookup id="dbDataSource" jndi-name="jdbc/DatabaseName" expected-type="javax.sql.DataSource" />
2) Use a property placeholder
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:database.properties</value>
<!-- this example use the system parameter configlocation, add -Dconfiglocation -->
<value>file:${configlocation}/database.properties</value>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="url" value="jdbc:oracle:thin:#localhost:1521:xe"></property>
<property name="username" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
The password can be in the file database.properties which is only in the classpath for the running application and not visible to all.

How to use Camel to get message from remote WMQ and place message in ActiveMQ?

I have been looking at these for days and still haven't have mush success.
I have install and run activeMQ on a server. Created a queue called "testUpdate". I also have another queue on another server, let call this "forward" and this is on the IBM MQ (WMQ).
So we have testUpdate on ActiveMQ and forward on WMQ. I want the message on forward queue to be placed into testUpdate queue. Trying to use Camel for this process.
So the setup in ActiveMQ has an XML(activemq.xml) that I can place spring beans and configure to do the routing. In this xml, I added http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd to the xmlns and then added
import resource="camel.xml"
In this new xml, I have the following:
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<route>
<description>Example Camel Route</description>
<from uri="mqseries:forward"/>
<to uri="activemq:testUpdate"/>
</route>
</camelContext>
<bean id="mqseries" class="com.ibm.mq.jms.MQQueueConnectionFactory">
<property name="transportType" value="1"/>
<property name="hostName" value="172.00.12.21/>
<property name="port" value="xyza"/>
<property name="queueManager" value="manager"/>
<property name="channel" value="srvcChannel"/>
</bean>
<!--
Lets configure some Camel endpoints
http://camel.apache.org/components.html
-->
<!-- configure the camel activemq component to use the current broker -->
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent" >
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://amq-broker?create=false"/>
<property name="userName" value="${activemq.username}"/>
<property name="password" value="${activemq.password}"/>
</bean>
</property>
</bean>
</beans>
I added the jar file com.ibm.mq.allclient.jar into the lib folder of ActiveMQ. When running the program, I am getting this exception:
java.lang.ClassNotFoundException: javax.jms.JMSRuntimeException
It sounds like I am missing the websphere jar file? Is this correct?
I use both IBM MQ and ActiveMQ on a regular basis. This example below will show you some sample configuration options. Please make sure you configure these to your own use cases.
//ActiveMQ connection factory
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent" destroy-method="doStop">
<property name="configuration">
<bean class="org.apache.camel.component.jms.JmsConfiguration">
<property name="concurrentConsumers" value="1" />
<property name="maxConcurrentConsumers" value="1" />
<property name="acceptMessagesWhileStopping" value="true" />
<property name="acknowledgementModeName" value="CLIENT_ACKNOWLEDGE" />
<property name="cacheLevelName" value="CACHE_CONSUMER" />
<property name="connectionFactory">
<bean class="org.apache.activemq.pool.PooledConnectionFactory" init-method="start" destroy-method="stop">
<property name="maxConnections" value="1" />
<property name="MaximumActiveSessionPerConnection" value="500" />
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="${activemq1.brokerUrl}" />
<property name="userName" value="${activemq1.username}" />
<property name="password" value="${activemq1.password}" />
<property name="redeliveryPolicy">
<bean class="org.apache.activemq.RedeliveryPolicy">
<property name="maximumRedeliveries" value="-1" />
</bean>
</property>
</bean>
</property>
</bean>
</property>
</bean>
</property>
</bean>
//IBM MQ connection factory
<bean id="ibmmq" class="org.apache.camel.component.jms.JmsComponent" destroy-method="doStop">
<property name="concurrentConsumers" value="1" />
<property name="maxConcurrentConsumers" value="1" />
<property name="connectionFactory">
<bean class="org.springframework.jms.connection.SingleConnectionFactory" destroy-method="destroy">
<constructor-arg>
<bean class="com.ibm.mq.jms.MQQueueConnectionFactory">
<property name="transportType" value="1" />
<property name="channel" value="${channel}" />
<property name="hostName" value="${hostname}" />
<property name="port" value="${port}" />
<property name="queueManager" value="${queueManager}" />
</bean>
</constructor-arg>
</bean>
</property>
</bean>
You can use jms component to consume the message from IBM MQ and use activemq component to post it to ActiveMQ
have a look at the following links
http://camel.apache.org/jms.html
http://camel.apache.org/activemq.html
Thanks,
Gibu
You can use users camel extra component https://github.com/camel-extra/camel-extra/blob/master/components/camel-wmq/README.md to get messages from wmq without using the JMS wrapping and then send messages to ActiveMQ with custom camel component https://camel.apache.org/components/latest/activemq-component.html. See also a similar topic Apache Camel with IBM MQ.

Retrieve attributes from jasig cas server from database

I have a problem in retrieving attributes from java cas (JA-SIG). It always return null.
Below is my code. What I guess was attributeRepository bean is never called, because I have changed table name to wrong one, and it ran, but it didn't give the runtime error for SQL Exception.
This is my deployerConfigContext.xml file (only the relevant part)
<bean id="authenticationManager" class="org.jasig.cas.authentication.AuthenticationManagerImpl">
<property name="credentialsToPrincipalResolvers">
<list>
<bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver">
<property name="attributeRepository">
<ref bean="attributeRepository"/>
</property>
</bean>
</list>
</property>
</bean>
<bean id="attributeRepository" class="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao">
<constructor-arg index="0" ref="dataSource"/>
<constructor-arg index="1" value="SELECT id,is_admin,screen_name FROM user WHERE {0}"/>
<property name="queryAttributeMapping">
<map>
<entry key="login" value="eroshan#rcapl.com" />
</map>
</property>
<property name="resultAttributeMapping">
<map>
<entry key="id" value="150" />
<entry key="is_admin" value="0" />
<entry key="screen_name" value="xxxx.." />
</map>
</property>
</bean>
Below is my client code to retrieve attributes. org.jasig.cas.client.authentication.Saml11AuthenticationFilter is used for getting data.
<h1>CAS Attribute Test</h1>
<p>User Id: <%= request.getRemoteUser() %></p>
<%
if (request.getUserPrincipal() != null) {
AttributePrincipal principal = (AttributePrincipal) request.getUserPrincipal();
Map attributes = principal.getAttributes();
out.println("attribute :"+attributes.size());
if (attributes != null) {
Iterator attributeNames = attributes.keySet().iterator();
out.println("Received attributes: <b>" + (attributeNames.hasNext() ? "YES!" : "No") + "</b>");
out.println("<hr><table border='3pt' width='100%'>");
out.println("<th colspan='2'>Attributes</th>");
out.println("<tr><td><b>Key</b></td><td><b>Value</b></td></tr>");
for (; attributeNames.hasNext();) {
out.println("<tr><td>");
String attributeName = (String) attributeNames.next();
out.println(attributeName);
out.println("</td><td>");
Object attributeValue = attributes.get(attributeName);
out.println(attributeValue);
out.println("</td></tr>");
}
out.println("</table>");
} else {
out.println("<pre>The attribute map is empty. Review your CAS filter configurations.</pre>");
}
} else {
out.println("<pre>The user principal is empty from the request object. Review the wrapper filter configuration.</pre>");
}
%>
When I print the attribute size it shows 0. What is wrong with my code? I'm having big trouble sorting this issue. Lot of resources are available for getting attributes from Ldap, but I need from my db.
Your config looks good, nonetheless you need to define for your CAS service which attributes you want to return and I don't see this part in your extracted config : this is done in the serviceRegistryDao bean for a RegisteredServiceImpl bean, property "allowedAttributes".
An example :
<bean id="serviceRegistryDao" class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl">
<property name="registeredServices">
<list>
<bean class="org.jasig.cas.services.RegisteredServiceImpl">
<property name="id" value="0" />
<property name="name" value="HTTP" />
<property name="description" value="Only Allows HTTP Urls" />
<property name="serviceId" value="http://**" />
<property name="evaluationOrder" value="10000001" />
<property name="allowedAttributes">
<list>
<value>name</value>
<value>first_name</value>
<value>middle_name</value>`
...

Resources