-->

PropertyAccessException in Apache camel Spring Ws

2019-09-08 16:03发布

问题:

I want to configure Spring-ws Connection Manager to use PoolingHttpClientConnectionManager. here is my configuration

camel-context.xml

<camel-context>
    <route>
        <from uri="direct:sampleCall"/>
        <to uri="bean:sampleCommand"/>
        <to uri="spring-ws:http://{{sample.uri}}?timeout={{sample.timeout}}&amp;messageSender=#messageSender&amp;soapAction=urn:MidwareWebServiceIntf-MidwareWebService#sampleCommand"/>
        <to uri="bean:xmlProcessor"/>
        <to uri="bean:validateResponse"/>
    </route>

    <route>
        <from uri="direct:anotherSampleCall"/>
        <to uri="bean:anotherSampleCommand"/>
        <to uri="spring-ws:http://{{anotherSample.uri}}?timeout={{anotherSample.timeout}}&amp;messageSender=#messageSender&amp;soapAction=urn:MidwareWebServiceIntf-MidwareWebService#ExecuteCommand"/>
        <to uri="bean:trimResponse"/>
        <to uri="bean:xmlProcessorTrim"/>
        <to uri="bean:validateResponse"/>
    </route>



</camelContext>



<bean id="messageSender" class="org.springframework.ws.transport.http.HttpComponentsMessageSender">
    <property name="httpClient" ref="httpClient"/>
    <property name="readTimeout" value="30000"/>
    <property name="connectionTimeout" value="30000"/>
</bean>


<bean id="requestConfigBuilder" class="org.apache.http.client.config.RequestConfig"
      factory-method="custom">
    <property name="socketTimeout" value="30000" />
    <property name="connectTimeout" value="30000" />
</bean>

<bean id="requestConfig" factory-bean="requestConfigBuilder" factory-method="build" />

<bean id="poolingConnectionManager" class="org.apache.http.impl.conn.PoolingHttpClientConnectionManager">
    <property name="defaultMaxPerRoute" value="20"/>
    <property name="maxTotal" value="20"/>
</bean>

<bean id="httpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder"
      factory-method="create">
    <property name="defaultRequestConfig" ref="requestConfig" />
    <property name="connectionManager" ref="poolingConnectionManager"/>
</bean>



<bean id="httpClient" factory-bean="httpClientBuilder" factory-method="build" />

But when i run the project i get the following exception

org.springframework.beans.factory.BeanCreationException: Error creating bean     with name 'messageSender' defined in class path resource [camel-context.xml]
: Error setting property values; nested exception is   org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (2) are:
PropertyAccessException 1:  org.springframework.beans.MethodInvocationException: Property 'readTimeout'  threw exception; nested exception is java.lang.Uns
upportedOperationException
PropertyAccessException 2:  org.springframework.beans.MethodInvocationException: Property 'connectionTimeout' threw exception; nested exception is java.la
ng.UnsupportedOperationException
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1506)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:762)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4751)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5175)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:724)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:700)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:714)
    at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:919)
    at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1704)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.PropertyBatchUpdateException; nested   PropertyAccessExceptions (2) are:
PropertyAccessException 1:    org.springframework.beans.MethodInvocationException: Property 'readTimeout'    threw exception; nested exception is java.lang.Uns
upportedOperationException
PropertyAccessException 2:  org.springframework.beans.MethodInvocationException:  Property 'connectionTimeout' threw exception; nested exception is java.la
ng.UnsupportedOperationException
    at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:121)
    at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:75)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1502)
    ... 26 more
15-Mar-2016 11:28:47.846 SEVERE [localhost-startStop-1]   org.apache.catalina.core.StandardContext.startInternal Error listenerStart
15-Mar-2016 11:28:47.847 SEVERE [localhost-startStop-1]       org.apache.catalina.core.StandardContext.startInternal Context [/camel##2.0.0]   startup failed due
to previous errors

Is this related to incompatible API Version that i use together?

回答1:

thanks to @smarquis for very helpful answer I finally can configure Spring-Ws Connection Manager Correctly. here is correct configuration. don't forget to use interceptedHttpClientBuilder part. without it you encountered with this exception : org.apache.http.ProtocolException: Content-Length header already present (see this thread for more information)

camel-context

<camel-context>
    <route>
        <from uri="direct:sampleCall"/>
        <to uri="bean:sampleCommand"/>
        <to uri="spring-ws:http://{{sample.uri}}?messageSender=#messageSender&amp;soapAction=urn:MidwareWebServiceIntf-MidwareWebService#ExecuteCommand"/>
        <to uri="bean:trimResponse"/>
        <to uri="bean:xmlProcessorTrim"/>
        <to uri="bean:validateResponse"/>
    </route>

</camelContext>

<bean id="messageSender" class="org.springframework.ws.transport.http.HttpComponentsMessageSender">
    <constructor-arg index="0" type="org.apache.http.client.HttpClient" ref="httpClient"/>
</bean>


<bean id="requestConfigBuilder" class="org.apache.http.client.config.RequestConfig"
      factory-method="custom">
    <property name="socketTimeout" value="${bank.webservice.timeout}" />
    <property name="connectTimeout" value="${bank.webservice.timeout}" />
</bean>

<bean id="requestConfig" factory-bean="requestConfigBuilder" factory-method="build" />

<bean id="poolingConnectionManager" class="org.apache.http.impl.conn.PoolingHttpClientConnectionManager">
    <property name="defaultMaxPerRoute" value="20"/>
    <property name="maxTotal" value="20"/>
</bean>



<bean id="interceptedHttpClientBuilder" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject" ref="httpClientBuilder" />
    <property name="targetMethod" value="addInterceptorFirst"> </property>
    <property name="arguments">
        <list>
            <bean class="org.springframework.ws.transport.http.HttpComponentsMessageSender.RemoveSoapHeadersInterceptor"/>
        </list>
    </property>
</bean>


<bean id="httpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder"
      factory-method="create">
    <property name="defaultRequestConfig" ref="requestConfig" />
    <property name="connectionManager" ref="poolingConnectionManager"/>
</bean>



<bean id="httpClient" factory-bean="interceptedHttpClientBuilder" factory-method="build" />


回答2:

Yes, HttpClient.getParams() has been deprecated and now throws UnsupportedOperationException.

The methods setReadTimeout() and setConnectionTimeout() of HttpComponentsMessageSender do nothing more as setting these values on the underlying HttpClient.

So you have to rely on the requestConfigBuilder (as you already do for socketTimeout) to configure the HttpClient directly.