timeout dynamic HTTP outbound gateway request-factory - java

I have configured timeouts for the HTTP Outbound Gateway providing a reference to a ClientHttpRequestFactory bean using the request-factory attribute:
<int-http:outbound-gateway request-channel="channelGetByCustomer"
request-factory="requestFactoryGetByCustomer"
reply-channel="jsonToObjectChannel" url="${getbycustomer.endpoint.url}"
http-method="GET" expected-response-type="com.mbracero.integration.dto.Item[]">
<int-http:uri-variable name="customerid" expression="payload.customerid"/>
</int-http:outbound-gateway>
<beans:bean id="requestFactoryGetByCustomer" class="org.springframework.http.client.SimpleClientHttpRequestFactory">
<beans:property name="connectTimeout" value="${getbycustomer.timeout}"/>
<beans:property name="readTimeout" value="${getbycustomer.timeout}"/>
</beans:bean>
But I want to load these attributes dynamically from DDBB (or programmatically) and not from Spring initial boot.
How can I do this?

Programmatically you can do that just from any your service injecting that requestFactoryGetByCustomer bean and using its setters:
#Autowired
private SimpleClientHttpRequestFactory requestFactoryGetByCustomer;
....
this.requestFactoryGetByCustomer.setConnectTimeout(30_000);
To read those options from the DB and populate them to the bean definition using Spring Container features (e.g. Property Placeholder like in your current case) you should take a look to the Commons Configuration framework and populate Properties object from the DB SELECT.

Related

How to inject an attribute using spring in a type handler?

I'm setting up an application which uses mybatis to map objects to/from the database.
In my mybatis file, I use a typehandler to map one of the objects being sent to the database.
In the typeHandler, I am injecting an attribute using spring #resource.
However, when the typehandler is called, the injected property is always null.
From my research, I have discovered that mybatis sets its configuration before spring loads. That means the bean is cannot be injected into the handler as it is created after.
Does anyone know a solution to this?
Should let spring manage customized type handler, like this:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="typeHandlers">
<array>
<bean class="com.example.YourCustomTypeHandler">
<!-- inject -->
<property name="property" ref="bean"/>
</bean>
</array>
</property>
</bean>

List jax-rs service beans

I have a jax-rs servlet configured with spring. In my beans.xml, I have a list of jax-rs beans:
<jaxrs:server id="salesRest" address="/">
<jaxrs:serviceBeans>
<bean id="usersWS" class="co.my.package.UsersImpl" />
<bean id="authenticationWS" class="co.my.package.AuthenticationImpl" />
</jaxrs:serviceBeans>
...
<jaxrs:server>
What I want is to be able to get a list of these beans programmatically, e.g. from the Application Context. Is this possible?
After looking through the jax-rs jar, I found some code in JaxRsInInterceptor.class that pointed me in the right direction: essentially you can get the JaxRsServerFactoryBean from the application context (or inject it), and then:
List<ClassResourceInfo> cris = jaxrsServerFactoryBean.getServiceFactory().getClassResourceInfo();
Gives you a list of all service beans.

Spring MVC - How can I use different timeouts for my resttemplates?

I am using Spring MVC with Spring 3.1. I have a web application that uses many REST services. One of these REST services takes up to an hour to respond - which I can not change. I have my timeout for the RestTemplate set up like this with the timeout set to 60 minutes:
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate ">
<constructor-arg>
<bean class="org.springframework.http.client.CommonsClientHttpRequestFactory">
<property name="readTimeout" value="3600000" />
<property name="connectTimeout" value="3600000" />
</bean>
</constructor-arg>
</bean>
I would like to be able to set all of my other REST calls to a different set of timeouts. Any ideas on how to do this?
Thanks,
Tim
You can't do this on a method call basis. In other words, all calls on the restTemplate bean will use the same underlying ClientHttpRequestFactory. If you want different requests to use different timeout values, declare multiple RestTemplate beans and inject the appropriate ones in your beans.

Spring: how to dynamically create multiple beans from single template definition

