cxf failover recovery - apache

I have a cxf JAX-WS client. I added the failover strategy. The question is how the client can recovery from the backup solution and use again the primary URL? Because now after the client will switch to secondary URL remains there, will not use the primary URL even if this become available again.
The code for the client part is:
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(GatewayPort.class);
factory.setAddress(this.configFile.getPrimaryURL());
FailoverFeature feature = new FailoverFeature();
SequentialStrategy strategy = new SequentialStrategy();
List<String> addList = new ArrayList<String>();
addList.add(this.configFile.getSecondaryURL());
strategy.setAlternateAddresses(addList);
feature.setStrategy(strategy);
List<AbstractFeature> features = new ArrayList<AbstractFeature>();
features.add(feature);
factory.setFeatures(features);
this.serviceSoap = (GatewayPort)factory.create();
Client client = ClientProxy.getClient(this.serviceSoap);
if (client != null)
{
HTTPConduit conduit = (HTTPConduit)client.getConduit();
HTTPClientPolicy policy = new HTTPClientPolicy();
policy.setConnectionTimeout(this.configFile.getTimeout());
policy.setReceiveTimeout(this.configFile.getTimeout());
conduit.setClient(policy);
}

You may add the primary URL to the alternate addresses list instead of setting that to JaxWsProxyFactoryBean. This way, since you are using SequentialStrategy, the primary URL will be checked first for every service call, if it fails then secodary URL will be tried.

You might as well try an alternative CXF failover feture with failback.
https://github.com/jaceko/cxf-circuit-switcher

Related

I am trying to create a Connection Pool with single connection using PoolingHttpClientConnectionManager and ClosableHttpClient for HTTPS and reuse it

Trying to create a connection pool, where only single HTTPS connection will be created and when subsequent request comes previous connection pool would be used. Currently when I am trying to hit any request each time new connection is getting Established and previous connection is going into time wait state.
Below code-snippet I am using, it's working for HTTP connection but not for HTTPS
SslConfigurator sslConfig = SslConfigurator.newInstance().keyStoreFile(this.connectionInfo.getKeyStorePath()).keyStorePassword(connectionInfo.getKeyStorePassword()).keyStoreType("JKS").trustStoreFile(this.connectionInfo.getKeyStorePath()).trustStorePassword(connectionInfo.getKeyStorePassword()).securityProtocol("TLS");
logger.info("SSL CONFIG Accepted");
sslContext = sslConfig.createSSLContext();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,NoopHostnameVerifier.INSTANCE);
logger.info("SSL CONTEXT CREATED, Building Client" );
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create().register("https", sslsf).build();
connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
connManager.setMaxTotal(1);
connManager.setDefaultMaxPerRoute(1);
config = RequestConfig.custom().setConnectTimeout(60000).setConnectionRequestTimeout(60000).setSocketTimeout(60000).build();
client = HttpClients.custom().setDefaultRequestConfig(config).setConnectionManager(connManager).build();
connManager.setMaxTotal(1);
I am not sure why you think this has no effect because this should definitely restrict the total number of connections in the pool to just one at a time.
In your particular case however you should be using BasicHttpClientConnectionManager instead of PoolingHttpClientConnectionManager

.Net Core ReportExecutionServiceSoapClient set credentials

I am using ReportExecutionServiceSoapClient in .Net Core i got the latest version of .net Core and tried to get a report from reporting services to work. after I've used the WCF connection service I was able to add the code with looks like bellow
// Instantiate the Soap client
ReportExecutionServiceSoap rsExec = new ReportExecutionServiceSoapClient(ReportExecutionServiceSoapClient.EndpointConfiguration.ReportExecutionServiceSoap);
// Create a network credential object with the appropriate username and password used
// to access the SSRS web service
string historyID = null;
TrustedUserHeader trustedUserHeader = new TrustedUserHeader();
ExecutionHeader execHeader = new ExecutionHeader();
// Here we call the async LoadReport() method using the "await" keyword, which means any code below this method
// will not execute until the result from the LoadReportAsync task is returned
var taskLoadReport = rsExec.LoadReportAsync(reportPath, historyID);
// By the time the LoadReportAsync task is returned successfully, its "executionInfo" property
// would have already been populated. Now the remaining code in this main thread will resume executing
string deviceInfo = null;
string format = "EXCEL";
// Now, similar to the above task, we will call the RenderAsync() method and await its result
var taskRender = await rsExec.RenderAsync(renderReq);
When it hist renderAsync all falls apart because the credentials for the service are not set anywhere. I've tried to Login async with no success. Also I've tried to set the credentials with SetExecutionCredentialsAsync but I've got and error saying "The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'NTLM'." I don't know how to change that for ReportExecutionServiceSoapClient.
I have read some posts in which Microsoft guys says that the authentication with a soap is not resolved but for me it seems so close to be true. I feel like I am missing something.
Technology stack: VS 2017, .net Core web api, ssrs 2016, sql server 2016 standard
How can I authenticate the user for this call?
I know this is an old question but I had the same issue and stumbled onto the answer.
After creating the ReportExecutionServiceSoap object you can specify the username and password in the ClientCredentials. I've had success with this using the Basic client credential type. Be sure you are using HTTPS, otherwise your password is sent in plaintext to the reporting server. I also recommend storing the user/password in a secure place and not code.
BasicHttpBinding rsBinding = new BasicHttpBinding();
rsBinding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
rsBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
EndpointAddress rsEndpointAddress = new EndpointAddress("https://servername/ReportServer/ReportExecution2005.asmx");
var rsExec = new ReportExecutionServiceSoapClient(rsBinding, rsEndpointAddress);
rsExec.ClientCredentials.UserName.UserName = "username";
rsExec.ClientCredentials.UserName.Password = "pass";

