Eager-Load all entries of a List<Ref<T>> - java

I currently use this pattern to store lists of types that are also Objectify entities:
#Entity
class Test{
private List<Ref<T>> data = new ArrayList<>();
public List<T> getTees(){
List<T> tmp = new ArrayList<>(this.data.size()); // Is the entire list loaded here?
for (Ref<T> d : this.data) {
tmp.add(d.get()); // or every single entry here??
}
return tmp;
}
}
The question is: will the first time the data-field is used load the entire list (the data that Ref "points" to) from the data-storage, or will the Ref<T>.get()-method load each entry individually?
If so, how can a bulk-load the entire list at once?
Note: I don't always need the list, that's why it doesn't have the #Load-annotation.

Objectify will not load anything referenced unless you .get() it explicitly, this results in individual fetches, or you tell it to auto load all the things via #Load. That speeds up loading overall because it can batch process the request instead of forming several individual ones.
If by "I don't always need the list" you mean that you have distinct cases of "need" vs "not need", take a look at load groups, essentially a way to turn the #Load annotation on or off.
https://code.google.com/p/objectify-appengine/wiki/Entities#Relationships has examples like yours
https://code.google.com/p/objectify-appengine/wiki/BasicOperations#Load_Groups to turn on/off auto loading
There is btw a way to load a list of Refs in a single batch using
Map<Key<T>,T> Loader#refs(Iterable<Ref<T>> refs)
public List<T> getTees(){
Collection<T> values = ofy().load().refs(data).values();
return new ArrayList<T>(values);
}

Related

How to flatMap to database in Apache Flink?

I am using Apache Flink trying to get JSON records from Kafka to InfluxDB, splitting them from one JSON record into multiple InfluxDB points in the process.
I found the flatMap transform and it feels like it fits the purpose. Core code looks like this:
DataStream<InfluxDBPoint> dataStream = stream.flatMap(new FlatMapFunction<JsonConsumerRecord, InfluxDBPoint>() {
#Override
public void flatMap(JsonConsumerRecord record, Collector<InfluxDBPoint> out) throws Exception {
Iterator<Entry<String, JsonNode>> iterator = //...
while (iterator.hasNext()) {
// extract point from input
InfluxDBPoint point = //...
out.collect(point);
}
}
});
For some reason, I only get one of those collected points streamed into the database.
Even when I print out all mapped entries, it seems to work just fine: dataStream.print() yields:
org.apache.flink.streaming.connectors.influxdb.InfluxDBPoint#144fd091
org.apache.flink.streaming.connectors.influxdb.InfluxDBPoint#57256d1
org.apache.flink.streaming.connectors.influxdb.InfluxDBPoint#28c38504
org.apache.flink.streaming.connectors.influxdb.InfluxDBPoint#2d3a66b3
Am I misunderstanding flatMap or might there be some bug in the Influx connector?
The problem was actually related to the fact that a series (defined by its tagset and measurement as seen here) in Influx can only have one point per time, therefore even though my fields differed, the final point overwrote all previous points with the same time value.

Enumerate Custom Slot Values from Speechlet

