Is there a way to use environment variable in payara-resources.xml when creating connector-connection-pool - jms

I am running an application on Payara micro and trying to create a connector-connection-pool in the payara-resources.xml file that uses environment variables to pass in data as below:
<connector-connection-pool resource-adapter-name="wmq.jmsra" name="jms/MyConnectionPool"
connection-definition-name="javax.jms.ConnectionFactory">
<property name="transportType" value="CLIENT"/>
<property name="port" value="${ENV=CONFIGURATION_PORT}"/>
<property name="channel" value="${ENV=CONFIGURATION_CHANNEL}"/>
<property name="queueManager" value="${ENV=CONFIGURATION_MANAGER}"/>
<property name="username" value="${ENV=CONFIGURATION_USERNAME}"/>
<property name="hostName" value="${ENV=CONFIGURATION_HOST}"/>
</connector-connection-pool>
However this fails with the error below, but when I hardcode the values it works fine:
... 320 more
Caused by: com.ibm.mq.connector.DetailedResourceException: MQJCA1012: Failed to create a JMS connection factory., error code: MQJCA1012 A JCA ManagedConnectionFactory object was not able to create a WebSphere MQ classes for JMS ConnectionFactory object. Check the properties of the ConnectionFactory object.
... 321 more
Caused by: com.ibm.msg.client.jms.DetailedJMSException: JMSCC0005: The specified value '${ENV=CONFIGURATION_MANAGER}' is not allowed for 'XMSC_WMQ_QUEUE_MANAGER'.
The given value is not allowed for the property specified.
...
... 324 more
In the same file, I have created a jdbc-connection-pool in a similar way but it is able to resolve the environment variable successfully work:
<jdbc-connection-pool datasource-classname="org.postgresql.ds.PGConnectionPoolDataSource"
name="my_database" res-type="javax.sql.ConnectionPoolDataSource">
<property name="port" value="5432"/>
<property name="user" value="${ENV=DB_USER}"/>
<property name="password" value="${ENV=DB_PWD}"/>
<property name="ServerName" value="${ENV=DB_HOST}"/>
<property name="DatabaseName" value="${ENV=DB_NAME}"/>
</jdbc-connection-pool>

I solved my problem by moving away from defining resources in payara-resources.xml. I created a new class and defined all the resources in Java using these annotations, #DataSourceDefinition, #ConnectionFactoryDefinition, #AdministeredObjectDefinition and #MailSessionDefinition.
So the connector-connection-pool that was giving problems ended up looking like this:
#ConnectionFactoryDefinitions({
#ConnectionFactoryDefinition(
name = "java:app/jms/MyConnectionPool",
interfaceName = "javax.jms.ConnectionFactory",
resourceAdapter = "wmq.jmsra",
properties = {
"transactionSupport=XATransaction",
"transportType=CLIENT",
"channel=${ENV=CONFIGURATION_CHANNEL}",
"queueManager=${ENV=CONFIGURATION_MANAGER}",
"hostName=${ENV=CONFIGURATION_HOST}",
"port=${ENV=CONFIGURATION_PORT}",
"username=${ENV=CONFIGURATION_USERNAME}",
}
),
// other connection pools went here...
})

Related

How to dynamically pass the property in Spring FTP Outboud channel context xml

The FTPapplicationContext.xml has the configuration to create the beans for FTPchannel. here it takes the property values from the application.proprty. Now my question is how to dynamically set the property while on the run time.
Context.xml:
<bean id="ftpClientFactory" class="org.springframework.integration.ftp.session.DefaultFtpSessionFactory">
<property name="host" value="${host}"/>
<property name="port" value="${availableServerPort}"/>
<property name="username" value="${userid}"/>
<property name="password" value="${password}"/>
</bean>
<int:channel id="ftpChannel"/>
<int-ftp:outbound-channel-adapter id="ftpOutbound"
channel="ftpChannel"
remote-directory="/temp"
session-factory="ftpClientFactory">
<int-ftp:request-handler-advice-chain>
<int:retry-advice />
</int-ftp:request-handler-advice-chain>
</int-ftp:outbound-channel-adapter>
application.prperties:
userid=Administrator
password=password
availableServerPort=21
host=Testfar
FTP code:
ConfigurableApplicationContext context =
new FileSystemXmlApplicationContext("context.xml");
MessageChannel ftpChannel = context.getBean("ftpChannel",MessageChannel.class);
File file1 = new File("test.txt");
Message<File> fileMessage = MessageBuilder.withPayload(file1).build();
ftpChannel.send(fileMessage);
context.close();
In application.properiites file, I can setup a default host address but Here I need to pass the host address dynamically based on the user input. Could you please advice me on how to achieve that. It would be great If you suggest/provide some ideas.

Spring cache Cache name must be non-null if specified excpetion

