Google place API returns same place for two different place with same name - web-services

I am using Google place API. While it works fine there is a case where it fails. Place API returns same place for "Gorakhpur, Uttar pradesh" and "Gorakhpur, Haryana". It returns "Gorakhpur, Haryana" for both places.
autocompleteFragmentSource = (PlaceAutocompleteFragment) getFragmentManager().findFragmentById(R.id.place_autocomplete_fragment_source);
autocompleteFragmentSource.setOnPlaceSelectedListener(new PlaceSelectionListener() {
#Override
public void onPlaceSelected(Place place) {
sourceAddress = (String) place.getAddress();
}
#Override
public void onError(Status status) {
Toast.makeText(MainActivity.this, "An Error Occured!", Toast.LENGTH_SHORT).show();
}
});
Now source address is same when I select Gorakhpur, Uttar pradesh and Gorakhpur, Haryana from google place autocomplete.
Note: There is no issue with other places having similar names.

Related

BulkProcessor .add() not finishing when number of bulks > concurrentRequests

Here is a sample of the code flow:
Trigger the process with an API specifying bulkSize and totalRecords.
Use those parameters to acquire data from DB
Create a processor with the bulkSize.
Send both the data and processor into a method which:
-iterates over the resultset, assembles a JSON for each result, calls a method if the final JSON is not empty and adds that final JSON to the process using processor.add() method.
This is where the outcome of the code is split
After this, if the concurrentRequest parameter is 0 or 1 or any value < (totalRecords/bulkSize), the processor.add() line is where the code stalls and never continues to the next debug line.
However, when we increase the concurrentRequest parameter to a value > (totalRecords/bulkSize), the code is able to finish the .add() function and move onto the next line.
My reasoning leads me to believe we might be having issues with our BulkProcessListener which is making the .add() no close or finish like it is supposed to. I would really appreciate some more insight about this topic!
Here is the Listener we are using:
private class BulkProcessorListener implements Listener {
#Override
public void beforeBulk(long executionId, BulkRequest request) {
// Some log statements
}
#Override
public void afterBulk(long executionId, BulkRequest request, BulkResponse response) {
// More log statements
}
#Override
public void afterBulk(long executionId, BulkRequest request, Throwable failure) {
// Log statements
}
}
Here is the createProcessor():
public synchronized BulkProcessor createProcessor(int bulkActions) {
Builder builder = BulkProcessor.builder((request, bulkListener) -> {
long timeoutMin = 60L;
try {
request.timeout(TimeValue.timeValueMinutes(timeoutMin));
// Log statements
client.bulkAsync(request, RequestOptions.DEFAULT,new ResponseActionListener<BulkResponse>());
}catch(Exception ex) {
ex.printStackTrace();
}finally {
}
}, new BulkProcessorListener());
builder.setBulkActions(bulkActions);
builder.setBulkSize(new ByteSizeValue(buldSize, ByteSizeUnit.MB));
builder.setFlushInterval(TimeValue.timeValueSeconds(5));
builder.setConcurrentRequests(0);
builder.setBackoffPolicy(BackoffPolicy.noBackoff());
return builder.build();
}
Here is the method where we call processor.add():
#SuppressWarnings("deprecation")
private void addData(BulkProcessor processor, String indexName, JSONObject finalDataJSON, Map<String, String> previousUniqueObject) {
// Debug logs
processor.add(new IndexRequest(indexName, INDEX_TYPE,
previousUniqueObject.get(COMBINED_ID)).source(finalDataJSON.toString(), XContentType.JSON));
// Debug logs
}

Acumatica - Action "Reverse and Apply Memo" Default Post Period to active financial period

