kotlin coroutine - what is default scope? - kotlinx.coroutines

How does coroutines default scope work if i do not specify anything. lets take a look at this example:
class MyAppCompatActivity:AppCompatActivity{
fun getContact() {
GlobalScope.launch {
val contact = contacts.getContact() // suspended function
withContext(Dispatchers.Default) {
phoneContact.value = contact }
}
}
}
which simply updates the UI when a contact is retrieved. this is added to the global scope of so the coroutine life span can be that of the entire application.
but lets do the same thing again without a globalScope:
class MyAppCompatActivity:AppCompatActivity{
fun getContact() {
launch {
val contact = contacts.getContact() // suspended function
withContext(Dispatchers.Default) {
phoneContact.value = contact }
}
}
}
what is the lifespan of getContact now that i have removed the globalScope ? is it tied to the MyAppCompatActivity scope ?

Your code will fail to compile because launch must be called on a CoroutineScope object. This object specifies the lifespan of the coroutine. Since your activity does not implement a scope it will fail to compile or call a completely unrelated launch function.

I don't think this is a good idea anymore, as it looks like they're just functions for testing (doesn't launch coroutines). Maybe this was an API available previously, but now you should be using lifecycleScope to scope a coroutine to a fragment or activity, and viewModelScope to scope them to a View Model's life cycle. These are properties available in those classes by already.
Here's what I see when I try to use launch:

Related

NullPointerException when accessing case object in map

I am receiving a NullPointerException which I believe is due to the way objects are initialised but cannot find any supporting documentation.
I have this example code which illustrates the problem in Scala 2.12.7, I have found repeatable results in Scala 3.1.3 also:
abstract class Item(val collectionName: String)
abstract class ItemCollection(val name: String)
object TechItems extends ItemCollection("tech") {
// referencing 'name' from 'ItemCollection' superclass
case object TV extends Item(collectionName = name)
val items: Map[String, Item] = Map("tv" -> TV)
}
object Test1 extends App {
// prints 'tech'
println(TechItems.items.get("tv").map(_.collectionName))
}
object Test2 extends App {
// prints 'tech'
println(TechItems.TV.collectionName)
// throws NullPointerException
println(TechItems.items.get("tv").map(_.collectionName))
}
When running Test1, the code behaves as you'd expect. When running Test2, we now receive a NullPointerException when accessing the map after accessing the TV object directly.
When I no longer reference a field from the superclass, the issue no longer occurs:
...
object TechItems extends ItemCollection("tech") {
// using String instead of reference to superclass field
case object TV extends Item(collectionName = "mycollection")
val items: Map[String, Item] = Map("tv" -> TV)
}
...
object Test2 extends App {
// prints 'mycollection'
println(TechItems.TV.collectionName)
// prints 'Some(mycollection)'
println(TechItems.items.get("tv").map(_.collectionName))
}
My current understanding of how TechItems is initialised:
We access TechItems.TV.collectionName which begins initialising TechItems
An ItemCollection("tech") is created whose fields are then available inside of TechItems (depending on access modifiers of said superclass fields)
TV is initialised and references the superclass field name
items is initialised and references TV as a value for key "tv"
I am sure that understanding is wrong but that is what I am here to learn.
My current theory for the NullPointerException:
We access TechItems.TV.collectionName which begins initialising TechItems
items is initialised alongside TV, but items captures an uninitialised TV as null
Our access to TechItems.TV.collectionName returns the value of "tech"
TechItems.items.get("tv") returns Some(null) because TV at the point of initialising items was null, due to not being initialised.
NullPointerException is thrown
To me it feels like a somewhat farfetched theory. I am sure my lack of understanding is shown here and there is an explanation in some documentation that I have failed to find. Why do I get this NullPointerException? What is the initialisation order? And why does removing the reference to a superclass field affect this initialisation?
Wow, this is a good one!
Here is what I think is going on ...
Consider this "pseudo-java" code, that I believe more-or-less accurately reflects what is actually happening in the JVM:
class TechItems extends ItemCollection {
static MODULE = new TechItems("tech")
static class TV extends Item {
static MODULE = new TV(TechItems.MODULE.name)
}
val items = Map("tv" -> TV.MODULE)
}
So, now, when you do print(TechItems.TV.MODULE.collectionName),
TechItems.MODULE gets constructed, because we need to pull name out of it to create TV.
This constructor, runs to the Map("tv" -> TV.MODULE) line, and puts null into the map (TV.MODULE is still null - we are only figuring out what to pass to its constructor.
If you use "mycollection" instead of name, it becomes
static MODULE = new TV("mycollection"), which doesn't trigger TechItems constructor.
What happens when you don't access TV before looking at items? Well, in that case, TechItems.MODULE gets initialized first, so, by the time you get to the new TV thing, as part of constructing the items, TechItems.MODULE.name is already available, so TV.MODULE can be created and put into the map.
Dima is right. In fact, without inspecting the decompiled code, it would be harder to figure out what is happening under the hood. For simplicity, let's assume you just do these 2 calls in order (it will reproduce the issue):
println(TechItems.TV) // prints 'TV'
println(TechItems.items) // prints 'Map(tv -> null)'
Now let's decompile the code and show only the relevant parts. (I removed unnecessary code to be easier to follow) First these calls:
Predef$.MODULE$.println((Object)Main.TechItems$.TV$.MODULE$);
Predef$.MODULE$.println((Object)Main.TechItems$.MODULE$.items());
This was our Main. Now TechItems and TV:
public static class TechItems$ extends ItemCollection {
public static final TechItems$ MODULE$;
private static final Map<String, Main.Item> items;
static {
MODULE$ = new TechItems$();
items = (Map)Predef$.MODULE$.Map().apply((Seq)ScalaRunTime$.MODULE$.wrapRefArray(
(Object[])new Tuple2[] {
Predef.ArrowAssoc$.MODULE$.$minus$greater$extension(
Predef$.MODULE$.ArrowAssoc((Object)"tv"), (Object)TV$.MODULE$)
}));
}
public Map<String, Main.Item> items() {
return TechItems$.items;
}
public TechItems$() {
super("tech");
}
public static class TV$ extends Main.Item implements Product, Serializable {
public static final TV$ MODULE$;
static {
Product.$init$((Product)(MODULE$ = new TV$()));
}
public TV$() {
super(TechItems$.MODULE$.name());
}
}
When calling our first println statement we trigger the evaluation of TechItems.TV which translates to TechItems$.TV$.MODULE$. The MODULE$ is just a static final reference of TV that gets initialized in the static block of TV. To get initialized, it starts executing the static block, which in turn calls TV's constructor, new TV$() which in turn triggers the call to TechItems via: super(TechItems$.MODULE$.name());
This is the part where it gets interesting: TechItems$.MODULE$ is just the static final reference of TechItems, that was not yet referenced, so it was not yet initialized. Again, in the same manner, to get initialized, the static block of TechItems gets called. But this time the static block is different: It has to initialize TechItems$.MODULE$ and items as well, because both reside in the same static block.
Since we are in the middle of initializing TV$.MODULE$, and we just called items which requires the same reference - that we have not yet finished initializing, this reference is null at this point in time, so items is executed having TV$.MODULE$ as null.
After this, the static block of TechItems$.MODULE$ finishes, the static block of TechItems.TV finishes and we get printed TV at the console. The second print becomes self-explanatory. The call to items() returns TechItems$.items that we just evaluated in the previous call to TV, so items return Map(tv -> null) which gets printed.
Observations:
Using case object TV extends Item(collectionName = name) is precisely what triggers the issue. The logical idea is that, you do not want to evaluate items before TV finishes evaluation. So one can do 2 things: 1 - either not call TV before first calling items or just TechItems - which will trigger the evaluation of TV, and thus the correct initialization of items - or 2 (better solution) - delay evaluation of items as much as possible, until you really needed.
Naturally - the solution to the second point is to make items a lazy val. If we do this, the issue goes away, because items will no longer be evaluated unless explicitly referenced by us, and it will no longer trigger evaluation when calling just TV. And if we call items first, it will trigger TV's evaluation first. I can't show you the difference in the decompiled code because only the ScalaSignature differs: keywords like lazy are implemented as "pickled" signature bytes since these are easily picked up by the JVM through reflection.
Changing it to case object TV extends Item(collectionName = "mycollection") is also a fix. Since you no longer call super(TechItems$.MODULE$.name()); from TV at all, items's evaluation is no longer triggered when just TV is called. The call to TV's constructor becomes super("mycollection"), so the second print would then correctly evaluate items to Map(tv -> TV). This is why the null goes away when you change it.
This is an example of a circular dependency: TV "kind of" needs items and items needs TV - and the order of initialization really makes the difference between a working code and a code that throws nulls at unexpected times.
Since TV is presumably initialized lazy, making items lazy as well should theoretically remove the circular dependency.
An object definition in Scala behaves much like a lazy val with an annonymous class, that gets initialized on demand, the first time it is used.
So the first instinct when you see an object inside another object, is to assume the former object will be lazily initialized (unless explicitly referenced). Because items does reference TV explicitly, even if you don't call TV explicitly, TV will be evaluated either when referencing just TechItems or directly items, whichever comes first, because both are in the same static context, as we saw.

Multicast Delegates - C++

I would like to receive a multicast event from the LeapMotion plugin in C++. From their documentation, they mention the following things:
> On Hand Grabbed Event called when a leap hand grab gesture is
> detected. Signature: const FLeapHandData&, Hand, see FLeapHandData
>
> FLeapHandSignature OnHandGrabbed;
So in my .cpp file I added the following:
ALeapMotionGesture::ALeapMotionGesture()
{
PrimaryActorTick.bCanEverTick = true;
Leap = CreateDefaultSubobject<ULeapComponent>(TEXT("Leap"));
}
void ALeapMotionGesture::BeginPlay()
{
Super::BeginPlay();
if (Leap != nullptr) {
FScriptDelegate Delegate;
Delegate.BindUFunction(this, FName("HandGrabbed"));
Leap->OnHandGrabbed.Add(Delegate);
}
}
void ALeapMotionGesture::HandGrabbed(const FLeapHandData& Hand) {
UE_LOG(LogTemp, Warning, TEXT("Hand Grabbed"));
}
As it is the first time I'm using delegates in Unreal/C++, I would like to know how I could make it work?
It compiles fine however I do not receive any events.
Add UFUNCTION() on your function HandGrabbed
Short Answer
Replace:
void ALeapMotionGesture::BeginPlay()
{
Super::BeginPlay();
if (Leap != nullptr) {
FScriptDelegate Delegate;
Delegate.BindUFunction(this, FName("HandGrabbed"));
Leap->OnHandGrabbed.Add(Delegate);
}
}
with:
void ALeapMotionGesture::BeginPlay()
{
Super::BeginPlay();
if (Leap != nullptr) {
Leap->OnHandGrabbed.AddDynamic(this, &ALeapMotionGesture::HandGrabbed);
}
}
Long Answer
ULeapComponent::OnHandGrabbed is a FLeapHandSignature which is declared with DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam.
The LeapMotion README says to consult the Multi-cast documentation, but they are using dynamic delegates, so you actually need to read the Dynamic Delegates documentation. There you will see you should use the AddDynamic helper macro which generates the function name string for you.
Dynamic Delegates make use of helper macros that take care of generating the function name string for you.
From the Dynamic Delegates doc:
Dynamic Delegate Binding
BindDynamic( UserObject, FuncName )
Helper macro for calling BindDynamic() on dynamic delegates.
Automatically generates the function name string.
AddDynamic( UserObject, FuncName )
Helper macro for calling AddDynamic() on dynamic multi-cast delegates.
Automatically generates the function name string.
RemoveDynamic( UserObject, FuncName )
Helper macro for calling RemoveDynamic() on dynamic multi-cast
delegates. Automatically generates the function name string.
Side Note
Dynamic delegates are serialized, which sometimes results in unexpected behavior. For example, you can have delegate functions being called even though your code is no longer calling AddDynamic (because a serialized/saved actor serialized the results of your old code) or you might call AddDynamic even though the deserialization process already did that for you. To be safe, you probably should call RemoveDynamic before AddDynamic. Here's a snippet from FoliageComponent.cpp:
// Ensure delegate is bound (just once)
CapsuleComponent->OnComponentBeginOverlap.RemoveDynamic(this, &AInteractiveFoliageActor::CapsuleTouched);
CapsuleComponent->OnComponentBeginOverlap.AddDynamic(this, &AInteractiveFoliageActor::CapsuleTouched);

Get newly created id of a record before redirecting page

I would like to retrieve the id of a newly created record using javascript when I click on save button and just before redirecting page.
Do you have any idea please ?
Thank you !
One way to do this in Sugar 7 would be by overriding the CreateView.
Here an example of a CustomCreateView that outputs the new id in an alert-message after a new Account was successfully created, but before Sugar gets to react to the created record.
custom/modules/Accounts/clients/base/views/create/create.js:
({
extendsFrom: 'CreateView',
// This initialize function override does nothing except log to console,
// so that you can see that your custom view has been loaded.
// You can remove this function entirely. Sugar will default to CreateView's initialize then.
initialize: function(options) {
this._super('initialize', [options]);
console.log('Custom create view initialized.');
},
// saveModel is the function used to save the new record, let's override it.
// Parameters 'success' and 'error' are functions/callbacks.
// (based on clients/base/views/create/create.js)
saveModel: function(success, error) {
// Let's inject our own code into the success callback.
var custom_success = function() {
// Execute our custom code and forward all callback arguments, in case you want to use them.
this.customCodeOnCreate(arguments)
// Execute the original callback (which will show the message and redirect etc.)
success(arguments);
};
// Make sure that the "this" variable will be set to _this_ view when our custom function is called via callback.
custom_success = _.bind(custom_success , this);
// Let's call the original saveModel with our custom callback.
this._super('saveModel', [custom_success, error]);
},
// our custom code
customCodeOnCreate: function() {
console.log('customCodeOnCreate() called with these arguments:', arguments);
// Retrieve the id of the model.
var new_id = this.model.get('id');
// do something with id
if (!_.isEmpty(new_id)) {
alert('new id: ' + new_id);
}
}
})
I tested this with the Accounts module of Sugar 7.7.2.1, but it should be possible to implement this for all other sidecar modules within Sugar.
However, this will not work for modules in backward-compatibility mode (those with #bwc in their URL).
Note: If the module in question already has its own Base<ModuleName>CreateView, you probably should extend from <ModuleName>CreateView (no Base) instead of from the default CreateView.
Be aware that this code has a small chance of breaking during Sugar upgrades, e.g. if the default CreateView code receives changes in the saveModel function definition.
Also, if you want to do some further reading on extending views, there is an SugarCRM dev blog post about this topic: https://developer.sugarcrm.com/2014/05/28/extending-view-javascript-in-sugarcrm-7/
I resolved this by using logic hook (after save), for your information, I am using Sugar 6.5 no matter the version of suitecrm.
Thank you !

Activiti Java Service Task: Passivate w/out the need for receive task

this has already been answered but the solutions have not been working out for me.
Activiti asynchronous behaviour is fairly simple and only allows the user to enable a flag which tells activiti engine to insert such task in a execution queue (managing a pool of threads).
What i want is not to insert my java service task in a pool but to passivate its behaviour and only complete such task when an external signal is received and/or a callback is called.
My attempt:
class customAsyncTask extends TaskActivityBehavior {
override def execute(execution: ActivityExecution): Unit = {
val future = Future {
println(s"Executing customAsyncTask -> ${execution.getCurrentActivityName}, ${cur}")
}
future.onComplete {
case Success(result) => leave(execution)
case _ => // whatever
}
}
def signal(processInstanceId : String, transition : String) = {
val commandExecutor = main.processEngine.getProcessEngineConfiguration.asInstanceOf[ProcessEngineConfigurationImpl].getCommandExecutor
val command = new customSignal(processInstanceId, transition)
commandExecutor.execute(command)
}
}
On my previous code sample i have registered a scala future callback which when called will terminate the current activity and move to the next.
I also have a signal method which builds a custom signal that based on the processId and a name will call execution.take with the appropriate transition.
On both cases i am getting the following error (the bottom stack changes a little)
java.lang.NullPointerException
at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:636)
at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:629)
at org.activiti.engine.impl.persistence.entity.ExecutionEntity.take(ExecutionEntity.java:453)
at org.activiti.engine.impl.persistence.entity.ExecutionEntity.take(ExecutionEntity.java:431)
at org.activiti.engine.impl.bpmn.behavior.BpmnActivityBehavior.performOutgoingBehavior(BpmnActivityBehavior.java:140)
at org.activiti.engine.impl.bpmn.behavior.BpmnActivityBehavior.performDefaultOutgoingBehavior(BpmnActivityBehavior.java:66)
at org.activiti.engine.impl.bpmn.behavior.FlowNodeActivityBehavior.leave(FlowNodeActivityBehavior.java:44)
at org.activiti.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior.leave(AbstractBpmnActivityBehavior.java:47)
Unfortunately, it is highly likely that the engine is erasing the information concerning the execution when the execute method returns, even though no complete/leave/take has been called. Even though my callback has the execution object in context, when i query for information using its proccess ID all i receive is null.
So, what i am doing wrong here? How can i achieve the behaviour that i want?
I dont see anything specific, I would have said you need to extend a class that implements SignalableActivityBehavior, but I think TaskActivityBehavior actually does this.
While the stack indicates the NPE is coming from the leave(), I am confused why leave is calling "take" since take is a transition event and really should only happen on a task labeled as synchronous.
All I can offer is, Camunda have an example implementation that is similar to your scenario. You may be able to use this to help you:
https://github.com/camunda/camunda-bpm-examples/tree/master/servicetask/service-invocation-asynchronous
It seems that activiti uses thread local variables which means that when calling methods from the scala threads (scala Executor Context) would be pointless since they do not share the context.
To solve all i have to do from my callback is make a signal call much like if i were calling from a remote system. The only difference is that i do not need to save my process instance identifier.
The code looks as such:
class AsynchronousServiceTask extends AbstractBpmnActivityBehavior {
val exec_id : String = "executionId"
override def execute(execution : ActivityExecution) = {
val future = Future { println("Something") }
future onComplete {
case _ => myobject.callSignalForMe(execution.getId)
}
}
override def signal(execution : ActivityExecution, signalName : String, signalData : AnyRef) = {
println("Signal called, leaving current activity..")
leave(execution)
}
}
Basically, myobject holds the runTimeEngine and will inject the signal in a ThreadLocal context. All clean and working as intended.

How does the session state work in MVC 2.0?

I have a controller that stores various info (Ie. FormID, QuestionAnswerList, etc). Currently I am storing them in the Controller.Session and it works fine.
I wanted to break out some logic into a separate class (Ie. RulesController), where I could perform certain checks, etc, but when I try and reference the Session there, it is null. It's clear that the Session remains valid only within the context of the specific controller, but what is everyone doing regarding this?
I would imagine this is pretty common, you want to share certain "global" variables within the different controllers, what is best practice?
Here is a portion of my code:
In my BaseController class:
public List<QuestionAnswer> QuestionAnswers
{
get
{
if (Session["QuestionAnswers"] == null)
{
List<QuestionAnswer> qAnswers = qaRepository.GetQuestionAnswers(CurrentSection, UserSmartFormID);
Session["QuestionAnswers"] = qAnswers;
return qAnswers;
}
else
{
return (List<QuestionAnswer>)Session["QuestionAnswers"];
}
}
set
{
Session["QuestionAnswers"] = value;
}
}
In my first Controller (derived from BaseController):
QuestionAnswers = qaRepository.GetQuestionAnswers(CurrentSection, UserSmartFormID);
I stepped through the code and the above statement executes fine, setting the Session["QuestionAnswers"], but then when I try to get from another controller below, the Session["QuestionAnswers"] is null!
My second controller (also derived from BaseController):
List<QuestionAnswer> currentList = (List<QuestionAnswer>)QuestionAnswers;
The above line fails! It looks like the Session object itself is null (not just Session["QuestionAnswers"])
does it make a difference if you retrieve your session using
HttpContext.Current.Session("mySpecialSession") ''# note this is VB, not C#
I believe TempData will solve your problem, it operates with in the session and persists across multiple requests, however by default it will clear the stored data once you access it again, if that's a problem you can tell it to keep the info with the newly added Keep() function.
So in your case:
...
TempData["QuestionAnswers"] = qAnswers;
...
There's much more info at:
http://weblogs.asp.net/jacqueseloff/archive/2009/11/17/tempdata-improvements.aspx
Where are you accessing the session in the second controller? The session object is not available in the constructor because it is injected later on in the lifecycle.
Ok, finally got it working, although a bit kludgy. I found the solution from another related SO post.
I added the following to my BaseController:
public new HttpContextBase HttpContext
{
get
{
HttpContextWrapper context =
new HttpContextWrapper(System.Web.HttpContext.Current);
return (HttpContextBase)context;
}
}
Then set/retrieved my Session variables using HttpContext.Session and works fine!