I have been trying to implement a basic caching for my project but i am getting an error while deploying the application .
Server : Tomcat 7
Spring Version : 4.1.4
Caused by: java.lang.IllegalArgumentException: Cache name must be non-null if specified
at org.springframework.util.Assert.hasText(Assert.java:162)
at org.springframework.cache.interceptor.CacheOperation.setCacheNames(CacheOperation.java:66)
at org.springframework.cache.annotation.SpringCacheAnnotationParser.parseCacheableAnnotation(SpringCacheAnnotationParser.java:102)
at org.springframework.cache.annotation.SpringCacheAnnotationParser.parseCacheAnnotations(SpringCacheAnnotationParser.java:67)
at org.springframework.cache.annotation.SpringCacheAnnotationParser.parseCacheAnnotations(SpringCacheAnnotationParser.java:57)
at org.springframework.cache.annotation.AnnotationCacheOperationSource$2.getCacheOperations(AnnotationCacheOperationSource.java:124)
at org.springframework.cache.annotation.AnnotationCacheOperationSource.determineCacheOperations(AnnotationCacheOperationSource.java:142)
at org.springframework.cache.annotation.AnnotationCacheOperationSource.findCacheOperations(AnnotationCacheOperationSource.java:121)
at org.springframework.cache.interceptor.AbstractFallbackCacheOperationSource.computeCacheOperations(AbstractFallbackCacheOperationSource.java:140)
at org.springframework.cache.interceptor.AbstractFallbackCacheOperationSource.getCacheOperations(AbstractFallbackCacheOperationSource.java:100)
at org.springframework.cache.interceptor.CacheOperationSourcePointcut.matches(CacheOperationSourcePointcut.java:39)
at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:225)
at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:262)
at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:294)
at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(AbstractAdvisorAutoProxyCreator.java:118)
at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:88)
at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:69)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:330)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:293)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:422)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1571)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
... 64 more
I tried using different cache manager configuration with no luck
here is the xml configuarion
<cache:annotation-driven />
<bean id="cacheManager" class="org.springframework.cache.concurrent.ConcurrentMapCacheManager">
<constructor-arg>
<set>
<value>cache1</value>
<value>cache2</value>
<value>cache3</value>
</set>
</constructor-arg>
</bean>
I also tried the config given on the spring docs
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="cache1"/>
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="cache2"/>
</set>
</property>
</bean>
the function I am trying to cache
#Cacheable(value = "cache1", key = "#root.methodName")
public List<ObjectDetails> getAllObjects() {
return objectDao.getAllObjects();
}
Can any one point me towards where this issue might arise from while implementing caching.
Thanks to Stéphane Nicoll I was able to find the issue
Cache name must be non-null if specified
This means I have provided an empty string in place of cache name like this.
#Cacheable(value = "", key = "#root.methodName")
public List<ObjectDetails> getAllObjects() {
return objectDao.getAllObjects();
}
Provided a suitable name and it was resolved . Thanks.

spring DefaultMessageListenerContainer and websphere MQ - failed to connect Queue Manager

This is my first time to post question on stackoverflow. I tried as much formatting for code/question and try to as much clear as i can do. apologize and explain if there's any err. recorrect in my next question.
I am newbie in try implementing service through soap over jms using websphereMq and spring JMS functionality.
I have make sure below things
binding file generated without any error encounter
Status of queue manager and Queue are up and running.
I encounter below error while try putting message into websphereMQ
com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2058' ('MQRC_Q_MGR_NAME_ERROR')
I have done homework regarding this error. This error may occurs due to unavailability of Queue manager but i see QM is up and running. where i am doing wrong? How can i resolved this error to put message successfully to webspherMQ using spring functionlity?
TestClass
public class JmsTransportWebServiceIntegrationTest {
private static final String expectedResponseContent = "<tns:placeOrderResponse xmlns:tns=\"http://www.packtpub.com/liverestaurant/OrderService/schema\"><tns:refNumber>order-xxxx_yyyy_1234</tns:refNumber></tns:placeOrderResponse>";
#Autowired
private WebServiceTemplate webServiceTemplate;
public void setWebServiceTemplate(WebServiceTemplate webServiceTemplate) {
this.webServiceTemplate = webServiceTemplate;
}
#Test
public void testSendReceive() throws Exception {
InputStream is = new JmsTransportWebServiceIntegrationTest().getClass().getResourceAsStream("placeOrderRequest.xml");
StreamSource source = new StreamSource(is);
StringResult result = new StringResult();
webServiceTemplate.sendSourceAndReceiveToResult(source, result);
XMLAssert.assertXMLEqual("Invalid content received", expectedResponseContent, result.toString());
} }
applicationContext.xml
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<map>
<entry key="java.naming.factory.initial"
value="com.sun.jndi.fscontext.RefFSContextFactory"/>
<entry key="java.naming.provider.url" value="file:C:/JNDI-Directory" />
</map>
</property>
</bean>
<bean id="ibm-mq-jms-qcf" class= "org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate"/>
</property>
<property name="jndiName">
<value>jms/mdpSampleQCF</value>
</property>
</bean>
<!-- Bean for JMS Destination -->
<bean id="ibm-mq-queue" class= "org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate"/>
</property>
<property name="jndiName">
<value>jms/mdpSampleQueue</value>
</property>
</bean>
<bean id="listenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="concurrentConsumers" value="1" />
<property name="connectionFactory" ref="ibm-mq-jms-qcf" />
<property name="destination" ref="ibm-mq-queue" />
<property name="messageListener">
<bean class="org.springframework.ws.transport.jms.WebServiceMessageListener">
<property name="messageFactory" ref="messageFactory"/>
<property name="messageReceiver" ref="messageDispatcher"/>
</bean>
</property>
</bean>
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory"/>
<property name="messageSender">
<bean class="org.springframework.ws.transport.jms.JmsMessageSender">
<property name="connectionFactory" ref="ibm-mq-jms-qcf"/>
</bean>
</property>
<property name="defaultUri" value="jms:mdpSampleQueue?deliveryMode=NON_PERSISTENT"/>
</bean>
<bean id="messageDispatcher" class="org.springframework.ws.soap.server.SoapMessageDispatcher">
<property name="endpointMappings">
<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
<property name="defaultEndpoint">
<bean class="com.packtpub.liverestaurant.service.endpoint.SimplePayloadEndpoint">
<property name="orderService">
<bean class="com.packtpub.liverestaurant.service.OrderServiceImpl"/>
</property>
</bean>
</property>
</bean>
</property>
</bean
I know this is quite old question, but maybe my answer will help someone in future.
I'm using WebSphere MQ 7.5 now and in installation there are also some Java classes. One that helped me a lot is called MQIVP.java in my installation in c:\Program Files (x86)\IBM\WebSphere MQ\tools\wmqjava\samples. Very good to test setting with this class first. From source of that class we can find that 2058 stands for:
Reason: 2058 - Queue manager name not valid or not known.
Action: Amend the queue manager name and retry.
Simply pressing enter at the queue manager name prompt will
connect to the default queue manager.

