I have a SOAP webservice endpoint url(let's say :"EP1") which we can connect only through a proxy server.
We are using org.springframework.ws.client.core.WebServiceTemplate class to consume webservices.
My question is, Is there a way that I can pass/set the proxy server details on WebServiceTemplate to connect to endpoint url "EP1"?
You can specify custom HttpClient via HttpComponentsMessageSender when constructing the WebServiceTemplate. You can then pass default request config which includes the proxy to the client. Something like this should work:
RequestConfig config = RequestConfig
.custom()
.setProxy(new HttpHost("host"))
.build();
CloseableHttpClient client = HttpClients
.custom()
.setDefaultRequestConfig(config)
.build();
HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender(client);
WebServiceTemplate wsTemplate = new WebServiceTemplate();
wsTemplate.setMessageSender(messageSender);
// Set other required properties ...
You might need to set other properties on the WebServiceTemplate object or the HttpClient depending on your needs so on. But this should demonstrate the basic concept.
Also take a look at this sample illustrating the usage of proxies in Apache HTTP client.
You must use VM arguments: -Dhttp.proxyHost=mydomain.com -Dhttp.proxyPort=8080
Having in mind that this setting applies to all HTTP requests made from Java.
Related
I'm using Spring 4 RestTemplate to do some server-side API calls.
The RestTemplate instance is a custom one (not Spring Boot default) using Apache HttpClient created as follows:
PoolingHttpClientConnectionManager cm;
...
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(cm)
.build();
Some of the API calls use HTTP Basic Authentication and thus need to have an Authorization header. I'm adding this on a RequestEntity and then performing an exchange() call on the RestTemplate and this works fine.
RequestEntity<Void> requestEntity;
requestEntity = RequestEntity.get(uri)
.accept(MediaType.valueOf("application/repository.folder+json"))
.acceptCharset(UTF_8)
.header("Accept-Encoding", "")
.header("Authorization", apiBasicAuthHeader())
.build();
Some other API calls (to the same backend server) should not use HTTP Basic Authentication and instead use a pre-authenticated token supplied as a request parameter.
RequestEntity<Void> requestEntity = RequestEntity.get(uriWithToken)
.accept(APPLICATION_JSON)
.acceptCharset(UTF_8)
.header("Accept-Encoding", "")
.build();
operations.exchange(requestEntity, ResourceLookupResults.class)
This also works fine by itself.
However, if I do an API call using the Authorization header first and then try to do one with the pre-authenticated token (with the same RestTemplate), it seems that the Authorization header is still sent on the 2nd request. I'd expect the header added to the RequestEntity to be added only for that specific request and not for subsequent requests that don't need it. Why is this and what is the best way to avoid this (like using separate RestTemplate instances)?
I'm working on an application where I have to consume a SOAP webservice and convert it to Rest based webservices. I followed the tutorial from Spring team and was capable to generate pojos, but when I try to make the call using the webServiceTemplate I have an error that the host is not recognized which is basically because I'm behind a proxy in our company.
The technology stack I'm using is Spring boot with web module and spring-ws-core, and I would like to know how to set up my proxy data in the webServiceTemplate.
Thanks
Try to setup the template according this answer.
Afterwards you should be able to set it within your class extending WebServiceGatewaySupport using
setWebServiceTemplate(WebServiceTemplate webServiceTemplate)
After a lot of research, I came up with a programmatic solution. Once you defined your SOAP client that will extend WebServiceGatewaySupport class, I created a configuration class (annotated with #configuration that will declare a bean of my SOAP client. In this method, I used the following code to setup my proxy information and thus I was able to consume my web service:
#Bean
public CommerceSoapClient commerceSoapClient(Jaxb2Marshaller marshaller) {
CommerceSoapClient commerceService = new CommerceSoapClient();
//Setup proxy
HttpClientBuilder builder = HttpClientBuilder.create();
builder.addInterceptorFirst(new HttpComponentsMessageSender.RemoveSoapHeadersInterceptor());
HttpHost proxy = new HttpHost("127.0.0.1", 8080);
builder.setProxy(proxy);
CloseableHttpClient httpClient = builder.build();
HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender(httpClient);
WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
webServiceTemplate.setMessageSender(messageSender);
webServiceTemplate.setDefaultUri("http://your webservice address path");
webServiceTemplate.setUnmarshaller(marshaller);
webServiceTemplate.setMarshaller(marshaller);
commerceService.setDefaultUri("https://your webservice address path");
commerceService.setWebServiceTemplate(webServiceTemplate);
return commerceService;
}
I am trying to access sample Rest method using Webtarget code in Websphere Liberty profile deployed as war and getting following exception.
[WARNING ] Interceptor for {https://www.google.com}WebClient has thrown exception, unwinding now
Could not send Message.
Its working when directly run with java main method.
#GET
#Produces("text/plain")
#Path("/hello")
public Response healthCheck() {
ClientConfig configuration = new ClientConfig();
configuration = configuration.property(ClientProperties.CONNECT_TIMEOUT, 30000);
configuration = configuration.property(ClientProperties.READ_TIMEOUT, 30000);
configuration = configuration.property(ClientProperties.PROXY_URI, "http://xxx.xxx.com:8080");
configuration.connectorProvider(new ApacheConnectorProvider());
Client client = ClientBuilder.newClient(configuration);
WebTarget target = client.target(
"https://www.google.com");
String content = target.request().get(String.class);
System.out.println(content);
}
Any help is appreciated? Its simple task but taking lot of time.
The ClientConfig and ClientProperties types are specific to Jersey. While you might have them in your application, they will almost certain conflict with WebSphere's JAX-RS implementation based on CXF. If you post the full logs, I may be able to confirm that.
Try using the JAX-RS spec API types instead of the Jersey types - and use the IBM properties (unfortunately, these properties are not portable) like this:
#GET
#Produces("text/plain")
#Path("/hello")
public Response healthCheck() {
Client client = ClientBuilder.newBuilder()
.property("com.ibm.ws.jaxrs.client.connection.timeout", 30000)
.property("com.ibm.ws.jaxrs.client.receive.timeout", 30000)
.property("com.ibm.ws.jaxrs.client.proxy.host", "xxx.xxx.com")
.property("com.ibm.ws.jaxrs.client.proxy.port", "8080")
.build();
WebTarget target = client.target(
"https://www.google.com");
String content = target.request().get(String.class);
System.out.println(content);
return Response.ok(content).build();
}
Hope this helps, Andy
I developped a spring-boot application. When I need to do REST requests (POST, PUT...) I use every time basic authentication like that
HttpEntity<PostJql> httpEntity = new HttpEntity<PostJql>(post, jiraUtils.getHeader());
ResponseEntity<IssueDataWrapper> response = restTemplate.exchange(urlJiraResponse, HttpMethod.POST, httpEntity, IssueDataWrapper.class);
Is there another way to do basic authentication once time in the application and then use RestTemplate or httpPost {Put/Delete...} without basic authentication ?
Best regards
Yes. Configure your RestTemplate with a ClientHttpRequestFactory that does what you need.
You can just set it in the constructor:
restTemplate = new RestTemplate(requestFactory);
... or you can make all of these things beans and let Spring wire it.
You could extend SimpleClientHttpRequestFactory, overriding createRequest():
public class BasicAuthSimpleClientHttpRequestFactory
extends SimpleClientHttpRequestFactory {
#Override
public HttpClientRequest createRequest(URI uri, HttpMethod httpMethod) {
HttpClientRequest request = super.createRequest(uri, httpMethod);
HttpHeaders headers = request.getHeaders();
headers.add(... your auth header ...);
return request;
}
}
... or you could bring in Apache HttpComponents as a dependency and use an HttpComponentsClientHttpRequestFactory, and configure the underlying Apache HttpClient to do the authentication you need. Apache documents this in detail, but to get you started:
BasicCredentialsProvider credentialsProvider =
new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials("user", "password"));
HttpClient client = HttpClientBuilder.create()
.setDefaultCredentialsProvider(credentialsProvider)
.build();
RestTemplate restTemplate = new RestTemplate(
new HttpComponentsClientHttpRequestFactory(client));
In my experience it's worth bringing in Apache HttpComponents if you can -- it is more reliable and configurable than the HttpUrlConnection based HTTP client that RestTemplate otherwise uses by default. When your requirements broaden to things like other authentication methods, timeouts, retry strategies etc., you'll be glad you have an HttpClient to configure.
I have written simple REST web service client class which uses the JAX-RS 2.0 client API to make REST requests. I am trying to figure out how to set a request timeout for each invocation. Here is the code for a request:
Client client = ClientBuilder.newBuilder().build();
WebTarget resourceTarget = client.target(restServiceUrl)
.path("{regsysID}/{appointmentID}/")
.resolveTemplate("regsysID", regSysId)
.resolveTemplate("appointmentID", apptId);
Invocation invocation = resourceTarget.request(MediaType.APPLICATION_JSON).buildPut(null);
String createSessionJson = invocation.invoke(String.class);
Note: this is a new method available on JAX-RS 2.1
This is a very old post but the below code will work for both jersey and resteasy.
ClientBuilder clientBuilder = ClientBuilder.newBuilder();
clientBuilder.connectTimeout(10, TimeUnit.SECONDS);
clientBuilder.readTimeout(12, TimeUnit.SECONDS);
Client client = clientBuilder.build();
You can do this by creating a ClientConfig first and providing it as an argument when creating the new client.
import org.glassfish.jersey.client.ClientProperties;
ClientConfig configuration = new ClientConfig();
configuration.property(ClientProperties.CONNECT_TIMEOUT, 1000);
configuration.property(ClientProperties.READ_TIMEOUT, 1000);
Client client = ClientBuilder.newClient(configuration);
With Resteasy this can be accomplished by building your Client as such.
Client client = new ResteasyClientBuilder()
.establishConnectionTimeout(2, TimeUnit.SECONDS)
.socketTimeout(2, TimeUnit.SECONDS)
.build();
I have not seen a list of standard configuration properties you could set via ClientBuilder.newClient(Configuration configuration) which would be needed to make this portable.
First, you have to add relevant dependencies (here is for the WildFly 10.1):
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>3.0.14.Final</version>
<scope>provided</scope>
</dependency>
Next - create a normal Apache HttpClient and push it the RestEasy Enginge with overriding one method, which causes the problem:
// create here a normal Apache HttpClient with all parameters, that you need
HttpClient httpClient = createHttpClient(connectTimeout,
socketTimeout,
connectionRequestTimeout,
maxTotalHTTPConnections);
// Deprecated Apache classes cleanup https://issues.jboss.org/browse/RESTEASY-1357
// Client Framework not honoring connection timeouts Apache Client 4.3 https://issues.jboss.org/browse/RESTEASY-975
ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient) {
#Override
protected void loadHttpMethod(ClientInvocation request, HttpRequestBase httpMethod) throws Exception {
super.loadHttpMethod(request, httpMethod);
httpMethod.setParams(new BasicHttpParams());
}
};
return new ResteasyClientBuilder().httpEngine(engine).build();
Have a look at https://issues.jboss.org/browse/RESTEASY-975 Seems, that the problem was just resolved in the version 3.1.0.Final.
For people stuck with older JAX-RS 2.0 API and old Resteasy implementation, you may use this method:
Client client = new ResteasyClientBuilder()
.establishConnectionTimeout(3, TimeUnit.SECONDS)
.socketTimeout(5, TimeUnit.SECONDS).build();
Despite the name, socketTimeout stands for "read timeout", since by the docs, it stands for "The timeout for waiting for data".
If you are using Jersey 2.x Here it is the simple solution it's work for me
import com.jclient.JClient;
Client c = Client.create();
WebResource webResource = c.resource("requestUrl");
c.setConnectTimeout(yourMins*60*1000);