IBM Watson Conversation Service Using Proxy settings from Java API - proxy

I have developed a conversation service using IBM Watson and deployed. I am able to access my service using the IBM Watson API explorer. I tried connecting the service using a Java API as explained in https://developer.ibm.com/recipes/tutorials/integration-of-ibm-watson-conversation-service-to-your-java-application/ I am working on a corporate network, so using proxy to access internet. Now I am not able to access the service from my Java API. I am getting below error.
Exception in thread "main" java.lang.RuntimeException: java.net.ConnectException: Failed to connect to gateway.watsonplatform.net/169.48.66.222:443
at com.ibm.watson.developer_cloud.service.WatsonService$1.execute(WatsonService.java:182)
at com.chat.CustomerChat.conversationAPI(CustomerChat.java:47)
at com.chat.CustomerChat.main(CustomerChat.java:32)
Caused by: java.net.ConnectException: Failed to connect to gateway.watsonplatform.net/169.48.66.222:443
at okhttp3.internal.io.RealConnection.connectSocket(RealConnection.java:187)
at okhttp3.internal.io.RealConnection.buildConnection(RealConnection.java:170)
at okhttp3.internal.io.RealConnection.connect(RealConnection.java:111)
at okhttp3.internal.http.StreamAllocation.findConnection(StreamAllocation.java:187)
at okhttp3.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:123)
at okhttp3.internal.http.StreamAllocation.newStream(StreamAllocation.java:93)
at okhttp3.internal.http.HttpEngine.connect(HttpEngine.java:296)
at okhttp3.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
at okhttp3.RealCall.getResponse(RealCall.java:243)
at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:201)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163)
at okhttp3.RealCall.execute(RealCall.java:57)
How do we set proxy connection in IBM watson Connection service?
My code:(Modified the user credentials and workspace id here)
ConversationService service = new ConversationService("2017-05-26");
service.setUsernameAndPassword("dfgdfg-578a-46b6-55hgg-ghgg4343", "ssdsd455gfg");
MessageRequest newMessage = new MessageRequest.Builder().inputText(input).context(context).build();
String workspaceId = "fgfdgfgg-ce7a-422b-af23-gfgf56565";
MessageResponse response = service.message(workspaceId, newMessage).execute();

Not completely sure about work around for Java, but when i had similar issue with Node, i had to set up proxy variables and that helped. I would recommend you to give a try by setting up proxy variables in eclipse and JVM. And also i think this Java file must be helpful.

After going though IBM API documentation I found below method to set the proxy. It should work.
HttpConfigOptions config = new HttpConfigOptions
.Builder()
.proxy(new Proxy(Proxy.Type.HTTP,
new InetSocketAddress("<Proxy IP>", <Proxy Port>)))
.build();
service.configureClient(config);
I implemented this code with Java-sdk 6.14.0. IBM has discontinued ConversationService package and deprecated Conversation package in this version of SDK. Instead Assistant package has been introduced. My working code is as below.
Assistant service = null;
Context context = null;
if (watsonUser.equalsIgnoreCase(APIKEY_AS_USERNAME))
{
IamOptions iamOptions = new IamOptions.Builder().apiKey(watsonApikey).build();
service = new Assistant(watsonVersion, iamOptions);
}
else
{
service = new Assistant(watsonVersion, watsonUser,watsonPassword);
}
service.setEndPoint(watsonUrl);
if(watsonProxy != null)
{
HttpConfigOptions config = new HttpConfigOptions
.Builder()
.proxy(new Proxy(Proxy.Type.HTTP,
new InetSocketAddress(watsonProxyIP, watsonProxyPort)))
.build();
service.configureClient(config);
}
String workspaceId = watsonWorkspace_id;
InputData input = new InputData.Builder(inputStr).build();
MessageOptions options = new MessageOptions.Builder(workspaceId)
.context(context)
.input(input)
.build();
MessageResponse response = service.message(options).execute();
context = response.getContext();
I have checked the code with Conversation package based implementation. It worked. I couldn't checked with code given in the question as ConversationService package is no more in the current SDK.

Related

Open Api 3.0 Swagger application with Visual Studio 19 - database connection problem

