This post:
http://kennytordeur.blogspot.com/2011/04/nhibernate-in-combination-with_06.html
Describes how to load an entity from a resource other than a database, in this case a webservice. This is great, but if I load a number of clients in one query, each with a different MaritialState, it will have to call the webservice for each Client. Is there a way to preload all marital states, so it doesn't have to go back and forth to the webservice for each client?
I don't think Hibernate supports this. 'n+1 select problem' is a well know issue and Hibernate has quite a few strategies for dealing with it (batches, subselects, eager fetching etc). The problem is you have 'n+1 web service call' and all these mechanisms are useless. Hibernate simply does not know about what you are doing in IUserType. It assumes that you converting already loaded data.
It looks like you will have to implement your own preloading. Something like this:
// TODO: not thread safe, lock or use ConcurrentDictionary
static IDictionary<Int32, ClientDto> _preLoadedClients
= new IDictionary<int,ClientDto>();
public Object NullSafeGet(IDataReader rs, String[] names, ...) {
Int32 clientid = NHibernateUtil.Int32.NullSafeGet(rs, names[0]);
// see if client has already been preloaded:
if(_preLoadedClients.ContainsKey(clientid)) {
return _preLoadedClients[clientid];
}
// load a batch: clientId + 1, client + 2, ... client + 100
var batchOfIds = Enumerable.Range(clientid, 100);
var clientsBatch = clientService.GetClientsByIds(batchOfIds);
_preLoadedClients.Add(clientsBatch);
return _preLoadedClients[clientid];
}
Related
According to documentation on loopback, lb soap creates models of underlying soap based datasource. Is there a programmatic way to do this? I want to do it programmatically to facilitate a dynamic soap consumption through dynamically created models and datasources.
Disclaimer: I am a co-author and maintainer of LoopBack.
Here is the source code implementing the command lb soap:
soap/index.js
soap/wsdl-loader.js
Here is the code that's generating models definition and method source code:
exports.generateAPICode = function generateAPICode(selectedDS, operationNames) { // eslint-disable-line max-len
var apis = [];
var apiData = {
'datasource': selectedDS,
'wsdl': selectedWsdl,
'wsdlUrl': selectedWsdlUrl,
'service': selectedService.$name,
'binding': selectedBinding.$name,
'operations': getSelectedOperations(selectedBinding, operationNames),
};
var code = soapGenerator.generateRemoteMethods(apiData);
var models = soapGenerator.generateModels(apiData.wsdl, apiData.operations);
var api = {
code: code,
models: models,
};
apis.push(api);
return apis;
};
As you can see, most of the work is delegated to soapGenerator, which refers to loopback-soap - a lower-level module maintained by the LoopBack team too. In your application, you can use loopback-soap directly (no need to depend on our CLI tooling) and call its API to generate SOAP-related models.
Unfortunately we don't have much documentation for loopback-soap since it has been mostly an internal module so far. You will have to read the source code to build a better understanding. If you do so, then we would gladly accept contributions improving the documentation for future users.
I am writing an application where the Client issues commands to a web service (CQRS)
The client is written in C#
The client uses a WCF Proxy to send the messages
The client uses the async pattern to call the web service
The client can issue multiple requests at once.
My problem is that sometimes the client simply issues too many requests and the service starts returning that it is too busy.
Here is an example. I am registering orders and they can be from a handful up to a few 1000s.
var taskList = Orders.Select(order => _cmdSvc.ExecuteAsync(order))
.ToList();
await Task.WhenAll(taskList);
Basically, I call ExecuteAsync for every order and get a Task back. Then I just await for them all to complete.
I don't really want to fix this server-side because no matter how much I tune it, the client could still kill it by sending for example 10,000 requests.
So my question is. Can I configure the WCF Client in any way so that it simply takes all the requests and sends the maximum of say 20, once one completes it automatically dispatches the next, etc? Or is the Task I get back linked to the actual HTTP request and can therefore not return until the request has actually been dispatched?
If this is the case and WCF Client simply cannot do this form me, I have the idea of decorating the WCF Client with a class that queues commands, returns a Task (using TaskCompletionSource) and then makes sure that there are no more than say 20 requests active at a time. I know this will work but I would like to ask if anyone knows of a library or a class that does something like this?
This is kind of like Throttling but I don't want to do exactly that because I don't want to limit how many requests I can send in a given period of time but rather how many active requests can exist at any given time.
Based on #PanagiotisKanavos suggjestion, here is how I solved this.
RequestLimitCommandService acts as a decorator for the actual service which is passed in to the constructor as innerSvc. Once someone calls ExecuteAsync a completion source is created which along with the command is posted to the ActonBlock, the caller then gets back the a Task from the completion source.
The ActionBlock will then call the processing method. This method sends the command to the web service. Depending on what happens, this method will use the completion source to either notify the original sender that a command was processed successfully or attach the exception that occurred to the source.
public class RequestLimitCommandService : IAsyncCommandService
{
private class ExecutionToken
{
public TaskCompletionSource<bool> Source { get; }
public ICommand Command { get; }
public ExecutionToken(TaskCompletionSource<bool> source, ICommand command)
{
Source = source;
Command = command;
}
}
private IAsyncCommandService _innerSrc;
private ActionBlock<ExecutionToken> _block;
public RequestLimitCommandService(IAsyncCommandService innerSvc, int maxDegreeOfParallelism)
{
_innerSrc = innerSvc;
var options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism };
_block = new ActionBlock<ExecutionToken>(Execute, options);
}
public Task IAsyncCommandService.ExecuteAsync(ICommand command)
{
var source = new TaskCompletionSource<bool>();
var token = new ExecutionToken(source, command);
_block.Post(token);
return source.Task;
}
private async Task Execute(ExecutionToken token)
{
try
{
await _innerSrc.ExecuteAsync(token.Command);
token.Source.SetResult(true);
}
catch (Exception ex)
{
token.Source.SetException(ex);
}
}
}
Our organization wants to develop a "LOST & FOUND System Application" using chatbot integrated in a website.
Whenever the user starts the conversation with the chatbot, the chatbot should ask the details of lost item or item found and it should store the details in database.
How can we do it ?
And can we use our own web-service because organization doesn't want to keep the database in Amazon's Server.
As someone who just implemented this very same situation (with a lot of help from #Sid8491), I can give some insight on how I managed it.
Note, I'm using C# because that's what the company I work for uses.
First, the bot requires input from the user to decide what intent is being called. For this, I implemented a PostText call to the Lex API.
PostTextRequest lexTextRequest = new PostTextRequest()
{
BotName = botName,
BotAlias = botAlias,
UserId = sessionId,
InputText = messageToSend
};
try
{
lexTextResponse = await awsLexClient.PostTextAsync(lexTextRequest);
}
catch (Exception ex)
{
throw new BadRequestException(ex);
}
Please note that this requires you to have created a Cognito Object to authenticate your AmazonLexClient (as shown below):
protected void InitLexService()
{
//Grab region for Lex Bot services
Amazon.RegionEndpoint svcRegionEndpoint = Amazon.RegionEndpoint.USEast1;
//Get credentials from Cognito
awsCredentials = new CognitoAWSCredentials(
poolId, // Identity pool ID
svcRegionEndpoint); // Region
//Instantiate Lex Client with Region
awsLexClient = new AmazonLexClient(awsCredentials, svcRegionEndpoint);
}
After we get the response from the bot, we use a simple switch case to correctly identify the method we need to call for our web application to run. The entire process is handled by our web application, and we use Lex only to identify the user's request and slot values.
//Call Amazon Lex with Text, capture response
var lexResponse = await awsLexSvc.SendTextMsgToLex(userMessage, sessionID);
//Extract intent and slot values from LexResponse
string intent = lexResponse.IntentName;
var slots = lexResponse.Slots;
//Use LexResponse's Intent to call the appropriate method
switch (intent)
{
case: /*Your intent name*/:
/*Call appropriate method*/;
break;
}
After that, it is just a matter of displaying the result to the user. Do let me know if you need more clarification!
UPDATE:
An example implementation of the slots data to write to SQL (again in C#) would look like this:
case "LostItem":
message = "Please fill the following form with the details of the item you lost.";
LostItem();
break;
This would then take you to the LostItem() method which you can use to fill up a form.
public void LostItem()
{
string itemName = string.Empty;
itemName = //Get from user
//repeat with whatever else you need for a complete item object
//Implement a SQL call to a stored procedure that inserts the object into your database.
//You can do a similar call to the database to retrieve an object as well
}
That should point you in the right direction hopefully. Google is your best friend if you need help with SQL stored procedures. Hopefully this helped!
Yes its possible.
You can send the requests to Lex from your website which will extract Intents and Entities.
Once you get these, you can write backend code in any language of your choice and use any DB you want.
In your use case, you might just want to use Lex. PostText will be main function you will be calling.
You will need to create an intent in Lex which will have multiple slots LosingDate, LosingPlace or whatever you want, then it will be able to get all these information from the user and pass it to your web application.
I have created a sample application to get full idea of Spring MVC with REST Webservice. I have created an application which host webservice and a client which calls to this webservice and fetch the relevant data. I am able to pass the arguments from client side like String, and able to receive the data as List or single object, and till here it goes smooth..
Now I want to pass the List as an argument from client side, and also want to implement on webservice side to get the List which is passed from client application. Can anyone helpout with this scenario?
Please find code snippet of my working version.
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("appContext.xml", Client.class);
RestTemplate restTemplate = applicationContext.getBean("restTemplate", RestTemplate.class);
String url;
// retrieve a list of customers
url = "http://localhost:8080/restful-ws/app/testlist.xml";
List<CustomerBean> custList = (List) restTemplate.getForObject(url, List.class);
for (CustomerBean cust : custList) {
System.out.println(">> cust :"+ cust.toString());}
Web Service side implementation.
#RequestMapping(method=RequestMethod.GET, value="/testlist")
public ModelAndView showCustomers() {
ModelAndView mv = new ModelAndView("customerListKey");
List<Customer> custs = new ArrayList<Customer>();
for (Customer customer:customers.values()) {
custs.add(customer);
}
mv.addObject("allCustomers", custs);
return mv;
}
also i have related files, but if will put all code snippets, it will become too much. Mainly my query is how can I pass List from client side and how can i get it from receiver/server side?, in both side i am using spring only
Thanks in advance for your time and help.
-Ronak.
Use an array of CustomerBean
CustomerBean[] custList = restTemplate.getForObject(url, CustomerBean[].class);
The conversion from array to list is left as an exercise for the interested reader...
Webservice1 can receive a set of Lon/Lat variables. Based on these variables it returns a resultset of items nearby.
In order to create the resultset Webservice1 has to pass the variables to multiple webservices of our own and multiple external webservices. All these webservice return a resultset. The combination of these resultsets of these secondary Webservices is the resultset to be returned by Webservice1.
What is the best design approach within Windows Azure with costs and performance in mind?
Should we sequential fire requests from Webservice1 to the other webservices wait for a response and continue? Or can we eg use a queue where we post the variables to be picked up by the secondary webservices?
I think you've answered you're own question in the title.
I wouldn't worry about using a queue. Queues are great for sending information off to get dealt with by something else when it doesn't matter how long it takes to process. As you've got a web service that's waiting to return results, this is not ideal.
Sending the requests to each of the other web services one at a time will work and is the easiest option technically, but it won't give you the best performance.
In this situation I would send requests to each of the other web services in parallel using the Task Parallel Library. Presuming the order of the items that you return isn't important your code might look a bit like this.
public List<LocationResult> PlacesOfInterest(LocationParameters parameters)
{
WebService[] webServices = GetArrayOfAllWebServices();
LocationResult[][] results = new LocationResult[webServices.Count()][];
// Call all of the webservices parallel
Parallel.For((long)0,
webServices.Count(),
i =>
{
results[i] = webServices[i].PlacesOfInterest(parameters);
});
var finalResults = new List<LocationResult>();
// Put all the results together
for (int i = 0; i < webServices.Count(); i++)
{
finalResults.AddRange(results[i]);
}
return finalResults;
}