Can a customization be created to set the post period to the current active financial period after pressing the "Reverse and Apply to Memo" action in "Invoices and Memos" screen?
We've noticed the newly created credit memo defaults to the post period of the invoice which could be incorrect if it's credited in the following financial period.
The solution defined below was developed within Acumatica 20.102.0015 and changes the date and post period for the created credit memo on "Reverse and Apply Memo" action to the default of a new document instead of the date from the reversed invoice.
namespace AARAMPostPeriod
{
public class AAARInvoiceEntryExtension : PXGraphExtension<ARInvoiceEntry>
{
public delegate IEnumerable ReverseDocumentAndApplyToReversalIfNeededDel(PXAdapter adapter, ReverseInvoiceArgs reverseArgs);
[PXOverride]
public virtual IEnumerable ReverseDocumentAndApplyToReversalIfNeeded(PXAdapter adapter, ReverseInvoiceArgs reverseArgs, ReverseDocumentAndApplyToReversalIfNeededDel del)
{
if(reverseArgs.ApplyToOriginalDocument) reverseArgs.DateOption = ReverseInvoiceArgs.CopyOption.SetDefault;
return del(adapter, reverseArgs);
}
}
}
Default value for reverseArgs.DateOption is typically
ReverseInvoiceArgs.CopyOption.SetOriginal
You are talking about the receivables side of things, but I did something similar on the payables side. It isn't exactly what you are asking for, but it is too big for a comment.
You may be able to get the general idea from this and apply to your scenario. The approach I took was to check the period when releasing.
protected virtual void _(Events.FieldUpdated<APInvoice.finPeriodID> e)
{
APInvoice row = (APInvoice)e.Row;
CheckPeriod(e.Cache, row);
}
#region Release override
public delegate IEnumerable ReleaseDelegate(PXAdapter adapter);
[PXOverride]
public virtual IEnumerable Release(PXAdapter adapter, ReleaseDelegate baseMethod)
{
CheckPeriod(Base.Caches[typeof(APInvoice)], Base.Document.Current);
return baseMethod(adapter);
}
#endregion
protected virtual void CheckPeriod(PXCache cache, APInvoice invoice)
{
if (invoice?.FinPeriodID == null) return;
string currentPeriod = GetCurrentPeriod(invoice.BranchID);
if (currentPeriod != invoice.FinPeriodID)
{
PXUIFieldAttribute.SetError<APInvoice.finPeriodID>(cache, invoice, "Invalid period");
}
}
public virtual string GetCurrentPeriod(int? branchID)
{
PXResultset<Branch> Results = PXSelectJoin<GL.Branch,
InnerJoin<FinPeriod, On<FinPeriod.organizationID, Equal<Branch.organizationID>>>,
Where<Branch.branchID, Equal<Required<Branch.branchID>>,
And<FinPeriod.startDate, LessEqual<Required<FinPeriod.startDate>>,
And<FinPeriod.endDate, Greater<Required<FinPeriod.endDate>>>>>> // End Date is the date AFTER the period ends
.SelectSingleBound(Base, null, branchID, Base.Accessinfo.BusinessDate, Base.Accessinfo.BusinessDate);
if (Results != null)
{
foreach (PXResult<GL.Branch, FinPeriod> result in Results)
{
FinPeriod period = result;
return period.FinPeriodID;
}
}
return null;
}
As you can see, I put an override on the Release to perform my validation which sets an error condition if the period is not current. The validation is performed by retrieving the current period of the current business date and comparing to the period on the APInvoice.
You could explore leveraging GetCurrentPeriod from the example and put into an override on FieldDefaulting if it helps with your goal.

Calling a Web Service (containg multiple pages) does not load all the pages (without an added sleep delay)