I have to make application for .NET5.0. (Core). I have installed packages Devart.Data (5.0.2658) and Devart.Data.Oracle(9.14.1234).
I use 32 bits oracle client in my computer.
I have switched my application to x86 mode.
I need to connect to a Oracle 12 server.
Here is my code:
[Route("GetMyData")]
[HttpGet]
public List<Cis_titul_pred> GetCiselnik()
{
List<DataModule.BO.Cis_titul_pred> testlist =
DataModule.DAL.Cis_titul_predDB.Instance.GetList();
return testlist;
}
public List<Cis_titul_pred> GetList()
{
List<Cis_titul_pred> cis_titul_predList = null;
using (OracleConnection oraConnect = new OracleConnection(AppConfig.ConnectionString))
{
OracleCommand oraCommand = new OracleCommand(selectList, oraConnect);
oraCommand.CommandType = CommandType.Text;
oraConnect.Open();
using (OracleDataReader oraReader = oraCommand.ExecuteReader())
{
if (oraReader.HasRows)
{
cis_titul_predList = new List<Cis_titul_pred>();
while (oraReader.Read())
{
cis_titul_predList.Add(FillCis_titul_pred(oraReader));
}
}
oraReader.Close();
}
oraConnect.Close();
}
return cis_titul_predList;
}
When I created .NET5.0 Desktop (WinForms) application , everything worked properly - I could connect to Oracle server and read data.
When I created .NET5.0 WEB application , everything worked properly - I could connect to Oracle server and read data.
When I created .NET5.0 OpenApi application , I got error message "Devart.Data.Oracle.OracleException (0x80004005): Server did not respond within the specified timeout interval
at Devart.Data.Oracle.dp.a(cj A_0, di A_1)
at Devart.Data.Oracle.OracleInternalConnection..ctor(cj connectionOptions, OracleInternalConnection proxyConnection)
at Devart.Data.Oracle.ci.a(ae A_0, Object A_1, DbConnectionBase A_2) Etc. ... Etc..."
I use the same code to connect to the Oracle server in all three applications
I tried change target framewor to NET.Core 3.0, or NET.Cre 3.1, but without success.
Any ideas?
What can I do?
What do you mean by .NET5.0 OpenApi application? It's the same architecture with .net5 web... Please check If you have a correct and same connection string in your appSettings.json file. Also consider using dependancy injection instead of creating OracleConnection instance inside controllers

Error during https call through proxy using CXF

In camel-cxf I have to call a SOAP webservice (exposed in https) through a proxy: configuring the http conduit as follows
public void configureClient(Client client) {
String proxySrv = Util.getProperty(Constants.Config.PROXY_SRV);
int proxyPort = new Integer(Util.getProperty(Constants.Config.PROXY_PORT));
log.info("Configurazione del server proxy:'"+proxySrv+"' port:'"+proxyPort+"'");
HTTPConduit conduit = (HTTPConduit) client.getConduit();
HTTPClientPolicy policy = new HTTPClientPolicy();
policy.setProxyServer(proxySrv); // set proxy host
policy.setProxyServerPort(proxyPort); // set proxy port
policy.setProxyServerType(ProxyServerType.SOCKS);
conduit.setClient(policy);
conduit.setAuthSupplier(new DefaultBasicAuthSupplier());
boolean proxyAuthEnabled = new Boolean(Util.getProperty(Constants.Config.PROXY_AUTH_EN));
String user = Util.getProperty(Constants.Config.PROXY_USER);
String pass = Util.getProperty(Constants.Config.PROXY_PASS);
log.info("Recuperati username:'+"+user+"' e password per il proxy:'"+proxySrv+"' port:'"+proxyPort+"'");
if (proxyAuthEnabled) {
ProxyAuthorizationPolicy ap = new ProxyAuthorizationPolicy();
ap.setUserName(user);
ap.setPassword(pass);
conduit.setProxyAuthorization(ap);
// conduit.getAuthorization().setUserName(user);
// conduit.getAuthorization().setPassword(pass);
log.info("Autenticazione abilitata per userName ='"+user+"' per il proxy:'"+proxySrv+"' port:'"+proxyPort+"'");
}
it works for http call (without the proxy server type set) but it doesn't work for https call. This proxy requires basic auth.
Reading various articles I saw that there is a bug in CXF that doesn't send the header authorization in the CONNECT call (and infact I'm getting 407 Authorization required -> even if with the same credentials with http calls it works).
Is there a way to fix it? I read about Olivier Billard solution
https://www.mail-archive.com/users#cxf.apache.org/msg06422.html
but I didn't undestand that solution (and I can't import at code any keystore).
Thanks
Hello I just faced this issue with the apache cxf client, the workaround suggested in the mailing list is to use the following static method of the java.net.Authenticator class :
Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("youruser", "yourpassword".toCharArray());
}
});
This way the basic will be set automatically on all your HttpUrlConnection that uses the proxy, since java 8 you also have to enable basic authentication for HTTPS tunneling, you can do this with the following property:
-Djdk.http.auth.tunneling.disabledSchemes=""
I hope this helps

