I am testing the new CDI2.0 pre-release and I was expecting the BeanManager to be able to fire events asynchronously.
In CDI 1.2 I was doing this:
#Inject
BeanManager beanManager;
public void fireEvents() {
for (int i = 0; i < 10; i++) {
beanManager.fireEvent(new LightEvent("Light Event " + i));
beanManager.fireEvent(new HeavyEvent("Heavy Event " + i));
}
}
As I wanted to test async events, I saw that the BeanManager does not have a fireAsync() method. Instead, I have to fire the events the other way:
#Inject
private Event<LightEvent> lightEvent;
#Inject
private Event<HeavyEvent> heavyEvent;
public void fireAsyncEvents() {
for (int i = 0; i < 10; i++) {
lightEvent.fireAsync(new LightEvent("light " + i));
heavyEvent.fireAsync(new HeavyEvent("heavy " + i));
}
}
Now this works fine, but I have to define the events first.
Are there any plans to add a fireAsync() method to the Beanmanager ?
Because a decision was taken not to bloat BeanManager (BM) that much. To elaborate further, there were people asking for fireAsync as well as people asking for option to fire event directly from BM with selected qualifiers or type, or type and qualifiers. All of those are valid requirements but adding all this onto BM would bloat this "uber" entry point even more.
Therefore, a decision was made to instead create BeanManager#getEvent() from which you get into an Event interface directly. From there you can do select(..) based on desired qualifiers/types (or leave it default) and you then fire (for sync events) or fireAsync (for async).
To support my statements above, you can read more in related CDI issue or check the pull request directly.
So what you are after is already there and probably looks like this:
#Inject
BeanManager bm;
public void myMethod() {
// default one
bm.getEvent().fireAsync(new MyPayload());
// with selections of subtype and qualifiers
bm.getEvent().select(MyType.class, MyQualifier.class).fireAsync(new MyPayload());
}
Related
I looked at ByteBuddy documentation and have also looked at few of the Java Agent implementations that are using ByteBuddy. But I am still not very clear on what is the right way to use the ByteBuddy agent.
This is the code I used to bootstrap my agent:
public class ByteBuddyAgent {
public static void premain(String arguments, Instrumentation instrumentation) {
System.out.println("Bootstrapping ByteBuddy Agent");
new AgentBuilder.Default()
.with(new AgentBuilder.InitializationStrategy.SelfInjection.Eager())
.type(ElementMatchers.hasSuperClass(ElementMatchers.nameContains("Level1")))
.transform(new ByteBuddyTransformer()
.installOn(instrumentation);
}
private static class ByteBuddyTransformer implements AgentBuilder.Transformer{
#Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription,
ClassLoader classLoader, JavaModule module) {
return builder.method(ElementMatchers.named("printLevel"))
.intercept(Advice.to(MethodTracker.class));
}
}
}
This is my Advice class where I have tried different annotations supported by Advice and it worked fine.
public class MethodTracker {
#Advice.OnMethodEnter
public static Object onMethodBegin(#Advice.This Object invokedObject, #Advice.AllArguments Object[] arguments,
#Advice.FieldValue("name") Object fieldValue, #Advice.Origin Object origin,
#Advice.Local("localVariable") Object localVariable) {
System.out.println("=======on Method Begin Running with ByteBuddy=======, " + invokedObject);
System.out.println("======Printing arguments=======");
for(Object obj: arguments){
System.out.println("Argument:: " + obj);
}
localVariable = "Gunika";
System.out.println("FieldValue:: " + fieldValue);
System.out.println("Origin:: " + origin);
return "ReturningStateFromOnMethodBegin";
}
#Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void onMethodEnd(#Advice.This Object invokedObject, #Advice.Return Object returnValue,
#Advice.FieldValue("name") Object fieldValue, #Advice.Enter Object state,
#Advice.Local("localVariable") Object localVariable){
System.out.println("=======on Method End Running with ByteBuddy======= " + invokedObject);
System.out.println("Return value is " + returnValue);
System.out.println("FieldValue:: " + fieldValue);
System.out.println("FieldValue:: " + fieldValue);
System.out.println("State:: " + state);
System.out.println("LocalVariable:: " + localVariable);
}
}
The questions that I have are as follows:
Right now in my sample app, I have just tried matching with 1 rule.
But if there are ānā rules that I want to apply what is the right away to achieve that.
There are initial set of rules that are applied/provided to the agent. Now let's say at some point of time I want to add another rule. What is the correct way to achieve that?
Does the AgentBuilder instance that we create should be created only once in the Java Agent?
Any other information that should be taken care while using ByteBuddy agent would be helpful.
Advice.to(MethodTracker.class) is pretty expensive. If you instrument many classes and want to spend the memory, I'd recommend you to reuse the instance, it is immutable.
Other than that, #Advice.AllArguments is more expensive than using specialized advice classes that read particular arguments, if you can afford it. This is however rather a JVM question than a Byte Buddy-specific one. You can use -Dnet.bytebuddy.dump=/some/folder to see what byte code is generated. Expensiveness often lies burried what constructs you go for.
I have my version column defined like this
#org.springframework.data.annotation.Version
protected long version;
With Spring Data JDBC it's always trying to INSERT. Updates are not happening. When I debug I see that, PersistentEntityIsNewStrategy is being used which is the default strategy. It has isNew() method to determine the state of the entity being persisted. I do see that version and id are used for this determination.
But my question is who is responsible to increment the version column after every save, so that when the second time .save() is called, the isNew() method can return false.
Should we do fire a BeforeSaveEvent and handle the incrementation of Version column? Would that be good enough to handle the OptimisticLock ?
Edit
I added an ApplicationListener to listen to BeforeSaveEvent like this.
public ApplicationListener<BeforeSaveEvent> incrementingVersion() {
return event -> {
Object entity = event.getEntity();
if (BaseDataModel.class.isAssignableFrom(entity.getClass())) {
BaseDataModel baseDataModel = (BaseDataModel) entity;
Long version = baseDataModel.getVersion();
if (version == null) {
baseDataModel.setVersion(0L);
} else {
baseDataModel.setVersion(version + 1L);
}
}
};
}
So now the version column works, but rest of Auditable fields #CreatedAt, #CreatedBy,#LastModifiedDate and #LastModifiedBy are not set!!
Edit2
Created a new ApplicationListener like below. In this case both my custom listener and Spring's RelationalAuditingListener are getting called. But still it doesn't solve the problem. Because the order of listeners[custom one followed by spring's] making the markAudited to invoke markUpdated instead of markCreated, since the version column is already incremented. I tried to make my Listener be the LOWEST_PRECEDENCE still no luck.
My custom listener here
public class CustomRelationalAuditingEventListener
implements ApplicationListener<BeforeSaveEvent>, Ordered {
#Override
public void onApplicationEvent(BeforeSaveEvent event) {
Object entity = event.getEntity();
// handler.markAudited(entity);
if (BaseDataModel.class.isAssignableFrom(entity.getClass())) {
BaseDataModel baseDataModel = (BaseDataModel) entity;
if (baseDataModel.getVersion() == null) {
baseDataModel.setVersion(0L);
} else {
baseDataModel.setVersion(baseDataModel.getVersion() + 1L);
}
}
}
#Override
public int getOrder() {
return LOWEST_PRECEDENCE;
}
}
Currently, you have to increment the version manually and there is no optimistic locking, i.e. the version is only used for checking if an entity is new.
There is an open issue for support of optimistic locking and there is even a PR open for it.
Therefore it is likely that this feature will be available with an upcoming 1.1 milestone.
I use the libpd4unity package to communicate with Pure Data. I receive a bang from Pure Data with LibPD.Bang. On a bang event I play sound by FMOD.
Problem is, that I receive bangs frequently, for example once every 500 ms but event doesn't trigger in specific length of frame. Usually length change 1 frame less or more.
Is there a solution for this problem? For example a framerate independent event? I want to know if event (delegate) in Unity3D is framerate independent or not.
Because there is tempo for playing each sound and just 1 frame ruins rhythm.
I need to sync sounds for playing by each separate bang.
Regarding your question on whether delegates are dependent or independent from Unity's framerate, there's no straight answer. It depends on how your delegates are called. Are they called from a thread? Are they executed in a thread?
Coroutines are not framerate independent, they are executed in Unity's loop.
The following script should shine a light on the difference between handling delegates in coroutines and in threads.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
public class DelegatesAndFramerate : MonoBehaviour {
delegate void MyDelegate();
MyDelegate myDelegate1; // done with coroutines
MyDelegate myDelegate2; // done with threads
Thread thread;
bool threadDone = false;
private int frameCount = 0;
private int delegate1CallCount = 0;
private int delegate2CallCount = 0;
private int callerLoopsCount_coroutine = 0;
private int callerLoopsCount_thread = 0;
void Start () {
myDelegate1 += Elab1;
myDelegate2 += Elab2;
StartCoroutine(CallerCoroutine());
thread = new Thread(new ThreadStart(CallerThread));
thread.Start();
}
void Update()
{
frameCount++;
}
void Elab1()
{
delegate1CallCount++;
}
void Elab2()
{
delegate2CallCount++;
}
IEnumerator CallerCoroutine()
{
while(true)
{
callerLoopsCount_coroutine++;
myDelegate1();
yield return null;
}
}
void CallerThread()
{
while(!threadDone)
{
callerLoopsCount_thread++;
myDelegate2();
}
}
void OnDestroy()
{
Debug.Log("Frame Count: " + frameCount);
Debug.Log("Delegate Call Count (Coroutine): " + delegate1CallCount);
Debug.Log("Delegate Call Count (Thread): " + delegate2CallCount);
Debug.Log("Caller Loops Count (Coroutine): " + callerLoopsCount_coroutine);
Debug.Log("Caller Loops Count (Thread): " + callerLoopsCount_thread);
threadDone = true;
thread.Join();
}
}
If you attach it to a GameObject and let Unity play for some seconds you'll see that the times the delegate was called from a coroutine is equal to the number of executed frames whilst the times the delegate was called from the thread will be way bigger.
I have experience in interfacing softwares similar to Pure Data and I think what you need is a (rather typical) thread with all your delegates there, create a queue of commands for Unity and digest it in Unity's Update.
Not knowing libPD in the specific this might not be the best practice for the case but it is a widely used approach. Basically the producer-consumer pattern.
Basing on the example GUITextScript.cs, libPD only requires you to subscribe to the right delegates. You don't have control on when these are executed, the library has; so if you keep having this issue it's worth submitting a bug report to the developers I guess.
I am looking for a way to subscribe to events like Storing a specific object type to ServiceStack.Redis.
For example I may
using (var redisClient = new RedisClient())
using (var redisMyObjects = redisClient.As<MyObject>())
{
redisMyObjects.Store(myObject);//<-- I want this to trigger an event somehow
}
Is there anything like a OnStore event which I can hook too, anything out of the box? if not, is there any recommendation about how this should be done?
I don't think there is anything you can hook into (could be wrong).
Two options that came to mind:
1 - Make an extension method
2 - Publish a message to store your object and have a handler that listens for a response and does something. This is probably overkill since it's heading into the publish/subscribe realm. But, I think, worth looking into. (Basic example here and see Pub/Sub here).
Extension Method
public static class RedisClientExtensions
{
public static void StoreWithTrigger<T>(this IRedisTypedClient<T> redisClient, T value, Action<T> trigger)
{
redisClient.Store(value);
trigger(value);
}
}
Using ExtensionMethod
public void MyMethod()
{
using (var redisClient = new RedisClient())
using (var redisMyObjects = redisClient.As<MyObject>())
{
redisMyObjects.StoreWithTrigger<MyObject>(new MyObject(), TriggerEvent);//<-- I want this to trigger an event somehow
}
}
private void TriggerEvent<T>(T value)
{
//dosomething
}
Hope this gives you some ideas.
I have an array of CheckboxField[] elements that I need to dynamically initialize. My sample code is -
class abc extends MainScreen implements FieldChangeListener {
CheckboxField[] boxField;
abc() {
.
.
.
boxField = new CheckboxField[length];
VerticalFieldManager vfm = new VerticalFieldManager();
for(int i=0; i<length; i++) {
boxField[i] = new CheckboxField(var[i], false);
boxField[i].setChangeListener(this);
vfm.add(boxField[i]);
}
add(vfm);
}
public void fieldChanged(Field field, int context) {
// The idea is to disable all the other checkboxes when one
// is clicked.
boxField[0].setChecked(false); // Gives stackoverflow error on JVM.
}
}
Any help?
Edit: The problem only seems to be with .setChecked(boolean)
I've tried chkboxField[0].setFont(), chkboxField.getChecked(), both of them seem to work.
So, what's apparently happening is boxField[i].setChecked(false) calls the FieldChangeListener again, and this loops infinitely till the stack blows.
I was told to use
if(context != FieldChangeListener.PROGRAMMATIC) {
boxField[i].setChecked(false);
}
Based on your comment in the FieldChanged method, it sounds like you have mutually exclusive checkboxes (that is, you have a group of checkboxes and when any one is checked, all the rest should be unchecked).
If so, you may want to consider using the RadioButtonField instead. You can stick your radio buttons into a RadioButtonGroup and then the BlackBerry will take care of unchecking for you.