We are using Spring JMS integration for connecting our application to Tibco EMS product. Our jndi template is defined as follows bean:
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">${app.java.naming.factory.initial}</prop>
<prop key="java.naming.provider.url">${app.java.naming.provider.url}</prop>
</props>
</property>
</bean>
Value of app.java.naming.provider.url is defined in property file as of now as :
app.java.naming.provider.url=tcp://server1:7222
I want to make our application pass multiple provider urls is it possible as follows:
app.java.naming.provider.url=tcp://server1:7222,tcp://server2:7222,tcp://server3:7222,tcp://server4:7222
At given time only one server will up, but if other goes down we dont want to change config and re-deploy hence above mechanism.
How Spring JNDI template works with multiple provider urls.
Related
I have a use case where need to integrate Flyway within application and execute the DDL scripts during application start up which is a normal flyway work of executing the scripts on basis of seeing diff in schema_version table.
The DB used is MSSQL server
The problem here is when defining the FluentConfiguration and using it in creating Flyway Bean
#Bean
public FluentConfiguration flywayBaseConfiguration() {
FluentConfiguration configuration = new FluentConfiguration();
configuration.baselineOnMigrate(true);
configuration.locations("classpath:com/schemafiles/db_release/DBSQLSERVER");
configuration.table("schema_version");
configuration.sqlMigrationPrefix("");
configuration.sqlMigrationSeparator("UTC-");
configuration.dataSource(String.format("jdbc:jtds:sqlserver:/DBDEVSERVER/TestDB", confManager.getOrThrow(DB_URL))
, confManager.getOrThrow("db.username"));
return configuration;
}
#Bean
public Flyway flyway(FluentConfiguration fluentConfiguration) {
Flyway flyway = new Flyway(fluentConfiguration);
flyway.migrate();
return flyway;
}
This fluent config defined above will be used for connecting flyway to DB.
Now if i see the data source connection for the application connecting to prod DB its as follows
<bean id="prodDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="connectionProperties">
<props>
<prop key="appName">${app.name}</prop>
<prop key="useKerberos">true</prop>
<prop key="loginTimeout">${db.login.timeout}</prop>
<prop key="socketTimeout">${db.socket.timeout}</prop>
</props>
</property>
<property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver"/>
<property name="url" value="jdbc:jtds:sqlserver://DBDEVSERVER/TestDB"/>
</bean>
This is using Kerberos auth in connecting to DB . We are only providing the user name and rest everything is governed by kerberos security realm.
The question is does Flyway Fluent Configuration support something related to Kerberos auth in order to be able to execute the DDL scripts without providing the password ??..
I've got a Spring Integration flow which uses an inbound gateway to get messages from an IBM MQ queue:
<int-jms:inbound-gateway id="InputGateway"
request-destination="RequestQueue"
request-channel="RequestChannel"
reply-channel="ReplyChannel"
/>
However I'm not capable of assigning security settings. In particular, I need an username, password and userAuthenticationMQCSP = false (for reasons beyond the scope of this post, I won't get into details but my broker will throw a MQRC = 2009 otherwise).
I've followed the IBM guide to connect with jmsTemplate and works just fine. This uses the official Spring boot starter from IBM MQ which will kindly create a connection factory and will autoconfigure it with some defaults from application.properties:
ibm.mq.queueManager=myQMName
ibm.mq.channel=myChannel
ibm.mq.connName=myhostname(myPort)
ibm.mq.user=username
ibm.mq.password=*******
ibm.mq.userAuthenticationMQCSP=false
Now, back to the Spring Integration case. According to the int-jms:inbound-gateway spec, a connectionFactory will be injected to the gateway, by name (attribute: connection-factory) which is set up to be "jmsConnectionFactory" by default
By default, all of the JMS adapters that require a reference to the
ConnectionFactory automatically look for a bean named
jmsConnectionFactory. That is why you do not see a connection-factory
attribute in many of the examples. However, if your JMS
ConnectionFactory has a different bean name, you need to provide that
attribute.
I don't see any way to set up a predictable name for the connection factory that I can plug into the int-jms:inbound-gateway.
Now, taking a different approach, as per this example I've created my connectionFactory with an adecuate name:
<bean id="jmsConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
<property name="transportType" value="1"/>
<property name="queueManager" value="myQMName"/>
<property name="hostName" value="myhostname"/>
<property name="port" value="myPort" />
<property name="channel" value="myChannel"/>
</bean>
But now I need somewhere to put the credentials and the security parameters. Looking at the example above, it looks like I need to plug something like:
<bean id="secureJmsConnectionAdapter" class="**yourpackages.SecureJMSConnectionAdapter**">
<property name="targetConnectionFactory" ref="${jms.mq.connection.factory}" />
<property name="userName" value="${jms.username}"/>
<property name="pwdAlias" value="${jms.alias}"/>
</bean>
However it is unclear to me how to implement this SecureJMSConnectionAdapter.
Additionally, if I set up my own connection factory, I will lose all of MQ boot starter automagic thanks to this annotation on the MQAutoConfiguration class:
#ConditionalOnMissingBean(value=javax.jms.ConnectionFactory.class)
Any ideas on how to put these pieces together?
EDIT: Just to avoid any possible red herrings to anyone, the MQRC2009 was irrelevant to ibm.mq.userAuthenticationMQCSP=false.
Some of my old projects I used a bean like this:
<bean id="jmsQueueConnectionFactory"
class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
<property name="targetConnectionFactory" ref="jmsConnectionFactory"/>
<property name="username" value="${jms.username}"/>
<property name="password" value="${jms.alias}"/>
</bean>
Should work well as a wrapper for your com.ibm.mq.jms.MQQueueConnectionFactory, but you have to use this jmsQueueConnectionFactory in the target components.
Although it looks like the mentioned IBM MQ JMS Spring doesn't that for us properly exposing a jmsConnectionFactory bean. You can rely on the default from Spring Integration in this case or use that jmsConnectionFactory explicitly for the connection-factory.
Also with Spring Boot you should consider to go away from XML configuration and give a chance for Spring Integration Java DSL: https://docs.spring.io/spring-integration/docs/5.1.7.RELEASE/reference/html/#java-dsl
I've managed to setup a web service using Spring Integration that goes through a ws inbound gateway and then on to a service activator. Now I want to change the setup so that the inbound gateway is no longer the default endpoint mapping because there are other existing services that need to be available. When I change the UriEndpointMapping so that the gateway is no longer the default endpoint, I get this message: org.springframework.ws.server.EndpointNotFound - No endpoint mapping found for [SaajSoapMessage ....
I've tried changing the UriEndpointMapping to set the mappings property where I set the url to the gateway reference, and I've tried setting the endpointMap property and used a number of different keys, all without success. The Spring Integration documentation doesn't indicate how to set the UriEndpointMapping for multiple endpoints that are mapped to gateways, and the examples I've found on the web don't work for me either. I'm at a loss on how to proceed.
FYI, this configuration needs to be done in a spring xml file if at all possible.
This works:
<bean class="org.springframework.ws.server.endpoint.mapping.UriEndpointMapping">
<property name="defaultEndpoint" ref="reconGateway"/>
</bean>
This is my latest try, but it fails.
<bean class="org.springframework.ws.server.endpoint.mapping.UriEndpointMapping">
<property name="usePath" value="true"/>
<property name="mappings">
<props>
<prop key="http://localhost:8081/intfacade-web/reconService">reconGateway</prop>
</props>
</property>
</bean>
Any help would be greatly appreciated. Oh, I have tried with just the path and that didn't work either.
Thanks!
Anyone?
I have a server application. Now I'm using Spring not only to inject dependencies, but also to config my application. Something like this:
<bean id="server" class="foo.bar.Server">
<property name="host" value="${config.host}"/>
<property name="someBean">
<ref bean="someBean"/>
</property>
</bean>
My colleague sad that configuring application in Spring is not obvious and we should avoid this. I see logic in his words, because Spring is for dependence injection and server port is not dependency, isn't it? But for me configuring application is Spring is very convenient and obvious. Is my colleague right?
Configuring in Spring is simple, clear and maintainable.
This way you can easily create several instances with different properties.
I have a Spring MVC web app which uses FreeMarker for rendering the views and have come up with the following issue.
Within my FreeMarker config I declare a Singleton Spring bean as a FreeMarker variable and within my application I have provided the mechanism for the Singleton Bean to be dynamically refreshed (the bean contains the application config retrieved from the DB).
Now the problem is that when it is refreshed the previously rendered FreeMarker templates use the values within the older version yet if I navigate to a page not rendered since the container started it uses the new values.
The following is a snippet of my FreeMarker config:
<!-- FreeMarker config -->
<bean id="freemarkerViewConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPaths">
<array>
<value>/WEB-INF/freemarker</value>
<value>classpath:/WEB-INF/freemarker</value>
</array>
</property>
<property name="freemarkerSettings">
<props>
<prop key="datetime_format">dd/MM/yyyy</prop>
<prop key="number_format">#</prop>
<prop key="whitespace_stripping">true</prop>
<prop key="auto_import">
spring.ftl as spring,
custom-macros.ftl as custom,
</prop>
</props>
</property>
<property name="freemarkerVariables">
<map>
<entry key="xml_escape" value-ref="fmXmlEscape"/>
<entry key="html_escape" value-ref="fmHtmlEscape"/>
<entry key="config" value-ref="config"/>
</map>
</property>
</bean>
To refresh the config model I execute the following within my Controller class:
((XmlWebApplicationContext)applicationContext).refresh();
Having this configuration picks up the refreshed config model when accessing a page which hasn't been already rendered but won't recognise the change on pages already visited.
I have tried the following to enforce the 'refresh' of the variable with no luck:
In the controller after the context is refresh I clear the templateCache within the FreeMarker Config which has been autowired:
freeMarkerConfig.getConfiguration().clearTemplateCache();
I have also tried disabling the caching of templates within the FreeMarker config using the following property within freeMarkerSettings:
freemarker.cache.NullCacheStorage
Finally, its worth pointing out that when in debug and looking through the cache and configuration the Shared Variable does indeed reference the most up to date config model yet the page renders using the older version.
Any advice / guidance on how to resolve this?
ps I am using Spring v3.1.1.RELEASE and FreeMarker v2.3.19
Not quite a solution but I have fixed my issue but it is more a hack to be honest.
I changed the code to refresh my config by using the following command so only the config bean was recreated:
((DefaultListableBeanFactory) beanFactory).destroySingleton("config");
And then modified the freemarker config by removing the reference to the config model as regardless what I tried I could not get this to be refreshed. So the solution to my issues was then to modify the BaseController which every controller within the application extends exposing the config model available as a #ModelAttribute so it was available to all the views.
As I said doesn't really solve the underlying issue but I have solved my problem albeit in a unorthodox fashion.