I am new to Java, Eclipse, Google App Engine and the Datastore and am writing my first app to teach myself some new technology both for work and for professional development purposes.
I have a Java app that successfully saves and retrieves data from a datastore that I have created based upon the key. I now want to be able to do more general queries based upon other information in my datastore for meta-code such as:
select key_column from my datastore where other_column = "data to be searched"
To achieve this, I have done some on-line reading and referenced the O'Reilly book Programming Google App Engine. I started with the sample code and it fails with the error message:
An error occured while attempting to contact the server.
Please check your network connect and try again
My code at this point is:
Query q = new Query("Force");
q.addFilter("ForceName", Query.FilterOperator.EQUAL, input);
PreparedQuery pq = datastore.prepare(q);
for (Entity forceresult : pq.asQueryResultIterable()); {
String newinput = (String) result.getProperty("ForceCode");
}
The error occurs on the last String netinput line.
The datastore code exists and is good - I have successfully written/read from it.
The documentation on the above sample code is lacking however to a newbie in this area, for instance: I am assuming that the Entity 'forceresult' only exists within the for loop and cannot be referenced from outside it - that is fine with me.
However, in the String newinput line, I have coded result.getProperty even though it seems to me that it should be forceresult.getProperty as this is what I want to refer to.
When I code that however, Eclipse tells me that it cannot resolve forceresult even though an Entity has been defined in the line above.
Is result a reserved word that I missed the significance of?
Is my code wrong in any other respect? Perhaps I am not understanding asQueryResultIterable properly yet?
How should I interpret the error message:
An error occured while attempting to contact the server.
Please check your network connect and try again
I hope someone can point me in the right direction either with a specific answer or advice on where to go next in my learning curve.
You have an error in your loop (a ; too much :)). Try this:
for (Entity forceresult : pq.asQueryResultIterable()) {
// ^ ; was here
String newinput = (String) result.getProperty("ForceCode");
}
Thus your loop was actually empty and the result.getProperty(...) got called outside, where forceresult isn't defined.
Related
I have a Google App Engine + Java app which has been happily running for many years (using JDO + datastore for persistence) and I have had no problem (occasionally, and reluctantly) updating a property of an entity in the Google Datastore console manually.
Recently (maybe the last 2-3 months) I have noticed a change in behaviour which breaks our app. I do not understand exactly what's going wrong or how we could handle it.
So my question is:
Why is it behaving differently and what can I do about it?
Let me first try to explain the behaviour I am seeing and then show my smallest possible replicating test case.
Suppose you had a simple persistence class:
#PersistenceCapable
public class Account implements Serializable {
#Persistent private ShortBlob testShortBlob;
#Persistent private String name;
// ...etc...
}
If I edited the name via the Datastore web console in the past, it would work as expected, the name field would change and everything else would work fine.
The behaviour I am seeing now is that after saving the entity via the console, I can no longer query and load the entity in JDO, I get:
java.lang.ClassCastException: com.google.appengine.api.datastore.Blob cannot be cast to com.google.appengine.api.datastore.ShortBlob
Which points to some underlying datastore change that means that ShortBlob field is having it's type change from ShortBlob to Blob (even though I make no edits to that field via the console).
This test case will replicate the issue:
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
// this one really is a ShortBlob - will load fine in JDO
Entity account = new Entity("Account", "123");
account.setProperty("name", "Test Name");
account.setUnindexedProperty("testShortBlob", new ShortBlob("blah".getBytes()));
datastore.put(account);
// this one really is not a ShortBlob, its a blob - it will fail for the same reason I am seeing in production.
account = new Entity("Account", "124");
account.setProperty("name", "Test Name 2");
account.setUnindexedProperty("testShortBlob", new Blob("blah".getBytes()));
datastore.put(account);
// then load the entity via JDO
try {
accountFromJdo = pm.getObjectById(Account.class, key);
} catch (Exception ex) {
System.out.println("We get here, the object won't load with the ClassCast Exception");
}
So that's the issue, but why would saving via the cloud datastore console be changing the ShortBlob's to Blob?
My workaround currently is to set the ShortBlob fields to null in the Datastore console - that will then allow the entity to load. But that sucks if the data in the blob is important!
Update:
I have been doing more testing on this, using the low-level JSON API to see if I could se a difference in the raw JSON responses before and after saving the entity via console. The good news is, I can!
Before editing the entity via the console, a shortBlob field saved to the Datastore via the JDO App Engine interface will look like this:
},
"testShortBlob": {
"blobValue": "tNp7MfsjhdfjkahsdvfkjhsdvfIItWyzy6glmIrow4WWhRPbhQ/U+MGX3opVvpxu"
},
But if I go in to the Datastore console, and edit the entity (leave the blob field unchanged, edit an unrelated field, such as name. Now when I run the same query I get:
},
"testShortBlob": {
"blobValue": "tNp7MfsjhdfjkahsdvfkjhsdvfIItWyzy6glmIrow4WWhRPbhQ/U+MGX3opVvpxu",
"excludeFromIndexes": true
},
Subtle difference, but I think it's important, according to the Java docs ShortBlob are indexed, and Blob are not.
So I think my question now is: why does editing an entity via the Cloud Datastore console change the indexed status of blob fields?
Thanks for the detailed question and debugging. This seems fishy. I will make sure https://issuetracker.google.com/issues/79547492 gets assigned to the correct team.
As far as workarounds go:
The JSON API you noticed is Cloud Datastore API v1 there are a variety of client libraries to help make it easy to access.
It is possible to use that API to transactionally read/modify/write entities. In your case it would allow you to perform the desired transforms. Alternatively, making modifications through JDO would also work.
I wanted to use the Braintree Marketplace (I've got the approval and signed to use the marketplace functionality). I used JAVA for my backend and played with the Sandbox account.
I was trying to create a submerchant accorinding to the tutorials in the overview and the specific section. E.g., the code I directly copied from the guide is (I'VE ALSO TRIED TO USE MY VALID PERSONAL INFORMATION BELOW):
MerchantAccountRequest request = new MerchantAccountRequest().
individual().
firstName("Jane").
lastName("Doe").
email("jane#14ladders.com").
phone("5553334444").
dateOfBirth("1981-11-19").
ssn("456-45-4567").
address().
streetAddress("111 Main St").
locality("Chicago").
region("IL").
postalCode("60622").
done().
done().
funding().
descriptor("Blue Ladders").
destination(MerchantAccount.FundingDestination.BANK).
email("funding#blueladders.com").
mobilePhone("071101307").
accountNumber("1123581321").
routingNumber("071101307").
done().
tosAccepted(true).
masterMerchantAccountId("14ladders_marketplace").
id("blue_ladders_store");
Result<MerchantAccount> result = gateway.merchantAccount().create(request);
I've also tried to use the testing first name
com.braintreegateway.test.MerchantAccount.Approve
so that the creation should always succeed. The code snippet is:
Result<MerchantAccount> result = gateway.merchantAccount().create(
new MerchantAccountRequest().
individual()
.firstName(com.braintreegateway.test.MerchantAccount.Approve)
.done()
);
However, in any case, when I tried to check if the result is successful (and if not, what the errors are):
logger.info("Is the result successful? " + result.isSuccess());
ValidationErrors errors = result.getErrors();
logger.info("Number of errors returned " + result.getErrors().size());
The result.isSuccess() always returns false, while there are no errors in result.getErrors(). I also cannot find any (error) information from the sandbox web account. Any insights what might go wrong? or is this because I haven't enabled the marketplace functionality?
Thanks!
I work at Braintree. If you have more questions, you can always get in touch with our support team. It looks like you already have an open ticket with us and got a response, but I'll post his here for others who have the same problem.
You're looking for result.getErrors().getAllDeepValidationErrors() not just result.getErrors().
For more information on this type of failure, see the validation errors page in the Braintree docs.
When I create a new ARB subscription the response comes back and I save the id it gives us. I tried it out and it gives us back "33".
Then when the silent post callback hits our method, the response has a different id, 15631016.
15631016 is correct in matching up with the one we see in the authorize.net online portal.
So, what is 33 and why doesn't it return the real ARB ID?
Here is the code that creates the new ARB and then gets the arbId:
net.authorize.arb.Transaction arbTransaction = createARBTransaction(startDate.getTime(), creditCard, member, splitOccurrences.intValue() - 1, splitUnit, useBillingAddress, billingAddress, recurringOrder.getTotalAmount().doubleValue(), recurringOrder);
net.authorize.arb.Result<?> arbResult = (net.authorize.arb.Result<?>) merchant.postTransaction(arbTransaction);
String arbId;
if (arbResult.isOk()) {
arbId = arbResult.getResultSubscriptionId();
}
If getResultSubscriptionId() is not the correct way to get the new ARB subscription ID, what is the correct method to use?
I went through the sample code and also their community and there isn't much to go on. The only thing I can think of trying is changing:
arbResult.getResultSubscriptionId();
to:
arbTransaction.getResultSubscriptionId();
I know that doesn't sound logical but it's the best I can some up with.
According to the source code, you are using the correct method.
If you trace the calls back into the code you'll see that the subscription id gets set by the following call in importResponseMessages() of net.authorize.arb.Result
getElementText(txn.getCurrentResponse().getDocumentElement(),AuthNetField.ELEMENT_SUBSCRIPTION_ID.getFieldName());
so if you call this on your arbResult variable, you might get closer. Note that txn should be replaced by your variable arbTransaction.
Alternatively, you can dig into the response itself to see why the Authorize.net APK isn't returning the correct subscription id.
xml = arbTransaction.getCurrentResponse().dump(true);
The true determines whether the XML tree is collapsed. xml should be a string containing your XML response from authorize.net
I have been using http://ofx4j.sourceforge.net/userguide.html as a guide to write a small java program to download my bank account statement from wells fargo. I keep getting an error saying Invalid Signon. I have the right url. I am using the same password and username as I use to logon to their webpage. Does anyone have any other simple samples that I could look at or use?
I had the same problem.
I was trying to log into Chase Bank but I was getting an Invalid Signon.
The problem that I had is that I was using the wrong data, oxf4j might have obsolete data
stored for the banks it has stored.
Go to gnucash to get the right updated setting for your bank:
http://wiki.gnucash.org/wiki/OFX_Direct_Connect_Bank_Settings.
Then you need to create a new BaseFinancialInstitutionData object
like this (this example is for chase credit card):
BaseFinancialInstitutionData data = new BaseFinancialInstitutionData();
data.setFinancialInstitutionId("10898");
data.setOFXURL(new URL("https://ofx.chase.com"));
data.setOrganization("B1");
FinancialInstitutionService service = new FinancialInstitutionServiceImpl();
FinancialInstitution fi = service.getFinancialInstitution(data);
I am working on a XMPP client on Android, using the Smack library. The roster/messaging/presence stuff is running very well. However, I didn't find a way to store additional profile information (userpicture, the dogs name, ...).
The only way I see from googling is using VCards. But it simply did not work. I tried the following:
VCard vCard = new VCard();
vCard.load(connection);
vCard.setEmailHome("meine_home#email.de");
vCard.setLastName("Scheller");
vCard.setField("blafasel", "asdf");
vCard.save(connection);
Then I was looking for a way to see that VCard information. It did neither show up in iChat nor in this System.out:
vCard.load(connection, user);
System.out.println(user + " has this vCard: " + vCard.toXML());
So anything went wrong, but theres no indication what it was. I tried this with the google talk server and my own copy of openfire with the same result. Btw, I am using this version of Smack: http://davanum.wordpress.com/2007/12/31/android-just-use-smack-api-for-xmpp/
What am I doing wrong here? What is the correct way of storing profile related information with Smack?
I have checked out the source of Smack and went through the important parts with a debugger, as well as using the Smack Debug Window. The problem is inside the VCard implementation of the Smack API. Saving a VCard does work as described, however the loading is broken.
parseIQ(XmlPullParser parser) is part of the PacketReader.java class and handles different types of packages. It only handles tags with the following namespaces:
"jabber:iq:auth",
"jabber:iq:roster",
"jabber:iq:register",
"urn:ietf:params:xml:ns:xmpp-bind"
It also looks if there is any registered IQProvider in the ProviderManager. And this is the root of my problem. There is no IQProvider for VCards registered. So whatever information is inside of the vCard tag simply gets dropped.
It is not too hard to register this IQProvider though:
ProviderManager.getInstance().addIQProvider("vCard", "vcard-temp", new VCardProvider());
This solved my little example above for saving my own vCard and downloading it again. I am still having trouble with downloading other users vcards... Gonna have a closer look into this and maybe open up another thread for that issue.
You can use the following code to get info.
VCard card = new VCard();
card.load(connection, "user#fqdn");
System.out.println("Voice: "+card.getPhoneHome("VOICE"));
Try setting a vCard for that user with another client first, and see how that changes your results. In order to diagnose further, you'll need to turn on protocol debugging in Smack (use "-Dsmack.debugEnabled=true" on a desktop machine), and post the relevant bits here.