My question is about a strange behavious I notice both on my iPhone device and the codenameone simulator (NetBeans).
I invoke the following code below which calls a google web service to provide a list of food places around a GPS coordinate:
The web service that is called is as follows (KEY OBSCURED):
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=40.714353,-74.00597299999998&radius=200&types=food&key=XXXXXXXXXXXXXXXXXXXXXXX
Each result contains the next page token and thus, the second call (for the subsequent page) is as follows:
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=40.714353,-74.00597299999998&radius=200&types=food&key=XXXXXXXXXXXXXXXXXXXXXXX&pagetoken=YYYYYYYYYYYYYYYYYY
public static byte[] getWSResponseData(String urlString, boolean usePost)
{
ConnectionRequest r = new ConnectionRequest();
r.setUrl(urlString);
r.setPost(usePost);
InfiniteProgress prog = new InfiniteProgress();
Dialog dlg = prog.showInifiniteBlocking();
r.setDisposeOnCompletion(dlg);
NetworkManager.getInstance().addToQueueAndWait(r);
try
{
Thread.sleep(2000);
}
catch (InterruptedException ex)
{
}
byte[] responseData = r.getResponseData();
return responseData;
}
public static void getLocationsList(double lat, double lng)
{
boolean done = false;
while (!done)
{
byte[] responseData = getWSResponseData(finalURL,false);
result = Result.fromContent(parser.parseJSON(new InputStreamReader(new ByteArrayInputStream(responseData))));
String venueNames[] = result.getAsStringArray("/results/name");
nextToken = result.getAsString("/next_page_token");
if ( nextToken == null || nextToken.equals(""))
done = true;
else
finalURL = completeURL + "&pagetoken=" + nextToken;
}
.....
}
This code works fine with the sleep timer, but when I remove the Thread.sleep, only the first page gets called.
Any help would be appreciated.
Using the debugger does not help as this is a timing issue and the issue does not occur when using the debugger.
Also when I put some print statements into the code
while (!done)
{
String nextToken = null;
**System.out.println(finalURL);**
...
}
System.out.println("Total Number of entries returned: " + itemCount);
I get the following output:
First Run (WITHOUT SLEEP):
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=40.714353,-74.00597299999998&radius=200&types=food&key=XXXXXXXX
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=40.714353,-74.00597299999998&radius=200&types=food&key=XXXXXXXX&pagetoken=CqQCF...
Total Number of entries returned: 20
Using the network monitor I see that the response to the second WS call returns:
{
"html_attributions" : [],
"results" : [],
"status" : "INVALID_REQUEST"
}
Which is strange as when I cut and paste the WS URL into my browser, it works fine...
Second Run (WITH SLEEP):
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=40.714353,-74.00597299999998&radius=200&types=food&key=XXXXXXXXX
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=40.714353,-74.00597299999998&radius=200&types=food&key=XXXXXXXXX&pagetoken=CqQCFQEAA...
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=40.714353,-74.00597299999998&radius=200&types=food&key=XXXXXXXXX&pagetoken=CsQDtQEAA...
Total Number of entries returned: 60
Well it seems to be a google API issue as indicated here:
Paging on Google Places API returns status INVALID_REQUEST
I still could not get it to work by changing the WS URL with a random parameter as they suggested, but I will keep trying and post something here if I get it to work. For now I will just keep a 2 second delay between the calls which seems to work.
Well gave up on using the google WS for this and switched to Yelp, works very well:
https://api.yelp.com/v3/businesses/search?.....

How do I invoke Multiple Startup Projects when running a unit tests in Debug Mode

