I use realm-java on Android. now I'm creating profile function, but I'm not sure how to user realm correctly.
when renew profile,
delete value -> store value
but, I fetch value from realm, sometimes old value is taken.
To reproduce,
My test repository is below, and I attached movie that problem is reproduced.
https://github.com/shinsan/realm_test/
When thread id is changed, sometimes old value appears.
so, if you try to reproduce, please use lower memory device such as nexus5 simulator
#I think Realm instance is singleton and transaction is thread-safe, so value is always only one.
my code
kotlin + Android Studio
Realm Java 10.3
//Store
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
val entity = AccountProfileEntity(accountProfile)
it.copyToRealmOrUpdate(entity)
}
//Delete
val realm = Realm.getDefaultInstance()
val entity = realm.where(AccountProfileEntity::class.java).findFirst()
realm.executeTransaction {
entity?.deleteFromRealm()
}
//Fetch
val realm = Realm.getDefaultInstance()
val instance = realm.where(AccountProfileEntity::class.java).findFirst()
return instance?.toModel()
// profile get function
override suspend fun getProfile(isForce: Boolean): AccountProfile =
withContext(Dispatchers.IO) {
if (isForce) {
database.delete()
}
val profile = database.fetch()
if (profile != null) {
return#withContext profile
}
val token = prefs.getToken() ?: throw NoTokenException
val response = service.getProfile(token)
database.store(response)
response
}
Please Help
I solved this. simply I forgot to close realm instance each fetch, store, delete.
Related
We have an application that loads all contacts stored in an account using the Microsoft Graph API. The initial call we issue is https://graph.microsoft.com/v1.0/users/{userPrincipalName}/contacts$count=true&$orderBy=displayName%20ASC&$top=100, but we use the Java JDK to do that. Then we iterate over all pages and store all loaded contacts in a Set (local cache).
We do this every 5 minutes using an account with over 3000 contacts and sometimes, the count of contacts we received due to using $count does not match the number of contacts we loaded and stored in the local cache.
Verifying the numbers manually we can say, that the count was always correct, but there are contacts missing.
We use the following code to achieve this.
public List<Contact> loadContacts() {
Set<Contact> contacts = new TreeSet<>((contact1, contact2) -> StringUtils.compare(contact1.id, contact2.id));
List<QueryOption> requestOptions = List.of(
new QueryOption("$count", true),
new QueryOption("$orderBy", "displayName ASC"),
new QueryOption("$top", 100)
);
ContactCollectionRequestBuilder pageRequestBuilder = null;
ContactCollectionRequest pageRequest;
boolean hasNextPage = true;
while (hasNextPage) {
// initialize page request
if (pageRequestBuilder == null) {
pageRequestBuilder = graphClient.users(userId).contacts();
pageRequest = pageRequestBuilder.buildRequest(requestOptions);
} else {
pageRequest = pageRequestBuilder.buildRequest();
}
// load
ContactCollectionPage contactsPage = pageRequest.get();
if (contactsPage == null) {
throw new IllegalStateException("request returned a null page");
} else {
contacts.addAll(contactsPage.getCurrentPage());
}
// handle next page
hasNextPage = contactsPage.getNextPage() != null;
if (hasNextPage) {
pageRequestBuilder = contactsPage.getNextPage();
} else if (contactsPage.getCount() != null && !Objects.equals(contactsPage.getCount(), (long) contacts.size())) {
throw new IllegalStateException(String.format("loaded %d contacts but response indicated %d contacts", contacts.size(), contactsPage.getCount()));
} else {
// done
}
}
log.info("{} contacts loaded using graph API", contacts.size());
return new ArrayList<>(contacts);
}
Initially, we did not put the loaded contacts in a Set by ID but just in a List. With the List we very often got more contacts than $count. My idea was, that there is some caching going on and some pages get fetched multiple times. Using the Set we can make sure, that we only have unique contacts in our local cache.
But using the Set, we sometimes have less contacts than $count, meaning some pages got skipped and we end up in the condition that throws the IllegalStateException.
Currently, we use microsoft-graph 5.8.0 and azure-identiy 1.4.2.
Have you experienced similar issues and can help us solve this problem?
Or do you have any idea what could be causing these inconsistent results?
Your help is very much appreciated!
I know its a bit weird question but how can I access the unique (auto) id google firebase generates for my document whenever I create new document. For example this is my code
val postCollections = db.collection("posts")
val newPost = Post(text, user, currentTime)
postCollections.document().set(newPost)
How can I know that what is the id generated for this document of "newPost" because i want to use that id in my code and at the same time i dont want to send custom id because it won't be unique
val postCollections = db.collection("posts")
val newPost = Post(text, user, currentTime)
postCollections.document().set(newPost)
As you've likely discovered, .set() returns a Promise <void> .
But what you've ignored is .set() only operates on a DocumentReference - which is what you get from postCollections.document(). A DocumentReference has properties id and path - it is the .document() that creates a new, unique, documentId.
So:
val postCollections = db.collection("posts")
val newPost = Post(text, user, currentTime)
val newRef = postCollections.document()
newRef.set(newPost)
And now you have the document id (and path) available as properties of newRef.
https://firebase.google.com/docs/reference/js/firebase.firestore.DocumentReference
I am integrating Stripe for Java in a Kotlin app.
This is the code that I wrote to create a Charge
createCharge function:
fun createCharge(charge: Charge, testApiKey: String): Charge? {
//met
// On your server, grab the Stripe token in the POST parameters submitted by your form. From there, it’s one simple API call to charge the card
Stripe.apiKey = testApiKey
try {
val chargeParams = mutableMapOf<String, Any?>()
chargeParams["amount"] = charge.amount
chargeParams["currency"] = charge.currency
chargeParams["description"] = charge.description
chargeParams["source"] = charge.source
chargeParams["customer"] = charge.customer
chargeParams["receipt_email"] = charge.receiptEmail
val requestOptions = idempotencyKeySetter()
val initialMetadata = mutableMapOf<String, String?>()
initialMetadata["start_date"] = charge.metadata["start_date"]
initialMetadata["end_date"] = charge.metadata["end_date"]
chargeParams["metadata"] = initialMetadata
return Charge.create(chargeParams, requestOptions)
} catch (e: StripeException) {
e.printStackTrace()
return null
}
}
and the function calling the createCharge function:
var formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
fun checkCreateCharge() {
val chargeParams: Charge = Charge()
chargeParams.amount = 2000
chargeParams.currency = "usd"
chargeParams.description = description
chargeParams.source = PaymentSource { "" }
chargeParams.customer = customerId
chargeParams.receiptEmail = testEmail
chargeParams.metadata["start_date"] = LocalDate.parse("2018-12-31", formatter).toString()
chargeParams.metadata["end_date"] = LocalDate.parse("2019-03-31", formatter).toString()
val newCharge: Charge? = createCharge(chargeParams, testApiKey)
}
When I the function checkCreateCharge runs, it sends the following error:
java.lang.IllegalStateException: chargeParams.metadata must not be null
Does anyone know why this is the case?
So while this is "possible" you absolutely should not do this. It's a very large security vulnerability. Anyone with your App would be able to sniff your Stripe Secret API Key and do any number of bad things. They could, for instance, test credit cards or even take money from your account.
When implementing Stripe on Android you should only use your Publishable API Key and only use the key to create Tokens/Sources. All other operations should leverage your Secret API Key on a secured backend.
Best I can tell from the API documentation, you're accessing getMetadata() which is returning null (as you've never set a value on it). Basically, the line:
chargeParams.metadata["start_date"] = LocalDate.parse("2018-12-31", formatter).toString()
is equivalent to the Java code:
chargeParams.getMetadata().put("start_date", LocalDate.parse("2018-12-31", formatter).toString())
and in your situation getMetadata() is null. I believe changing this to be:
chargeParams.setMetadata(
mapOf(
"start_date" to LocalDate.parse("2018-12-31", formatter).toString(),
"end_date" to LocalDate.parse("2019-03-31", formatter).toString()
)
)
will resolve the issue.
We are building a basic PoC example with Corda. Right now we have a basic Cordapp that send a String message from one node to another.
That works fine but next steps are to retrieve one message using the api.
We have this path to retrieve all, but we need just one.
#GET
#Path("cases")
#Produces(MediaType.APPLICATION_JSON)
public List<StateAndRef<CaseState>> getCases();
return rpcOps.vaultQuery(CaseState.class).getStates();
}
We have already tried like this:
#GET
#Path("cases/{caseId}")
#Produces(MediaType.APPLICATION_JSON)
public StateAndRef<CaseState> getCase(#PathParam("caseId") String caseId) throws InterruptedException, ExecutionException {
UniqueIdentifier id = new UniqueIdentifier.fromString("caseId");
QueryCriteria criteria = new QueryCriteria.LinearStateQueryCriteria(null, InmutableList.of(id), Vault.StateStatus.UNCONSUMED, null);
return rpcOps.vaultQueryBy(CaseState.class).queryBy(criteria).getStates().get(0);
}
Can you help me?
I have done this in my Cordapps by querying by unconsumed states of the wanted type and then simply filtering the returned result to get what is needed. For example, the following is an example of a Account state being filtered by linearID (as needed in your example)
//Query the vault for unconsumed states and then for account states
val criteria = QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.UNCONSUMED)
val customerStates = serviceHub.vaultService.queryBy<Account.State>(criteria)
//Filter the customer states to find a matching linearId
val filteredStates = customerStates.states.filter {
it.state.data.linearId == linearId
}
Hopefully this helps!
Trying to reconstruct the UniqueIdentifier from the externalId won't work, as you don't know what the UUID is.
The full constructor for LinearStateQueryCriteria is:
data class LinearStateQueryCriteria #JvmOverloads constructor(
val participants: List<AbstractParty>? = null,
val uuid: List<UUID>? = null,
val externalId: List<String>? = null,
override val status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
override val contractStateTypes: Set<Class<out ContractState>>? = null)
So you need to use the full constructor and query the vault using the following criteria:
QueryCriteria criteria = new QueryCriteria.LinearStateQueryCriteria(
null,
null,
ImmutableList.of("caseId"),
Vault.StateStatus.UNCONSUMED,
null);
Note how here, we're not specifying the UUID, but we are specifying the externalId.
You can use something like this
UUID linearId = "2be921da-5a79-4513-8cb3-7b87ea9307cf";
QueryCriteria criteria = new QueryCriteria.LinearStateQueryCriteria( null, Arrays.asList(linearId), null, Vault.StateStatus.UNCONSUMED, null);
I am using mongo cashbash here is my code
case class A (id:String,name:String)
class InsertClassA(a:A)
{
def inserA()={
val mongoClient=MongoClient(hostName,port)
//get collection and insert record in mongo
mongoClient.close()
}
}
class UpdateClassA(a:A)
{
def UpdateA()={
val mongoClient=MongoClient(hostName,port)
//get collection and update record in mongo
mongoClient.close()
}
}
class DeleteClassA(a:A)
{
def deleteA()={
val mongoClient=MongoClient(hostName,port)
//get collection and delete record in mongo
mongoClient.close()
}
}
object test extends App {
val a =A("123","bob")
val insert =new InsertClassA(a)
val update =new UpdateClassA(a)
val delete =new DeleteClassA(a)
insert.insertA()
update.UpdateA()
delete.deleteA()
}
I want to know when should i close a mongoConnection? The above approach is correct ? if not what is the right way to not waste any resources and utilize the mongoCLient instance in well manner ,please guide me
Generally, the MongoClient is a heavyweight component tailored for long lifetime (i.e. application lifetime.) Thus, you should rather open it once in the beginning and retain the reference.