I have written custom event notifier and registered it in HystrixPlugins. I have requirement like need to send notifications when Circuit is opened and closed. To track circuit-open I can use below event type
HystrixEventType.SHORT_CIRCUITED
but what about transition from Open to close? is there any way in hystrix to track circuit is close now which was opened previously?.
Below is my Event notifier.
public class CircuitBreakerHystrixEventNotifier extends HystrixEventNotifier{
#Resource
private List<HystrixNotification> notificationHandlers;
public CircuitBreakerHystrixEventNotifier(){
}
public void markEvent(HystrixEventType eventType, HystrixCommandKey key) {
super.markEvent(eventType, key);
if(notificationHandlers != null && notificationHandlers.size() > 0){
for (HystrixNotification notificationHandler : notificationHandlers){
notificationHandler.notify(eventType, key);
}
}
}
}
Related
I'm trying to set a user's attribute after they register in my custom Keycloak extension. My event listener implementation looks as follows:
#AutoService(EventListenerProviderFactory.class)
public class EventListener implements EventListenerProvider {
private final KeycloakSession session;
public EventListener(KeycloakSession session) {
this.session = session;
}
#Override
public void onEvent(Event event) {
if (event.getType() != EventType.REGISTER)
return;
RealmModel realm = session.realms().getRealm(event.getRealmId());
UserModel user = session.users().getUserById(realm, event.getUserId());
user.setSingleAttribute("hello", "world");
}
#Override
public void onEvent(AdminEvent event, boolean includeRepresentation) {
}
#Override
public void close() {
}
}
My extension is recognized by Keycloak and successfully triggers onEvent() when an event occurs (hence why I didn't include the factory class).
However, the attribute isn't added to the user. How do I actually persist the changes to the user?
While searching for a solution to the above, I came across this discussion of a very similar issue. Extending RegistrationUserCreation instead of EventListenerProvider and using the solution given by #dvlpphb did actually manage to solve my problem; however, the solution only worked when overriding the RegistrationUserCreation's validate() method, which is called every time the user attempts to register.
If anyone knows a way to set a user attribute without EventListenerProvider through RegistrationUserCreation's success() callback, that would also solve my issue.
Thank you!
I get the fact that it might take more than 10 lines of code (hopefully not more than 50), but I was wondering if you could help me anyway.
I'm trying to update one user's UI thread at runtime, based on another user's input. I've created a basic project which implements three predefined users (jim, tom and threeskin). I'd like to send a message from jim to tom and have it appear as a new Label object in tom's UI, without threeskin ever knowing about it, even though they're all logged in. Oh, and jim shouldn't have to refresh his page. The label should just spawn on screen out of it's own accord.
To say that I'd appreciate some help would be the understatement of the decade.
public class User {
public String nume;
public User(String nume) {
super();
this.nume = nume;
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
public class Engine implements ServletContextListener {
public static ArrayList<User>userbase;
public void contextDestroyed(ServletContextEvent arg0) { }
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("This code is running at startup");
userbase =new ArrayList<User>();
userbase.add(new User("jim"));userbase.add(new User("tom"));userbase.add(new User("threeskin"));
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
public class InfigeUI extends UI {
User us3r;
#WebServlet(value = "/*", asyncSupported = true)
#VaadinServletConfiguration(productionMode = false, ui = InfigeUI.class)
public static class Servlet extends VaadinServlet {}
protected void init(VaadinRequest request) {
VerticalLayout everything=new VerticalLayout();
setContent(everything);
if (us3r==null){everything.addComponent(auth());}else{everything.addComponent(main());}
}
ComponentContainer auth(){
final VerticalLayout layout = new VerticalLayout();
layout.setMargin(true);
TextField userField=new TextField();
Button login = new Button("Log in");
login.addClickListener(new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
us3r=login(userField.getValue());
if (us3r!=null){
saveValue(InfigeUI.this, us3r);
layout.removeAllComponents();
layout.addComponent(main());
}else{Notification.show("I only know jim, tom and threeskin. Which one are you?");}}
});
layout.addComponent(userField);
layout.addComponent(login);
return layout;
}
User login(String nume){
for (int i=0;i<Engine.userbase.size();i++){
if (nume.equals(Engine.userbase.get(i).nume)){return Engine.userbase.get(i);}
}
return null;
}
static void saveValue(InfigeUI ui,User value){
ui.us3r=value;
ui.getSession().setAttribute("something", value);
VaadinService.getCurrentRequest().getWrappedSession().setAttribute("something", value);
}
ComponentContainer main(){
VerticalLayout vl=new VerticalLayout();
Label label=new Label("This is the post-login screen");
String name=new String(us3r.nume);
Label eticheta=new Label(name);
TextField to=new TextField("Send to");
TextField message=new TextField("Message");
Button sendNow=new Button("Send now!");
vl.addComponent(eticheta);
vl.addComponent(label);
vl.addComponent(eticheta);
vl.addComponent(to);
vl.addComponent(message);
vl.addComponent(sendNow);
return vl ;
}
}
Basically you want three things
UI updates for a user which does no action himself, or in other words a message sent from the server to the browser. To enable this, you need to annotate the UI class using #Push. Otherwise, the update will only be shown when the user does something which causes a server visit, e.g. clicks a button
Some way of sending messages between UI instances (there is one UI instance per user). You can use some message bus implementation for this (CDI, Spring, ...) or you can make a simple on using a static field (static fields are shared between all users). See e.g. https://github.com/Artur-/SimpleChat for one way of doing it. It's also a good idea here to avoid all *.getCurrent methods as they in many cases will refer to another UI than you think (e.g. sender when you are in the receiver code), and you will do something else than you intend.
Safely update a UI when a message arrives. This is done using UI.access, also visible in the chat example.
First of all you need to enable the server push on your project help
based on Vaadin Documentation.
However, below code example will give what you want:
Create an Broadcast Listener Interface:
public interface BroadcastListener {
public void receiveBroadcast(final String message);
}
The Broadcaster Class:
public class Broadcaster {
private static final List<BroadcastListener> listeners = new CopyOnWriteArrayList<BroadcastListener>();
public static void register(BroadcastListener listener) {
listeners.add(listener);
}
public static void unregister(BroadcastListener listener) {
listeners.remove(listener);
}
public static void broadcast(final String message) {
for (BroadcastListener listener : listeners) {
listener.receiveBroadcast(message);
}
}
}
Your UI with Push Enalbed (via Annotation):
#Push
public class BroadcasterUI extends UI implements BroadcastListener {
#Override
protected void init(VaadinRequest request) {
final VerticalLayout layout = new VerticalLayout();
layout.setMargin(true);
setContent(layout);
final TextArea message = new TextArea("",
"The system is going down for maintenance in 10 minutes");
layout.addComponent(message);
final Button button = new Button("Broadcast");
layout.addComponent(button);
button.addClickListener(new Button.ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
Broadcaster.broadcast(message.getValue());
}
});
// Register broadcast listener
Broadcaster.register(this);
}
#Override
public void detach() {
Broadcaster.unregister(this);
super.detach();
}
#Override
public void receiveBroadcast(final String message) {
access(new Runnable() {
#Override
public void run() {
Notification n = new Notification("Message received",
message, Type.TRAY_NOTIFICATION);
n.show(getPage());
}
});
}
you can find the full link here.
I'm currently working on a eclipse e4 RCP application and I have a part that serves as a job manager where the user can see all active jobs and their progresses, like one in eclipse. The problem is now that the user can open the progress part by double clicking in the toolbar and he should also be able to close the progress part whenever he wants, but instead of disposing the part I want to just make it invisible.
I thought at first this shouldn't be a problem because I can set the part to be not visible, but the problem is how to catch the closing event and process it by my way. Is there any event, interfaces or listeners I can implement to catch the closing event and prevent the part from getting disposed?
You can implement a CustomSaveHandler and replace the Default Eclipse Save Handler with a Processor. In that SaveHandler you can control if the Part shoud get closed or not. So you could do not close it and make it invisible.
ExampleCode:
public class ReplaceSaveHandlerProcessor {
#Named("your.id.to.window")
#Inject
MWindow window;
#Inject
IEventBroker eventBroker;
#Execute
void installIntoContext() {
eventBroker.subscribe(UIEvents.Context.TOPIC_CONTEXT, new EventHandler() {
#Override
public void handleEvent(final Event event) {
if (UIEvents.isSET(event)) {
if (window.equals(event.getProperty("ChangedElement")) && (window.getContext() != null)) {
window.getContext().runAndTrack(new RunAndTrack() {
private final ISaveHandler saveHandler = new CustomSaveHandler();
#Override
public boolean changed(final IEclipseContext context) {
Object getSaveHandlerValue = context.get(ISaveHandler.class);
if (!saveHandler.equals(getSaveHandlerValue)) { // prevents endless loop
ContextInjectionFactory.inject(saveHandler, window.getContext());
context.set(ISaveHandler.class, saveHandler);
}
return true; // ture keeps tracking and the saveHandler as the only opportunity
}
});
}
}
}
});
}
}
You have to define a Extention for ExtentionPoint org.eclipse.e4.workbench.model
With Your ReplaceSaveHandlerProcessor. (You have to declare the window id as "element" in this extention. (Added Screenshot: )
The CustomSaveHandler have to implement the ISaveHandler interface. In its Methods ypu can say if the Part should realy be closed.
public class CustomSaveHandler implements ISaveHandler {
#Override
public boolean save(MPart dirtyPart, boolean confirm) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean saveParts(Collection<MPart> dirtyParts, boolean confirm) {
// TODO Auto-generated method stub
return false;
}
#Override
public Save promptToSave(MPart dirtyPart) {
// TODO Auto-generated method stub
return null;
}
#Override
public Save[] promptToSave(Collection<MPart> dirtyParts) {
// TODO Auto-generated method stub
return null;
}
}
I have an Activity A (not the main Activity) that launches a Service S that does some stuff in the background and, in the meanwhile, should made some changes to the UI of A.
Let's just say that S count from 0 to 100 and A should display this count in Real-Time. Since the real job of S is quite more complicated and CPU-consuming, I do not want to use AsyncTask for it (indeed "AsyncTasks should ideally be used for short operations (a few seconds at the most.) [...]") but just a regular Service started in a new Thread (an IntentService would be fine as well).
This is my Activity A:
public class A extends Activity {
private static final String TAG = "Activity";
private TextView countTextView; // TextView that shows the number
Button startButton; // Button to start the count
BResultReceiver resultReceiver;
/**
* Receive the result from the Service B.
*/
class BResultReceiver extends ResultReceiver {
public BResultReceiver(Handler handler) {
super(handler);
}
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
switch ( resultCode ) {
case B.RESULT_CODE_COUNT:
String curCount = resultData.getString(B.RESULT_KEY_COUNT);
Log.d(TAG, "ResultReceived: " + curCount + "\n");
runOnUiThread( new UpdateUI(curCount) ); // NOT WORKING AFTER onResume()!!!
break;
}
}
}
/**
* Runnable class to update the UI.
*/
class UpdateUI implements Runnable {
String updateString;
public UpdateUI(String updateString) {
this.updateString = updateString;
}
public void run() {
countTextView.setText(updateString);
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.counter);
countTextView = (TextView) findViewById(R.id.countTextView);
startButton = (Button) findViewById(R.id.startButton);
resultReceiver = new BResultReceiver(null);
}
public void startCounting(View view) {
startButton.setEnabled(false);
//Start the B Service:
Intent intent = new Intent(this, B.class);
intent.putExtra("receiver", resultReceiver);
startService(intent);
}
}
And this is my Service B:
public class B extends Service {
private static final String TAG = "Service";
private Looper serviceLooper;
private ServiceHandler serviceHandler;
private ResultReceiver resultReceiver;
private Integer count;
static final int RESULT_CODE_COUNT = 100;
static final String RESULT_KEY_COUNT = "Count";
/**
* Handler that receives messages from the thread.
*/
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
while ( count < 100 ) {
count++;
//Sleep...
sendMessageToActivity(RESULT_CODE_COUNT, RESULT_KEY_COUNT, count.toString());
}
//Stop the service (using the startId to avoid stopping the service in the middle of handling another job...):
stopSelf(msg.arg1);
}
}
#Override
public void onCreate() {
//Start up the thread running the service:
HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
this.count = 0;
//Get the HandlerThread's Looper and use it for our Handler
serviceLooper = thread.getLooper();
serviceHandler = new ServiceHandler(serviceLooper);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
this.resultReceiver = intent.getParcelableExtra("receiver");
//For each start request, send a message to start a job and deliver the start ID so we know which request we're stopping when we finish the job:
Message msg = serviceHandler.obtainMessage();
msg.arg1 = startId;
serviceHandler.sendMessage(msg);
//If we get killed, after returning from here, restart:
return START_REDELIVER_INTENT;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* Send a message from to the activity.
*/
protected void sendMessageToActivity(Integer code, String name, String text) {
Bundle bundle = new Bundle();
bundle.putString(name, text);
//Send the message:
resultReceiver.send(code, bundle);
}
}
Everything works fine but if I click the back button (or the home button) and then I re-open the Activity A then the UI of A is not updated anymore (it just shows the initial configuration of A - i.e. the "startButton" is still clickable and the count is not showed - it seems runOnUiThread(...) is not working anymore). However, the Service B is still running in the background and the I can see the correct count is passed to the Activity A in the Log.d(...). Finally, if I click on the "startButton" again, the counting does not start from the beginning (0) but from where B has been arrived (I've double checked it by showing it in the notification bar).
How can I fix this behaviour? I would like that, when I re-open the Activity A, it automatically continues to receive and update the data from the Service B. Or, in other words, that the Service keeps the UI of the Activity A up-to-date.
Please give me some hints, links or piece of code. Thanks!
When you click back button your Activity is destroyed. When you start the Activity again you get a new Activity. That also happen when you rotate the device. This is Android lifecycle event
The Activity is not good for heavy Business Logic only to show stuff/control stuf.
What you have to do is create a simple MVC, Model View Controller. The view (Activity) should only be used for showing results and controlling the eventflow.
The Service can hold an Array of the count and when your Activity start it will onBind() your Service that is running (or if not running will start the Service since you bind to it) Let the Activity(View) get the Array of results and show it. This simple setup exclude the (M)Model Business Logic.
Update
Following up a bit read this it's Android official docs and perfect start since it do kind of what you asking. As you see in the example in the onStart() the Activity establish a connection with the service and in the onStop() the connection is removed. There's no point having a connection after on onStop(). Just like you asking for. I would go with this setup and not let the Service continuously sending data because that would drain resources and the Activity is not always listening because it will stop when in the background.
Here's an activity that binds to LocalService and calls getRandomNumber() when a button is clicked:
I want to have the user click a button, then they will see a "Toast" message popup, which fades away , then the action that the button click performs should happen. What is the best way to do this? Should I trigger a Timer on catching the click event and let it timeout (While the toast is being displayed ) and then call the handling code or is there any built in delay mechanism in event handling I can use?
I don't want my toast to be involved at all in the event handling
If I really follow your requirements the following code should do:
// interface of the "Toast" no matter what the implementation actually is
public interface Toast
{
void open( String message );
void closeFadingAway();
}
// calling code
public class ClientCode
{
private static final int myDelay = 1000; // 1 second in millis
private Toast myToast;
void onMyAction()
{
myToast.open( "Your action is being handled..." );
Scheduler.get().scheduleFixedDelay( new RepeatingCommand()
{
#Override
public boolean execute()
{
myToast.closeFadingAway();
performAction();
return false; // return false to stop the "repeating" = executed only once
}
}, myDelay );
}
void performAction()
{
// do something interesting
}
}
Now, if you actually mean to be able to interrupt the action when the user presses some button in the toast this is a different story.
If you are using a popup panel you could use the addCloseHandler on the popup panel and from here call the method that would have otherwise been called by the button.
popUpPanel.addCloseHandler(new CloseHandler<PopupPanel>(){
#Override
public void onClose(CloseEvent<PopupPanel> event) {
// TODO Do the closing stuff here
}
});
So when the PopupPanel disappears and the close event triggers you can do your magic there.