Is there any way to inspect or enumerate the Custom Slot Values that are set-up in your interaction model? For Instance, Say you have an intent schema with the following intent:
{
"intent": "MySuperCoolIntent",
"slots":
[
{
"name": "ShapesNSuch",
"type": "LIST_OF_SHAPES"
}
]
}
Furthermore, you've defined the LIST_OF_SHAPES Custom Slot to have the following Values:
SQUARE
TRIANGLE
CIRCLE
ICOSADECAHECKASPECKAHEDRON
ROUND
HUSKY
Question: is there a method I can call from my Speechlet or my RequestStreamHandler that will give me an enumeration of those Custom Slot Values??
I have looked through the Alexa Skills Kit's SDK Javadocs Located Here
And I'm not finding anything.
I know I can get the Slot's value that is sent in with the intent:
String slotValue = incomingIntentRequest.getIntent().getSlot("LIST_OF_SHAPES").getValue();
I can even enumerate ALL the incoming Slots (and with it their values):
Map<String, Slot> slotMap = IncomingIntentRequest.getIntent().getSlots();
for(Map.Entry<String, Slot> entry : slotMap.entrySet())
{
String key = entry.getKey();
Slot slot = (Slot)entry.getValue();
String slotName = slot.getName();
String slotValue = slot.getValue();
//do something nifty with the current slot info....
}
What I would really like is something like:
String myAppId = "amzn1.echo-sdk-ams.app.<TheRestOfMyID>";
List<String> posibleSlotValues = SomeMagicAlexaAPI.getAllSlotValues(myAppId, "LIST_OF_SHAPES");
With this information I wouldn't have to maintain two separate "Lists" or "Enumerations"; One within the interaction Model and another one within my Request Handler. Seems like this should be a thing right?
No, the API does not allow you to do this.
However, since your interaction model is intimately tied with your development, I would suggest you check in the model with your source code in your source control system. If you are going to do that, you might as well put it with your source. Depending on your language, that also means you can probably read it during run-time.
Using this technique, you can gain access to your interaction model at run-time. Instead of doing it automatically through an API, you do it by best practice.
You can see several examples of this in action for Java in TsaTsaTzu's examples.
No - there is nothing in the API that allows you to do that.
You can see the full extent of the Request Body structure Alexa gives you to work with. It is very simple and available here:
https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference#Request%20Format
Please note, the Request Body is not to be confused with the request, which is a structure in the request body, with two siblings: version and session.

Google App Engine Objectify - load single objects or list of keys?

