Reuse jax-ws client proxies for different addresses - spring

I have a bunch of web services servers (around 200) running on the same machine which expose the same service on different ports.
I have a client which perform tasks which include calling the service on different servers.
Something like:
while (true) {
task = readTask();
runHelloService(task.serverAddress)
}
I was wondering what is the best way to generate the HelloService client proxy.
Can I generate one and replace the target address before each call?
Should i generate a client per server (which means 200 client proxies) and use the relevant one?
I will probably want to run the above loop concurrently on several threads.
Currently I have only one proxy which is generated by spring and cxf with the jaxws:client declaration.

This is an interesting use case. I believe that changing the endpoint whilst sharing the proxy amongst multiple threads will not work. There is a one-to-one relationship between a client proxy and a conduit definition. Changes to a conduit are explicitly not thread safe.
I recommend eschewing Spring configuration altogether to create client proxies and instead use programmatic construction of the 200 client proxies.
See also Custom CXF Transport - Simplified Client Workflow.

Related

Is there a way to communicate synchronously between two EARs using SpringBoot?

I have two EARs which are deployed on a single Weblogic server. The two EARs are A and B.
"A" has a service that "B" needs to access. B needs to access this service and get the data synchronously.
I do not want to use REST or other HTTP methods as it would slow down the communication.
Is there something like RMI for SpringBoot that works within the Same server?
Or is it equally faster to use a REST call within the same server compared to an RMI based solution?
I went through Spring Remote, but it seems to be for communication between different servers. Please let me know if this is the case.

Provider side of PACT using gradle

I am new to PACT. My application is a spring boot application. Consumer has pact created in PACT broker. Now I am trying to run tests from providers end and I am using gradle plugin to run tests. I have couple of questions:
Pact published by consumer do not have any states specified. So this means I don't have to use any stateChangeUrl at provider side ?
Pact published has get method. However when I run pactVerify server starts and my pact tests are failing because I don't have any existing data. How can I inject data after.
What I am trying to achieve is: When I say pactVerify
Server starts up, and my spring boot app should be up and running in localhost (This is good)
Before pacts are verified I need to inject some data like "POST\add User. So that pact test passes when it tries to do GET\User. (How to do this ?)
Below is my gradle file
pact {
serviceProviders {
'user-api' {
protocol = 'http'
host = 'localhost'
port = 8080
startProviderTask = startService
terminateProviderTask = stopService
if ('pactVerify' in gradle.startParameter.taskNames) {
hasPactsFromPactBroker('http://pactbroker.com') {
< How to write some code here to say do POST before running PACT >
}
}
}
}
Pact published by consumer do not have any states specified. So this means I don't have to use any stateChangeUrl at provider side ?
It means you have chosen not to use this mechanism to change states, and therefore yes, you don't need to use that URL. But you may wish to change your mind on that.
Pact published has get method. However when I run pactVerify server starts and my pact tests are failing because I don't have any existing data. How can I inject data after.
Why not inject the data before you start all of the tests? If you don't have states to worry about, then you may as well just start the provider with the data pre-loaded into the database.
As noted, all of the configuration info can be found at https://github.com/DiUS/pact-jvm/tree/master/pact-jvm-provider-gradle.
The consumer code needs to declare provider states in the pact to allow you to set up the right data for the interaction.
From docs.pact.io
Each interaction in a pact should be verified in isolation, with no context maintained from the previous interactions. Tests that depend on the outcome of previous tests are brittle and land you back in integration test hell, which is the nasty place you're trying to escape by using pacts.
So how do you test a request that requires data to already exist on the provider? Provider states allow you to set up data on the provider by injecting it straight into the data source before the interaction is run, so that it can make a response that matches what the consumer expects. The name of the provider state is specified in the given clause of an interaction in the consumer, and then used to find the block of code to run in the provider to set up the right data. If you need to stub a downstream system, or return an error response that is difficult to cause in the normal scheme of things (e.g. a 500), this is the place where you can set up stubs.
Provider states also allow the consumer to make the same request with different expected responses (e.g. different response codes, or the same resource with a different subset of data).
Keep in mind that a provider state is all about the state of the provider (eg. what data is there, how it is going to handle a given response), not about the state of the consumer, or about what is in the request.
Refer to the the Ruby example to see how this plays out in code.

How to send data to multiple servers in spring boot micro service?

I have requirement something like this:
once the request is received by my service, i need to send it 2-3 third party servers at a time and get the response from all server and return the response.
How can I achieve that?.
My thought : I can create separate threads for different servers and send the request to all servers parallely, but here the issue is, how I will come to know the threads are finished and consolidate the response from all servers and return to caller.
Is there any other way to do in spring boot(micro service)?.
You can leverage asyn feature supported by Spring Framework. Let's see the folllowing example which issue multiple calls in Async style from Spring's official guides:Async Method
Another possible solution for internal communications between Microserives is to use the message queue.
You didn't specify what type of services are you consuming. If they are HTTP, you may want to use some Enterprise Integrations abstractions (most popular are Spring Integration and Apache Camel).
If you don't want to introduce message bus solution into your microservice, you may want to take a look at AsyncRestTemplate

Jax rs client pool

I am working on setting up a REST Client using jax-rs 2 client API.
In the api doc it says "Clients are heavy-weight objects that manage the client-side communication infrastructure. Initialization as well as disposal of a Client instance may be a rather expensive operation. It is therefore advised to construct only a small number of Client instances in the application." (https://docs.oracle.com/javaee/7/api/javax/ws/rs/client/Client.html). As per this statement it sounds like Client is not thread-safe and i should not be using single Client instance for all requests.
I am using CXF implementation, so far i didn't find a way to set up pool for Client objects.
If anyone has any information reg this could you please share.
Thanks in advance.
By default, CXF uses a transport based on the in-JDK HttpURLConnection object to perform HTTP requests.
Connection pooling is performed allowing persistent connections to reuse the underlying socket connection for multiple http requests.
Set these system properties to configure the pool(default values)
http.keepalive=true
http.maxConnections=5
Increment the value of http.maxConnections to set the maximum number of idle connections that will be simultaneously kept alive, per destination. See in this link the complete list of properties properties.html
In this post are explained some detail how it works
Java HttpURLConnection and pooling
Note also that the default JAX-RS client is not thread-safe by default. Check the limitations for proper use here
When you need many requests executed simultaneosly CXF can also use the asynchronous apache HttpAsyncClient. Ser details here
http://cxf.apache.org/docs/asynchronous-client-http-transport.html

Proxy Service & Business Service

Can i use a proxy service without a business service while configuring message flows in Oracle service bus? If so is what scenarios would we use it?
You can create a proxy service that does not use a business service.
Some reasons for such an approach is to create a common proxy module that is used by other proxy services that may do some common message processing before forwarding to a business service.
I think you cannot create a proxy service without a business service call in OSB, but you can call dummy business services that publish on a JMS topic that nobody listens on. This kind of proxy service could implement data transformation (e.g. XSLT) between the request and response, or enrich the response with data retrieved from a lookup table (fn-bea:execute-sql()).
A service bus, like OSB is meant to provide a façade to back-end (business) services: route to and compose existing services. What you are asking for is to create new back-end services which is more suited for Java EE servers or Oracle BPEL.
Update: You can create stand-alone proxy service, if you use pipeline pair and stage, but no route steps.
You can create a proxy service without a business service. A simple scenario is suppose you want to fetch the data from the queue, could be jms or mq, and you don't want to do anything with that data. You just simply want to empty the queue and do not want to store the message. In this case, your purpose can be fulfilled by simply creating a proxy service.

Resources