#Resource dataSource mappedName - overriding to test in non JNDI env

I have an existing service bean which we deployed in Jboss. Unfortunatly it's dataSource reference is configured to inject the datasource reference via the "mappedName" lookup of the JNDI Service.
#Resource(name = "dataSource", mappedName = "java:/OracleDS")
private DataSource dataSource = null;
I want to test the bean in a non JNDI env. I expected to get this exception when i run in a non JNDI env.
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating
bean with name 'myService': Injection of resource fields failed; nested exception
is org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean
definition with name 'java:/OracleDS' defined in JNDI environment: JNDI lookup
failed; nested exception is javax.naming.NoInitialContextException: Need to
specify class name in environment or system property, or as an applet parameter,
or in an application resource file: java.naming.factory.initial
I realise the quickest way to fix this is to dropped the mappedName restriction, since then the production or test spring context can define the datasource. But in the case that i can't do this. Is there a way to define an InitialContext via a test spring context to avoid the exception above.
I did some more reading on SimpleNamingContextBuilder and came up with this context setup for my test case. The trick being to use the MethodInvokingFactoryBean to ensure the bind() method is called.
<bean id="jndiContext" class="org.springframework.mock.jndi.SimpleNamingContextBuilder" factory-method="emptyActivatedContextBuilder"/>
<bean id="invokingFactoryBean"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject">
<ref local="jndiContext" />
</property>
<property name="targetMethod">
<value>bind</value>
</property>
<property name="arguments">
<list>
<value>java:/OracleDS</value>
<ref bean="dataSource" />
</list>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${datasource.driverClassName}" />
<property name="url" value="${datasource.url}" />
<property name="username" value="${datasource.username}" />
<property name="password" value="${datasource.password}" />
</bean>

Spring Programmatic Jdbc Transaction rollback doesn't work

I use spring transaction to include a few db update operation into a single transaction. let say there 2 db updates within a single transaction. the update 1 is successful while the second fails. my problem is when such a case happens, the first db update get committed to db even though the second db update failed which leads to transaction rollback.
XML declaration:
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="test" />
<property name="password" value="test" />
</bean>
<bean id="testDao" class="dao.TestDao">
<constructor-arg >
<ref local="simpleJdbcTemplate" />
</constructor-arg>
<constructor-arg >
<ref local="txManager" />
</constructor-arg>
</bean>
java code:
public class DaoCallback extends TransactionCallbackWithoutResult {
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
try{
dbUpdate1();
dbUpdate2();
}catch(Exception e){
arg0.setRollbackOnly();
}
}
i intentionally make the dbUpdate1 to success and the dbUpdate2 to fail so as the test out whether the rollback really works. When I debug through my code, i can see that the control flow run into the catch exception and the "setRollbackOnly()" method is called.
But when I check the database, I can see the change from dbUpdate1(). So please help explain what is wrong here?
Dara kok,
I've found out the problem. It's not the code i've that cause the problem. it's MySQL data storage configuration. MyISAM doesn't support transaction.
Spring should have shown some kind of error message so that developer can know that a transaction is being called on a database engine without transaction support.

Resources