I am trying to figure out the best way to move the following bit of code into a spring .xml configuration file: (force async and disable chunkng so NTLM works)
final WSSoap port = new WS().getWSSoap();
final Client client = ClientProxy.getClient(port);
final HTTPConduit httpConduit = (HTTPConduit) client.getConduit();
final HTTPClientPolicy httpClientPolicy = httpConduit.getClient();
httpClientPolicy.setAllowChunking(false);
httpClientPolicy.setAutoRedirect(true);
final BindingProvider bindingProvider = (BindingProvider) port;
final Map<String, Object> requestContext = bindingProvider.getRequestContext();
final Credentials credentials = new NTCredentials("username", "password", "workstation", "domain");
requestContext.put(Credentials.class.getName(), credentials);
requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://www.example.com/");
requestContext.put(AsyncHTTPConduit.USE_ASYNC, Boolean.TRUE);
I've looked over the CXF configuration page (here: http://cxf.apache.org/docs/configuration.html), but I don't see any way to do what I need.
Is there a clean way to handle NTLM authentication for CXF using spring?
Update: I've figured out how to force an async conduit, using the following:
<cxf:bus name="asyncBus">
<cxf:properties>
<entry key="use.async.http.conduit" value="true"/>
</cxf:properties>
</cxf:bus>
<http-conf:conduit name="{http://www.webserviceX.NET}GlobalWeatherSoapPort.http-conduit">
<http-conf:client AllowChunking="false" Connection="Keep-Alive"/>
</http-conf:conduit>
<jaxws:client id="weatherClient" bus="asyncBus"
address="http://www.webservicex.com/globalweather.asmx"
serviceClass="net.webservicex.GlobalWeatherSoap"/>
However I am still having trouble accessing the request context so I can add my NTLM credentials.
I wanted to answer my own question. After many, many hours debugging and stepping through Apache CXF code, I have found a solution. The following spring configuration will enable NTLM authentication over an async conduit:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:cxf="http://cxf.apache.org/core"
xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd">
<!--
~
~ create an asynchronous-only bus for NTLM requests
~
-->
<cxf:bus name="asyncBus">
<cxf:properties>
<entry key="use.async.http.conduit" value="true"/>
</cxf:properties>
</cxf:bus>
<!--
~
~ configure conduit for NTLM request
~
-->
<http-conf:conduit name="{http://www.webserviceX.NET}GlobalWeatherSoapPort.http-conduit">
<http-conf:client AllowChunking="false" AutoRedirect="true" Connection="Keep-Alive"/>
</http-conf:conduit>
<!--
~
~ create service stub
~
-->
<jaxws:client id="weatherClient" bus="asyncBus"
address="http://www.webservicex.com/globalweather.asmx"
serviceClass="net.webservicex.GlobalWeatherSoap">
<jaxws:properties>
<entry key="org.apache.http.auth.Credentials">
<bean class="org.apache.http.auth.NTCredentials">
<constructor-arg value="DOMAIN/USER:PASSWORD"/>
</bean>
</entry>
</jaxws:properties>
</jaxws:client>
</beans>
It is also possible to specify the username, password, domain, and workstation in the NTCredentials constructor, if necessary.
Related
In my application, I am consuming a third party web-service that is provided by my client.
I have developed my application on Spring and Hibernate framework and in one module I am consuming this third party web-service url. I have generated web-service stubs using
javab2-maven-plugin
The maven plugin in declared as below in my pom.xml file :
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- Package to store the generated file -->
<packageName>com.equifax.unsolicited.wsdl.stub</packageName>
<!-- Treat the input as WSDL -->
<wsdl>true</wsdl>
<!-- Input is not XML schema -->
<xmlschema>false</xmlschema>
<!-- The WSDL file that you saved earlier -->
<schemaFiles>Duk_CIS_Send_CreditStatus.wsdl</schemaFiles>
<!-- The location of the WSDL file -->
<schemaDirectory>${project.basedir}/src/main/wsdl</schemaDirectory>
<!-- The output directory to store the generated Java files -->
<outputDirectory>${project.basedir}/src/main/java</outputDirectory>
<!-- Don't clear output directory on each run -->
<clearOutputDir>false</clearOutputDir>
</configuration>
</plugin>
And I am using the auto-generated JAXB java classes to call the web service. I have created a service bean which call the web service :
#Service("unsolicitResponseService")
public class UnsolicitResponseServiceImpl implements UnsolicitResponseService{
private static final Logger LOGGER = Logger.getLogger(UnsolicitResponseServiceImpl.class);
#Autowired
private WebServiceTemplate webServiceTemplate;
#Override
public void sendUnsolicitResponse() {
LOGGER.debug("Calling Duke Web Service to Send Unsolicit Response ... ");
try{
ObjectFactory objecFactory = new ObjectFactory();
CreditStatusMsgType creditStatusMessage = objecFactory.createCreditStatusMsgType();
creditStatusMessage.setMessageHeader(createMessageHeader(objecFactory));
//WRAP THE CLASS AS THE INSTANCE OF JAXBELEMENT OTHERWISE IT WILL THROW MISSING ROOTELEMENT ERROR
JAXBElement<CreditStatusMsgType> creditStatusMessageJaxbElement = objecFactory.createSendCreditStatus(creditStatusMessage);
//CREATE STRING WRITER TO LOG THE REQUEST
Object response = this.webServiceTemplate.marshalSendAndReceive(creditStatusMessageJaxbElement);
LOGGER.debug("Jumio Web Service Response Reponse :"+response);
LOGGER.debug("Unsolicit Response sent to Duke Successfully.");
}catch(Exception ex){
LOGGER.error("Exception generated while calling Web Service to send unsolicit Response : "+ex.getLocalizedMessage(),ex);
}
}
Below is the xml configuration where I have declared interceptors to log the request and response :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sws="http://www.springframework.org/schema/web-services"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:oxm="http://www.springframework.org/schema/oxm"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/web-services
http://www.springframework.org/schema/web-services/web-services-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- DEFINE SOAP VERSION USED BY A WSDL -->
<bean id="soapMessageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
<property name="soapVersion">
<!-- FOR TEXT/XML -->
<util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_11"/>
</property>
</bean>
<!-- LOCATION OF THE GENERATED JAVA FILEs -->
<oxm:jaxb2-marshaller id="marshaller" contextPath="com.equifax.unsolicited.wsdl.stub"/>
<!-- CONFIGURE THE SPRING WEB SERVICE -->
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="soapMessageFactory"/> <property name="marshaller" ref="marshaller"/>
<property name="unmarshaller" ref="marshaller"/>
<property name="defaultUri" value="https://partnerstg.duke-energy.com:4443/DukCISSendCreditStatus?wsdl"/>
</bean>
<sws:interceptors>
<bean id="jumioPeyLoadLoggingInterceptor" class="com.test.datasource.logging.interceptor.PayloadLoggingInterceptor">
</bean>
<bean id="jumioSOAPLoggingInterceptor" class="com.test.datasource.logging.interceptor.SOAPLoggingInterceptor">
</bean>
</sws:interceptors>
</beans>
And I also have added and new logging category to enable the logger level to DEBUG mode :
Above code is calling the web service successfully. But the interceptors are not getting called. So I am not able to log the XML request and response.
Here, I am assuming that, these interceptors will not work while consuming the service. Let me know if I am wrong here.
I am referring Spring Web Service from HERE . This website has given explanation interceptors while publishing a web-service.
Kindly let me know should we use this interceptors while consuming a web-service ? Or How should I print request and response which are JAXB-ELEMENT ?
I am adding here solution which I have implemented. There are two ways by which we can implement this solution. I have implemented the second one from below list using JAXBContext and Marshaller.
1> Log Request/Response By interceptor.
We can not use PayloadLoggingInterceptor or SOAPLoggingInterceptor when we are consuming the web service.
We need to use ClientInterceptor when we are consuming the web service. ClientInterceptor is implemented by PayloadValidatingInterceptor class which is used to intercept the request/response and validate the it based on xsd schema.
For that we need to provide interceptor reference as below :
<bean id="MyPayloadValidatingInterceptor" class="com.equifax.ic.datasource.jumio.ws.logging.interceptor.JumioPayloadValidatingInterceptor">
<property name="schema" value="file:WebContent/WEB-INF/schemas/account-balance-service.xsd" />
<property name="validateRequest" value="false" />
<property name="validateResponse" value="false" />
</bean>
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="soapMessageFactory"/> <property name="marshaller" ref="marshaller"/>
<property name="unmarshaller" ref="marshaller"/>
<property name="defaultUri" value="https://partnerstg.duke-energy.com:4443/DukCISSendCreditStatus?wsdl"/>
<property name="interceptors">
<list>
<ref bean="MyPayloadValidatingInterceptor"/>
</list>
</property>
</bean>
2> Log Request/Response by using JAXBContext
This is the solution which I have implemented in my application as we should not use PayloadValidatingInterceptor only to log reqeust/response.
private void logJAXBRequest(JAXBElement<CreditStatusMsgType> creditStatusMessageJaxbElement){
LOGGER.debug("Logging Web Service Request ...");
StringWriter writer = null;
StreamResult streamResult = null;
StringBuffer buffer = null;
try{
writer = new StringWriter();
streamResult = new StreamResult(writer);
JAXBContext jaxbContext = JAXBContext.newInstance(CreditStatusMsgType.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.marshal(creditStatusMessageJaxbElement, streamResult);
buffer = writer.getBuffer();
LOGGER.debug("JAXB Webservice Request : "+ buffer.toString());
writer.close();
}catch(Exception ex){
LOGGER.error("Exception generated while creating XML Logs of JAXB Request :",ex);
}
}
He everyone, colleagues.
There are two main ways to show XML requests / responses:
First of all you have to add log4j dependency into your pom.xml file:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
Then you have to place log4j.properties file into a classpath of your application. When I develop SOAP services I often use Spring WS Maven artefact. Unfortunately, a usual resources folder is not created from scratch and you have to create it manually. Then you place log4j.properties file there. The contents of log4j config depends on the approach you want to use (see items below). Obtained structure is following:
Use a standard Message Logging and Tracing approach & log4j.properties file. Nothing should be configured, developed, written except log4j config file contents. The contents of log4j config should be the following (use these contents as is):
log4j.rootCategory=DEBUG, stdout
log4j.logger.org.springframework.ws.client.MessageTracing.sent=TRACE
log4j.logger.org.springframework.ws.client.MessageTracing.received=DEBUG
log4j.logger.org.springframework.ws.server.MessageTracing=DEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%p [%c{3}] %m%n
Use a PayloadLoggingInterceptor & log4j.properties file. Some config changes should be applied, but this approach is more flexible, as for me. First of all you have to add PayloadLoggingInterceptor into a MessageDispatcherServlet config file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:sws="http://www.springframework.org/schema/web-services" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.ln.springws"/>
<sws:annotation-driven/>
<sws:interceptors>
<bean class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor" />
</sws:interceptors>
<sws:dynamic-wsdl id="holiday" portTypeName="HumanResource" locationUri="http://localhost:8080/holidayService/" targetNamespace="http://spring-ws-holidays.com/hr/definitions">
<sws:xsd location="/WEB-INF/hr.xsd"/>
</sws:dynamic-wsdl>
</beans>
And at last place the following contents to log4j.properties file:
log4j.rootLogger=debug, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-5p [%c] - <%m>%n
And as a result of both approaches you will have something like that in a console:
How do I add the authentication token created by Neo4j Server to Spring Neo4j Rest configuration
context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<import resource="spring-data-context.xml" />
<bean id="graphDatabaseService"
class="org.springframework.data.neo4j.rest.SpringRestGraphDatabase">
<constructor-arg index="0" value="http://localhost:7474/db/data" />
</bean>
</beans>
As per the SpringRestGraphDatabase class, there are two more parameters which can be passed into Constructor which are username and password.
Here is how you should configure it.
<bean id="graphDatabaseService" class="org.springframework.data.neo4j.rest.SpringRestGraphDatabase">
<constructor-arg value="http://localhost:7474/db/data"/>
<constructor-arg name="user" value="neo4j"/>
<constructor-arg name="password" value="******"/>
</bean>
Ended using Jersey Client's HttpBasicAuthFilter
Your parameters should be something like:
public static final String DATABASE_ENDPOINT = "http://localhost:7474/db/data";
public static final String DATABASE_USERNAME = "neo4j";
public static final String DATABASE_PASSWORD = "3c0a0a6ea1sdsdsdsdsdsdsdsdf2a94d";
private String callRest(String query) {
final String cypherUrl = ENDPOINT + "/cypher";
Client c = Client.create();
c.addFilter(new HTTPBasicAuthFilter(USERNAME, PASSWORD));
WebResource resource = c.resource(cypherUrl);
String request = "{\"query\":\"" + query + "\"}";
ClientResponse response = resource.accept(MediaType.APPLICATION_JSON)
.type(MediaType.APPLICATION_JSON).entity(request)
.post(ClientResponse.class);
String object = response.getEntity(String.class);
response.close();
return object;
}
Latest Jersey client can be found by adding this to your mvn pom if its not already in your dependency tree.
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.18.3</version>
</dependency>
I have a REST API. I'm making a client.
I configured spring security to authentication by my rest service.
My REST API controller
#RequestMapping(value = "/login", method = RequestMethod.POST, headers="content-type=application/json")
public #ResponseBody
UserDetails loginUser(WebRequest request)
throws LoginOrPasswordException {
logger.info("login user");
logger.info(request);
String username = request.getParameter("username");
logger.info(username);
UserDetails uDetails = userRepository.login(username);
System.out.println(uDetails.getPassword());
return uDetails;
}
Application context of API
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="com.zayats." />
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
</list>
</property>
</bean>
<!-- Http Json MessageConverter -->
<bean id="jsonConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
</bean>
<import resource="jdbc-config.xml" />
Next is client method with restTemplate
HashMap<String, String> params = new HashMap<String, String>();
params.put("username", username);
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<?> httpEntity = new HttpEntity<Object>(params, requestHeaders);
logger.info("Create map and doing request.");
UserDetails matchingUser = restTemplate.postForObject(
"http://localhost:8080/ApiFamilyShoplist/user/login", httpEntity,
UserDetails.class);
Rest Template config
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<list>
<bean id="jsonConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
</bean>
</list>
</property>
</bean>
When I call my API with postForObject in controller of API doesn't receive any parameters.
Please, give me some advice how to make it to send data to API.
Thanks.
You need to have another parameter in your method to accept the string parameter and annotate it with #RequestBody (inside the method signature):
#ResponseBody
#Consumes("text/plain")
public UserDetails loginUser(WebRequest request, #RequestBody String userName)
Also, if you're passing a string, I suggest to add a simple http string converter to the converters of the rest template and annotate the server method with #Consumes(text/plain). This way you'll get it as a simple string.
I am writing a RESTful service (using CXF on JBoss) in which I have inject another class using Spring (Autowired). But the class is not getting injected and is null.
Web Service Interface and Class (Where injection needs to happen)
package com.company.project.web;
#Path("/myws")
public interface IMyWebService {
#POST
#Path("/doSomething")
#Consumes("application/json")
#Produces("application/json")
MyResponse doSomething(MyRequest myRequest)
}
#Service("myWebService")
public class MyWebService implements IMyWebService {
#Autowired
private IMyCore myCore;
public MyResponse doSomething(MyRequest myRequest) {
....
}
}
That which has to be injected
package com.company.project.biz;
public interface IMyCore {
MyResponse doSomething(MyRequest myRequest);
}
#Component("myCore")
public class MyCore implements IMyCore {
public MyResponse doSomething(MyRequest myRequest) {
.....
}
}
Beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-http.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<context:annotation-config />
<context:component-scan base-package="com.company.project"/>
<jaxrs:server id="myWebService" address="/">
<jaxrs:serviceBeans>
<bean class="com.company.project.web.MyWebService" />
</jaxrs:serviceBeans>
<jaxrs:extensionMappings>
<entry key="json" value="application/json" />
</jaxrs:extensionMappings>
</jaxrs:server>
</beans>
My service is active (http://localhost:8080/{warname}/myws/doSomething) but the MyCore instance is not being injected into MyWebService (in the myCore field). It is always null and my service does not work as expected, instead throws NullPointerException
Tried all inputs gathered over google. No luck! Your help is highly appreciated.
Regards
Try to add below method to your web service:
#PostConstruct
public void init() {
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
The current web application context (usually the one loaded by ContextLoaderListener) will be used for autowiring, so the IMyCore bean has to be defined in the context listener configuration file and not in the web service one.
If you want to use Spring Beans in CXF Web Service class, then declare WebService as following in the XML configuration file of the CXF (e.g. spring-cxf.xml)
<bean id="hello" class="demo.spring.service.HelloWorldImpl" />
<jaxws:endpoint id="helloWorld" implementor="#hello" address="/HelloWorld" />
Declare separated bean for the WebService class and then put it in the endpoint with an ID. Like this you will have spring managed bean, where you can use AutoWired annotations as well.
Your beans never won't be injected automatically if you will declare your web service as following.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<jaxws:endpoint id="helloWorld" implementor="demo.spring.service.HelloWorldImpl" address="/HelloWorld"/>
In this case you will need either:
Inject spring beans manually
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
Or retrieve the beans one by one from the spring context
ApplicationContext context = ...; // your Spring ApplicationContext
HelloBean helloBean = (HelloBean) context.getBean("bean");
I haven't tried this for JAX-RS, but the approach in my opinion should be the same.
From CXF official documentation.
Try to add below bean configuration at Beans.xml
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
In my case, it worked..
I am using a spring-ws client to invoke a web service in two way ssl mode. I need to make sure that I don't end up creating a new connection everytime - instead I re-use connections.
I did some re-search and found that by default HTTP 1.1 always makes persistent http(s) connections. Is that true?
Do I need any piece of code in my client to ensure connections are persistent? How can I check if the connections are persistent or if a new connection is being created vereytime I send a new request ?
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oxm="http://www.springframework.org/schema/oxm"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd">
<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="marshaller" ref="jaxb2Marshaller" />
<property name="unmarshaller" ref="jaxb2Marshaller" />
<property name="messageSender" ref="httpSender" />
</bean>
<bean id="httpSender" class="org.springframework.ws.transport.http.CommonsHttpMessageSender">
</bean>
<oxm:jaxb2-marshaller id="jaxb2Marshaller" contextPath="com.nordstrom.direct.oms.webservices.addressval" />
<bean id="Client" class="test.ClientStub">
<property name="webServiceTemplate" ref="webServiceTemplate" />
</bean>
</beans>
HTTP/1.1 has connection keep-alive but the server can decide to close it after a number of requests or does not support keep-alive
The easiest way to check is to use tcpdump or wireshark and check for SYN [S] flags. Thats new connections.
I am using the following and on J2SE 1.6 jdk it did not create any new sockets across multiple requests. The server did not send the Connection: Keep-Alive header but connections were kept alive anyway.
Bean configuration:
<bean id="wsHttpClient" factory-bean="customHttpClient"
factory-method="getHttpClient" />
<bean id="messageSender"
class="org.springframework.ws.transport.http.CommonsHttpMessageSender"
p:httpClient-ref="wsHttpClient" />
Java Code:
import org.apache.commons.httpclient.*;
import org.springframework.stereotype.*;
#Component public class CustomHttpClient {
private final HttpClient httpClient;
public CustomHttpClient() {
httpClient = new HttpClient(new MultiThreadedHttpConnectionManager());
httpClient.getParams().setParameter("http.protocol.content-charset",
"UTF-8");
httpClient.getHttpConnectionManager().getParams()
.setConnectionTimeout(60000);
httpClient.getHttpConnectionManager().getParams().setSoTimeout(60000);
httpClient.setHostConfiguration(new HostConfiguration());
}
public HttpClient getHttpClient() {
return httpClient;
}
}