When creating an IServiceManagement for Dynamics 365, why does the authentication endpoint respond with an HTML sign in page?

I have some integration code that intends to use the Organization Service via the CRM SDK.
On one environment, creating an IServiceManagement<IOrganizationService>:
IServiceManagement<IOrganizationService> orgServiceManagement = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri("dynamics uri")));
and then authenticating with service account credentials:
AuthenticationCredentials authCredentials = new AuthenticationCredentials();
authCredentials.ClientCredentials.UserName.UserName = _config.GetValue<string>("Dynamics:Username");
authCredentials.ClientCredentials.UserName.Password = _config.GetValue<string>("Dynamics:Password");
AuthenticationCredentials tokenCredentials = orgServiceManagement.Authenticate(authCredentials);
works fine.
On another Dynamics environment, the call to GetServiceManagement fails with the following error message:
System.InvalidOperationException
HResult=0x80131509
Message=Metadata contains a reference that cannot be resolved: 'https://login.microsoftonline.com/[guid]/oauth2/authorize?client_id=[some client id]&response_mode=form_post&response_type=code+id_token&scope=openid+profile&state=OpenIdConnect.AuthenticationProperties%[some base-64]RedirectTo%3dhttps%253a%252f%252ftst-success.crm4.dynamics.com%252f&nonce=[some nonce]&redirect_uri=https:%2f%2fcloudredirector.crm4.dynamics.com%2fG%2fAuthRedirect%2fIndex.aspx&max_age=86400'.
Source=System.ServiceModel
StackTrace:
at System.ServiceModel.Description.MetadataExchangeClient.MetadataRetriever.Retrieve(TimeoutHelper timeoutHelper)
at System.ServiceModel.Description.MetadataExchangeClient.ResolveNext(ResolveCallState resolveCallState)
at System.ServiceModel.Description.MetadataExchangeClient.GetMetadata(MetadataRetriever retriever)
at System.ServiceModel.Description.MetadataExchangeClient.GetMetadata(Uri address, MetadataExchangeClientMode mode)
at Microsoft.Xrm.Sdk.Client.ServiceMetadataUtility.RetrieveServiceEndpointMetadata(Type contractType, Uri serviceUri, Boolean checkForSecondary)
at Microsoft.Xrm.Sdk.Client.ServiceConfiguration`1..ctor(Uri serviceUri, Boolean checkForSecondary)
at Microsoft.Xrm.Sdk.Client.ServiceConfigurationFactory.CreateConfiguration[TService](Uri serviceUri, Boolean enableProxyTypes, Assembly assembly)
at Microsoft.Xrm.Sdk.Client.ServiceConfigurationFactory.CreateConfiguration[TService](Uri serviceUri)
at CrmAuthTest.Program.Main(String[] args) in c:\users\t.wolverson\Source\Repos\CrmAuthTest\CrmAuthTest\Program.cs:line 18
Inner Exception 1:
XmlException: CData elements not valid at top level of an XML document. Line 1, position 3.
(I have masked the bits which look identifying or cryptographic)
POSTing to this URL in PostMan yields the HTML for a browser login page, which explains the failure; this isn't what the ServiceConfigurationFactory expects. The scenario is not user-interactive, so this would never make sense, there is no browser and no user able to interact with it.
What do I have to change in Dynamics CRM Online to stop it doing this, and make it just work normally?
Do you instantiate your OrganizationServiceProxy depending on the AuthenticationProviderType right after the lines of code you have posted? Like this
var orgServiceManagement = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri(ConfigurationManager.AppSettings["CrmUrlService"]));
var authCredentials = new AuthenticationCredentials();
authCredentials.ClientCredentials.UserName.UserName = ConfigurationManager.AppSettings["CrmUserName"];
authCredentials.ClientCredentials.UserName.Password = ConfigurationManager.AppSettings["CrmPassword"];
var tokenCredentials = orgServiceManagement.Authenticate(authCredentials);
IOrganizationService _service;
switch (orgServiceManagement.AuthenticationType)
{
case AuthenticationProviderType.ActiveDirectory:
_service = new OrganizationServiceProxy(orgServiceManagement, tokenCredentials.ClientCredentials);
break;
default:
_service = new OrganizationServiceProxy(orgServiceManagement, tokenCredentials.SecurityTokenResponse);
break;
}
Even if this solves your problem, I recommend that you use CrmServiceClient instead. This class can be found in Microsoft.Xrm.Tooling.Connector dll. It is the go to authentication class when building Windows client applications that connect to Microsoft Dynamics 365. More information on this can be found here
Here is an example on how to initialize CrmServiceClient when connecting to Dynamics 365 online using Office 365:
var myConnectionString = "Url=https://[YourOrganization].crm4.dynamics.com;Username=[YourUser];Password=[YourPassword];AuthType=Office365;";
var crmClient = new CrmServiceClient(myConnectionString);
//Do your stuff
var response = crmClient.Execute(new WhoAmIRequest());
If you need other authentication methods in Dynamics Online check how to build your connection string here.
For on-premises check how to build your connection string here.

PlatformPlugin exception getting app-only token using MSAL in ASP.NET Core

I'm trying to create an ASP.NET Core app that uses MSAL for the client credentials flow.
I get the following exception when trying to get an access token:
NullReferenceException: Object reference not set to an instance of an object.
Microsoft.Identity.Client.Internal.PlatformPlugin.LoadPlatformSpecificAssembly()
Authentication is modeled after this sample: active-directory-dotnet-webapp-openidconnect-aspnetcore-v2
Authorization is modeled after this sample: active-directory-dotnet-daemon-v2
My app is registered with the Mail.Read Application permission. Here's the code that throws the exception:
string authority = $"https://login.microsoftonline.com/{ tenantId }/v2.0";
ConfidentialClientApplication client = new ConfidentialClientApplication(
authority,
appId,
redirectUri,
new ClientCredential(appSecret),
null);//new TokenCache());
AuthenticationResult authResult = await client.AcquireTokenForClient(
new string[] { "Mail.Read" }, null);
return authResult.Token;
Also tried with "https://graph.microsoft.com/.default" scope, as in the daemon sample.
Answering this question. I opened this as an issue on the GitHub repo. It was closed with the following response:
this problem will not occur with the next release as we will move to a single binary.

Can I use the Dynamics CRM 4.0 SDK against a hosted IFD system?

I am running this code (with names and security details obscured). When I do, I get 401 unauthorised. The credentials are that of the user on the hosted server. Is this possible against an IFD system?
var token = new CrmAuthenticationToken();
token.AuthenticationType = 0;
token.OrganizationName = "myorganisation";
CrmService service = new CrmService();
service.Url = "https://myorganisation.dynamicsgateway.com/mscrmservices/2007/crmservice.asmx";
service.CrmAuthenticationTokenValue = token;
service.Credentials = new NetworkCredential("bob.smith", "Password", "HOSTEDCRM");
var request = new RetrieveMultipleRequest();
request.Query = new QueryExpression
{
ColumnSet = new ColumnSet(new string[] { "name" }),
EntityName = "account"
};
var response = service.Execute(request);
I assume this code is outside of the CRM Website? In that case you'll want to add a reference to the discovery service as Mercure points out above. You'll want to execute a RetrieveCrmTicketRequest against the discovery service to get a ticket good for connecting to the Crm Services.
In your CRM Authentication Token you'll want to set the authentication type to 2 (IFD). Then set the CrmTicket property on the token to the ticket you got from your RetrieveCrmTicketResponse.
I also set the URL based on that response, but you could continue to hard code it.
You will want to continue to set the Credentials on the service.
I use a single user to connect to CRM and cache that ticket (an expiration date is in the response from the discovery service). That way I can bypass the discovery service on future requests. There is an error code to look for to go after the ticket again, but I don't have it off hand.
Yes, it's possible, you are only missing a little pieces, the CrmAuthenticationToken.ExtractCrmAuthenticationToken.
Check out this great explaination on Dynamics Forum http://social.microsoft.com/Forums/en-US/crmdevelopment/thread/81f8ba82-981d-40dd-893d-3add67436478

Resources