This seems like a simple thing to do but I can't seem to find any info anywhere! I've got a solution that has a service that we run in 'Console Mode' when debugging. I want it to be started and 'attached' when I run my unit test from Visual Studio.
I'm using Resharper as the unit test runner.
Not a direct answer to your question, BUT
We faced a similar problem recently and eventually settled on a solution using AppDomain
As your solution is already running as a Console project it would be little work to make it boot in a new AppDomain. Furthermore, you could run Assertions on this project as well as part of unit testing. (if required)
Consider the following static class Sandbox which you can use to boot multiple app domains.
The Execute method requires a Type which is-a SandboxAction. (class definition also included below)
You would first extend this class and provide any bootup actions for running your console project.
public class ConsoleRunnerProjectSandbox : SandboxAction
{
protected override void OnRun()
{
Bootstrapper.Start(); //this code will be run on the newly create app domain
}
}
Now to get your app domain running you simply call
Sandbox.Execute<ConsoleRunnerProjectSandbox>("AppDomainName", configFile)
Note you can pass this call a config file so you can bootup your project in the same fashion as if you were running it via the console
Any more questions please ask.
public static class Sandbox
{
private static readonly List<Tuple<AppDomain, SandboxAction>> _sandboxes = new List<Tuple<AppDomain, SandboxAction>>();
public static T Execute<T>(string friendlyName, string configFile, params object[] args)
where T : SandboxAction
{
Trace.WriteLine(string.Format("Sandboxing {0}: {1}", typeof (T).Name, configFile));
AppDomain sandbox = CreateDomain(friendlyName, configFile);
var objectHandle = sandbox.CreateInstance(typeof(T).Assembly.FullName, typeof(T).FullName, true, BindingFlags.Default, null, args, null, null, null);
T sandBoxAction = objectHandle.Unwrap() as T;
sandBoxAction.Run();
Tuple<AppDomain, SandboxAction> box = new Tuple<AppDomain, SandboxAction>(sandbox, sandBoxAction);
_sandboxes.Add(box);
return sandBoxAction;
}
private static AppDomain CreateDomain(string name, string customConfigFile)
{
FileInfo info = customConfigFile != null ? new FileInfo(customConfigFile) : null;
if (!string.IsNullOrEmpty(customConfigFile) && !info.Exists)
throw new ArgumentException("customConfigFile not found using " + customConfigFile + " at " + info.FullName);
var appsetup = new AppDomainSetup();
//appsetup.ApplicationBase = Path.GetDirectoryName(typeof(Sandbox).Assembly.Location);
appsetup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
if (customConfigFile==null)
customConfigFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
appsetup.ConfigurationFile = customConfigFile;
var sandbox = AppDomain.CreateDomain(
name,
AppDomain.CurrentDomain.Evidence,
appsetup);
return sandbox;
}
public static void DestroyAppDomainForSandbox(SandboxAction action)
{
foreach(var tuple in _sandboxes)
{
if(tuple.Second == action)
{
AppDomain.Unload(tuple.First);
Console.WriteLine("Unloaded sandbox ");
_sandboxes.Remove(tuple);
return;
}
}
}
}
[Serializable]
public abstract class SandboxAction : MarshalByRefObject
{
public override object InitializeLifetimeService()
{
return null;
}
public void Run()
{
string name = AppDomain.CurrentDomain.FriendlyName;
Log.Info("Executing {0} in AppDomain:{1} thread:{2}", name, AppDomain.CurrentDomain.Id, Thread.CurrentThread.ManagedThreadId);
try
{
OnRun();
}
catch (Exception ex)
{
Log.Error(ex, "Exception in app domain {0}", name);
throw;
}
}
protected abstract void OnRun();
public virtual void Stop()
{
}
}

Why does my XML ASP.NET web service return results which repeats itself?

I have written an ASP.NET web service.
It looks like this:
WebServices.logic pLogic = new WebServices.logic();
WebServices.manager[] pManager = new PowerManager[1];
pManager[0] = new PowerManager();
pManager[0].CustomerId = "sjsjshd";
pManager[0].state = pLogic.getState("sasj");
return pManager[0];
The pManager class looks like this:
public string _CustomerId;
public int PowerStatus;
public List<ArrayList> _Power;
public string CustomerId
{
get
{
return _CustomerId;
}
set
{
_CustomerId = value;
}
}
public List<ArrayList> Power
{
get
{
return _Power;
}
set
{
_Power = value;
}
}
When I run it, I get a repetition of the results, like so:
<p>
<_CustomerId>sjsjshd</_CustomerId>
<pStatus>0</PowerStatus>
−
<_p>
−
<ArrayOfAnyType>
<anyType xsi:type="xsd:int">1</anyType>
</ArrayOfAnyType>
<ArrayOfAnyType/>
</_p>
<CustomerId>sjsjshd</CustomerId>
−
<p>
−
<ArrayOfAnyType>
<anyType xsi:type="xsd:int">1</anyType>
</ArrayOfAnyType>
<ArrayOfAnyType/>
</p>
</pManager>
However, there is no duplicate values stored (Eg. I store client name in a collection, but only once - count of 1). There are no duplicates stored when I call getState(). This method returns a collection and it contains one value, but the results in XML has a repetition of this.
How comes the results appear to repeat themselves? When running the system, I only get one error.
Thanks
OK, looks like your XML serialization is giving you all the public members of your PowerManager class. Based on the naming convention of starting with an underscore, those members should be private, like this:
private string _CustomerId;
private List<ArrayList> _Power;
You also state "When running the system, I only get one error." What error are you getting?