RavenDB failover scenario. How to know the actual server?

I'm setting up a project with replication and failover for RavenDB (server and client 3.0), and now I'm testing with a replica DB.
The failover behavior is very simple: I've two servers, one on 8080 and one on 8081. The configuration is basically this:
store.FailoverServers.ForDatabases = new Dictionary<string, ReplicationDestination[]>
{
{
"MyDB",
new[]
{
new ReplicationDestination
{
Url = "http://localhost:8080"
},
new ReplicationDestination
{
Url = "http://localhost:8081"
}
}
}
};
The failover IS working well, I've tried to shut down the first server (that is the one used in the DocumentStore configuration) and the second one is responding as expected.
What I want to know is: is there a way to understand what is the current failover server that is responding to the queries? If inside the session I try to navigate the DocumentSession properties (as the session.Advanced.DocumentStore.Identifier) I cannot find references to the second server, but I see only reference to the first one, that is the one used for the configuration.
Am I missing something?
You can use the ReplicationInformer.FailoverStatusChanged to get notified on failovers.
You can access the replication informer using: DocumentStore.GetReplicationInformerForDatabase()

WCF routing -- how to correctly add filter table programmatically

I am using the WCF 4 routing service, and need to configure the service programmatically (as opposed to via config). The examples I have seen of doing so, which are rare, create a MessageFilterTable as follows:
var filterTable=new MessageFilterTable<IEnumerable<ServiceEndpoint>>();
But, the generic parameter to that method is supposed to be TFilterData (the type of data you are filtering on)? I have my own custom filter that accepts a string -- can I still create the filter table this way?
If this will work...will the routing infrastructure create client endpoints out of the list I pass in?
I have created a WCF 4 routing service and configured it programmatically. My code is a bit more spaced out than it needs to be (maintainability for others being a concern, hence the comments), but it definitely works. This has two filters: one filters some specific Actions to a given endpoint, and the second sends the remaining actions to a generic endpoint.
// Create the message filter table used for routing messages
MessageFilterTable<IEnumerable<ServiceEndpoint>> filterTable = new MessageFilterTable<IEnumerable<ServiceEndpoint>>();
// If we're processing a subscribe or unsubscribe, send to the subscription endpoint
filterTable.Add(
new ActionMessageFilter(
"http://etcetcetc/ISubscription/Subscribe",
"http://etcetcetc/ISubscription/KeepAlive",
"http://etcetcetc/ISubscription/Unsubscribe"),
new List<ServiceEndpoint>()
{
new ServiceEndpoint(
new ContractDescription("ISubscription", "http://etcetcetc/"),
binding,
new EndpointAddress(String.Format("{0}{1}{2}", TCPPrefix, HostName, SubscriptionSuffix)))
},
HighRoutingPriority);
// Otherwise, send all other packets to the routing endpoint
MatchAllMessageFilter filter = new MatchAllMessageFilter();
filterTable.Add(
filter,
new List<ServiceEndpoint>()
{
new ServiceEndpoint(
new ContractDescription("IRouter", "http://etcetcetc/"),
binding,
new EndpointAddress(String.Format("{0}{1}{2}", TCPPrefix, HostName, RouterSuffix)))
},
LowRoutingPriority);
// Then attach the filter table as part of a RoutingBehaviour to the host
_routingHost.Description.Behaviors.Add(
new RoutingBehavior(new RoutingConfiguration(filterTable, false)));
You can find a good example on MSDN here: How To: Dynamic Update Routing Table
Note how they dont directly create an instance of the MessageFilterTable, but instead use the 'FilterTable' property provided by a new RoutingConfiguration instance.
If you have written a custom filter, then you will add it like this:
rc.FilterTable.Add(new CustomMessageFilter("customStringParameter"), new List<ServiceEndpoint> { physicalServiceEndpoint });
The CustomMessageFilter will be your filter, and the "customStringParameter" is the string that (I believe) you are talking about.
When the Router receives a connection request, it will attempt to map it via this table entry, if this is successful, then you are right, the router will create a client endpoint to talk to the ServiceEndpoint that you provided.

Where do I specify proxy credentials in my WCF client?

I have created a WCF client using channel factory.
But I am not able to connect to a server in another machine. I am getting a (407) Prxy Authentication Required exception.
WSHttpBinding wsBinding = new WSHttpBinding();
wsBinding.BypassProxyOnLocal = true;
EndpointAddress endpoint =
new EndpointAddress("http://machineName:7676/MyWCFService");
ChannelFactory<IService> sericeInterface =
new ChannelFactory<IService>(wsBinding, endpoint);
sericeInterface.Credentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
sericeInterface = sericeInterface.CreateChannel();
This is my client connection code nippet. I am getting exception when I call a method of the service.
Take a look at this CodePlex link, try to find a scenario that matches closely to yours. It provides checklists and samples of how to set the various credentials for different situations/bindings.
Also this MSDN link might help with Windows Authentication, which you seem to be using.
To assign credentials you'll need something like the below taken from the MSDN link:
CalculatorClient cc = new
CalculatorClient("WSHttpBinding_ICalculator");
// This code returns the WindowsClientCredential type.
cc.ClientCredentials.Windows.ClientCredential.UserName = GetUserName();
cc.ClientCredentials.Windows.ClientCredential.Password = GetPassword();