I am trying to get a grasp on Google App Engine programming and wonder what the difference between these two methods is - if there even is a practical difference.
Method A)
public Collection<Conference> getConferencesToAttend(Profile profile)
{
List<String> keyStringsToAttend = profile.getConferenceKeysToAttend();
List<Conference> conferences = new ArrayList<Conference>();
for(String conferenceString : keyStringsToAttend)
{
conferences.add(ofy().load().key(Key.create(Conference.class,conferenceString)).now());
}
return conferences;
}
Method B)
public Collection<Conference> getConferencesToAttend(Profile profile)
List<String> keyStringsToAttend = profile.getConferenceKeysToAttend();
List<Key<Conference>> keysToAttend = new ArrayList<>();
for (String keyString : keyStringsToAttend) {
keysToAttend.add(Key.<Conference>create(keyString));
}
return ofy().load().keys(keysToAttend).values();
}
the "conferenceKeysToAttend" list is guaranteed to only have unique Conferences - does it even matter then which of the two alternatives I choose? And if so, why?
Method A loads entities one by one while method B does a bulk load, which is cheaper, since you're making just 1 network roundtrip to Google's datacenter. You can observe this by measuring time taken by both methods while loading a bunch of keys multiple times.
While doing a bulk load, you need to be cautious about loaded entities, if datastore operation throws exception. Operation might succeed even when some of the entities are not loaded.
The answer depends on the size of the list. If we are talking about hundreds or more, you should not make a single batch. I couldn't find documentation what is the limit, but there is a limit. If it not that much, definitely go with loading one by one. But, you should make the calls asynchronous by not using the now function:
List<<Key<Conference>> conferences = new ArrayList<Key<Conference>>();
conferences.add(ofy().load().key(Key.create(Conference.class,conferenceString));
And when you need the actual data:
for (Key<Conference> keyConference : conferences ) {
Conference c = keyConference.get();
......
}

How to get all existing groups in jcr?

I want to fetch a list of all existing groups in CQ5 JCR. I am able to fetch a list of all existing users in the JCR using following code,
UserManager userManager = jkrSession.getUserManager();
final List<String> users = new ArrayList<String>();
Iterator<Authorizable> iter = userManager.findAuthorizables(
"jcr:primaryType", "rep:User");
while (iter.hasNext()) {
Authorizable auth = iter.next();
if (!auth.isGroup()) {
users.add(auth.getID());
}
}
I haven't found any way to get a list of all existing users. Although, I can see the parent nodes /home/users and /home/groups and I can iterate over the child nodes to fetch users and groups.
I am looking for an easier way out.
The title of your question doesn't sync with your question's content.
First, the following code is really unnecessary, as you are searching for rep:User, and hence only users would be available in the iterator, thereby making your if check fail every time.
Authorizable auth = iter.next();
if (!auth.isGroup()) {
users.add(auth.getID());
}
Hence the while loop could be rewritten as
users.add(iter.next().getID());
Second, if it is the list of all existing groups that you want to fetch, then you can use
Iterator<Authorizable> iter = userManager.findAuthorizables(
"jcr:primaryType", "rep:Group");
This would return only the groups that are present in your instance.
But, if it is both, users and groups that you want to fetch, may be you can try this.
Iterator<Authorizable> iter = userManager.findAuthorizables(
"profile/jcr:primaryType", "nt:unstructured", UserManager.SEARCH_TYPE_AUTHORIZABLE);
This would return all the authorizables that are present in the instance. It is not mandatory that you have to specify only profile/jcr:primaryType and nt:unstructured as the property and value. You can use the relative path to any property which would be present in all the authorizables, containing the same value if you want to list all the authorizables(in my case profile/jcr:primaryType caught my eye first), else the results would be filtered to those authorizables for whom the property value matches.
For further reference you can check the docs.

EMF model comparison with EMF Compare

I have two versions of the EMF instances that are based on the same ecore model. I need to prepare a list of things that changed from v1 to v2 in the following format
For each object in the model
Object Name:
Modified Attributes:
Added Attributes:
Deleted Attributes:
Each of these emf instance files are actually a representation of the DB data. User doesn't directly change the DB but they change the emf instance file. The tool need to identify these changes and then need to generate the necessary DML statements. Appreciate if a pseudo code can be presented on how to achieve this or is there a better alternative. Below is the code I currently have
public Comparison compare()
{
// Load the two input models
ResourceSet resourceSet1 = new ResourceSetImpl();
ResourceSet resourceSet2 = new ResourceSetImpl();
String xmi1 = "src/test/java/com/equifax/ic/provisioning/service/v1.xmi";
String xmi2 = "src/test/java/com/equifax/ic/provisioning/service/v2.xmi";
load(xmi1, resourceSet1);
load(xmi2, resourceSet2);
// Configure EMF Compare
EMFCompare comparator = EMFCompare.builder().build();
// Compare the two models
IComparisonScope scope = EMFCompare.createDefaultScope(resourceSet1, resourceSet2);
return comparator.compare(scope);
}
#Test
public void testCompare()
{
Comparison comparison = compare();
List<Diff> differences = comparison.getDifferences();
for(Diff d: differences)
{
System.err.println("d.getKind(): "+d.getKind());
System.err.println("d.getMatch(): " + d.getMatch());
System.err.println("State: " + d.getState());
}
assertSame(Integer.valueOf(12), Integer.valueOf(differences.size()));
}
Output
d.getKind(): ADD
d.getMatch(): MatchSpec{left=BillableSystemEvent#1b5340c Application Processed, right=BillableSystemEvent#16c163f Application Processed, origin=<null>, #differences=2, #submatches=2}
State: UNRESOLVED
d.getKind(): DELETE
d.getMatch(): MatchSpec{left=BillableSystemEvent#1b5340c Application Processed, right=BillableSystemEvent#16c163f Application Processed, origin=<null>, #differences=2, #submatches=2}
State: UNRESOLVED
I cannot say I really understand everything you're trying to achieve, but as I understand it, you are not really interested in the format EMF Compare uses for its differences. Rather, you are trying to generate a differente kind of representation for the diffs.
You might be interested in just reimplementing an IDiffProcessor. Diff processors are notified every time we detect a change. By default we create our "Diff" instances... Nothing prevents you from generating DML statements instead. You can get a quick overview of the IDiffProcessor API here.

Categories

Resources