I have the following Spring bean for a remote web service defined in xml:
<bean id="authWSTemplate" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean" abstract="true">
<property name="serviceInterface" value="com.example.webservices.Authentication" />
<property name="wsdlDocumentUrl" value="${ws.root}/authentication?wsdl" />
<property name="namespaceUri" value="http://security.webservices.example.com/" />
<property name="serviceName" value="AuthenticationWebService" />
<property name="portName" value="AuthenticationPort" />
<property name="maintainSession" value="true" />
</bean>
How do I obtain this bean template and create a concrete bean (i.e. supply the root property)? Can I then put the concrete bean into the Spring container?
I need numerous concrete beans pointing to different systems, so I have different root values. For this example, say there are 2 systems with roots: http://domain1.com:8001/ws and http://domain2.com:8002/ws.
Therefore I'd want 2 beans called "authWSdom1" and "authWSdom2".
I'm expecting to do this programmatically in an application initialisation block, where I'd retrieve a list of all known system implementations (this info is only known at runtime), and create a bean for each impl, cache the bean name, then my application will retrieve the appropriate bean from the Spring container when required.
Or, is there a better pattern for this? Perhaps by providing the root value in a constructor for the bean?
I'm thinking I cannot have a single bean in Spring as I need to support concurrent access across multiple end points (i.e. multiple users hitting domain1 and domain2 at the same time).
Create custom bean that implements BeanFactoryPostProcessor and InitializingBean.
Use postProcessBeanFactory method to create bean:
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
String wsdlDocumentUrl = ....;
// .......
registry.registerBeanDefinition(YOUR_BEAN_NAME, BeanDefinitionBuilder.childBeanDefinition(
getParentNoDomainServicBeanName(authWSTemplate)).addPropertyReference(
"wsdlDocumentUrl", wsdlDocumentUrl).getBeanDefinition());
}
While I believe that Ragnor's answer is suitable if you want to dynamically create the bean in the spring container, I decided to use spring to define my own WSTemplate DTO then use a factory class to use this DTO and programmatically build (root url provided at runtime and DTO suffix value added to it) and cache the resulting JaxWS ProxyBean:
<bean id="authWSTemplate" class="com.example.WSProxyTemplate">
<property name="serviceInterface" value="com.example.webservices.Authentication" />
<property name="wsdlDocumentUrlSuffix" value="/authentication?wsdl" />
<property name="namespaceUri" value="http://security.webservices.example.com/" />
<property name="serviceName" value="AuthenticationWebService" />
<property name="portName" value="AuthenticationPort" />
<property name="maintainSession" value="true" />
</bean>
I like this approach as my spring config is abstracted away from the actual WS bean used. I.e. if I wanted to use something other that JaxWS, then I'd simply write a different factory which used the same DTO beans. Again, this would help if I have to choose the WS implementation at runtime depending upon some system/env criteria.

How can I inject a property value into an annotation configured spring mvc 3.0 controller

First: I'm using Spring 3.0
I have a problem when configuring my controller class. The controller uses a web service which I want to define the endpoint address using a .properties file.
#Controller
public class SupportController {
#Value("#{url.webservice}")
private String wsEndpoint;
...
In my application context xml-file, I've defined this:
<context:property-placeholder location="/WEB-INF/*.properties" />
I've been reading the documentation, trying different approaches (like adding prefix systemProperties.),but I keep getting an error message telling me that it doesn't exist.
Field or property 'url' cannot be
found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext'
Ok. I've figured it out.
Now, in the controller:
#Value("#{settings['url.webservice']")
Then in the context configuration I have this "helper bean":
<util:properties id="settings"
location="/WEB-INF/supportweb.properties"></util:properties>
This should work, too:
#Value("${url.webservice}")
private String wsEndpoint;
I have this configuration and it works fine:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:application.properties</value>
</list>
</property>
</bean>
and I iniejct the property in this way
#Value("${root.log.level}")
private String prop;
the field is correctly initialized to "DEBUG" value.
you should check that the
<context:property-placeholder location="/WEB-INF/*.properties" />
is defined in webmvc-config.xml where you create instances of the #Controllers

Categories

Resources