Guava EventBus: pause event posting - guava

Is there any way to pause event posting by the EventBus from the guava library.
I have a method changeSomething() that posts an event (e.g. SomethingChangedEvent). Now this method is called in a loop by another method doStuff().
The problem is that the SomethingChangedEvent is posted on every call to changeSomething() even though only the last change matters. Due to the fact that the handlers of the event execute some heavy-weight calculations, the performance of the application degrades fast.
After the last time changeSomething() is executed I would like to tell guava to resume event processing.
Is there any way to tell guava to ignore all SomethingChangedEvents except the very last one?

I tried this pattern, derived from the poison pill pattern using sub-classing :
public class SomethingChangedEvent {
private final String name;
public SomethingChangedEvent(String name) {
this.name = name;
}
#Override
public String toString() {
return name;
}
}
public class IgnoreSomethingChangedEvent extends SomethingChangedEvent {
public IgnoreSomethingChangedEvent(String name) {
super(name);
}
}
public class HandleSomethingChangedEvent extends SomethingChangedEvent {
public HandleSomethingChangedEvent(String name) {
super(name);
}
}
private void eventBusTest() {
EventBus eventBus = new EventBus();
eventBus.register(new EventBusSomethingChanged());
eventBus.post(new SomethingChangedEvent("process this one"));
eventBus.post(new IgnoreSomethingChangedEvent("ignore"));
eventBus.post(new SomethingChangedEvent("don't process this one"));
eventBus.post(new HandleSomethingChangedEvent("handle"));
eventBus.post(new SomethingChangedEvent("process this one bis"));
}
public class EventBusSomethingChanged {
private boolean ignore;
#Subscribe
public void SomethingChanged(SomethingChangedEvent e) {
if (e instanceof IgnoreSomethingChangedEvent) {
ignore = true;
return;
}
if (e instanceof HandleSomethingChangedEvent) {
ignore = false;
return;
}
if (!ignore) {
System.out.println("processing:" + e);
}
}
}

Related

Dynamic Merge of Infinite Reactor streams

Usecase:
There is a module which Listens for events in synchronous mode. In the same module using the EmitterProccessor, the event is converted to Flux and made as infinite stream of events. Now there is a upstream module which can subscribes for these event streams. The problem here is how can I dynamically merge these streams to one and then subscribe in a single stream. A simple example is, let us say there are N number of sensors, we can dynamically register these sensors and start listening for measurements as stream of data in single stream after merging them into one stream. Here is the code sample written to mock this behavior.
Create callback and start listening for events
public interface CallBack {
void callBack(int name);
void done();
}
#Slf4j
#RequiredArgsConstructor
public class CallBackService {
private CallBack callBack;
private final Function<Integer, Integer> func;
public void register(CallBack intf) {
this.callBack = intf;
}
public void startServer() {
log.info("Callback started..");
IntStream.range(0, 10).forEach(i -> {
callBack.callBack(func.apply(i));
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
log.info("Callback finished..");
callBack.done();
}
}
Convert the events to streams using event proccessor
#Slf4j
public class EmitterService implements CallBack {
private EmitterProcessor<Integer> emitterProcessor;
public EmitterService(){
emitterProcessor = EmitterProcessor.create();
}
public EmitterProcessor<Integer> getEmmitor() {
return emitterProcessor;
}
#Override
public void callBack(int name) {
log.info("callbakc {} invoked", name);
//fluxSink.next(name);
emitterProcessor.onNext(name);
}
public void done() {
//fluxSink.complete();
emitterProcessor.onComplete();
}
}
public class WrapperService {
EmitterService service1;
ExecutorService service2;
public Flux<Integer> startService(Function<Integer, Integer> func) {
CallBackService service = new CallBackService(func);
service1 = new EmitterService();
service.register(service1);
service2 = Executors.newSingleThreadExecutor();
service2.submit(service::startServer);
return service1.getEmmitor();
}
public void shutDown() {
service1.getEmmitor().onComplete();
service2.shutdown();
}
}
Subscribe for the events
#Slf4j
public class MainService {
public static void main(String[] args) throws InterruptedException {
TopicProcessor<Integer> stealer = TopicProcessor.<Integer>builder().share(true).build();
CountDownLatch latch = new CountDownLatch(20);
WrapperService n1 =new WrapperService();
WrapperService n2 =new WrapperService();
// n1.startService(i->i).mergeWith(n2.startService(i->i*2)).subscribe(stealer);
n1.startService(i->i).subscribe(stealer);
n2.startService(i->i*2).subscribe(stealer);
stealer.subscribeOn(Schedulers.boundedElastic())
.subscribe(x->{
log.info("Stole=>{}", x);
latch.countDown();
log.info("Latch count=>{}", latch.getCount());
});
latch.await();
n1.shutDown();
n2.shutDown();
stealer.shutdown();
}
}
Tried to use TopicProccessor with no success. In the above code subscription happens for first source, for second source there is no subscription. however if use n1.startService(i->i).mergeWith(n2.startService(i->i*2)).subscribe(stealer); subscription works, but there is no dynamic behavior in this case. Need to change subscriber every time.

CDI - Injecting objects dynamically at runtime

How do I inject objects at runtime? For example, if I want to inject DerviedOne, DerivedTwo objects at runtime into the Test class in the following example, how do I do that? I found a few examples in Spring, but I'm not using Spring. This is a Dynamic Web Project with CDI using Java EE 6.
public abstract class Base
{
public Base(String initiator)
{
this.initiator = initiator;
}
public abstract void process();
public void baseProcess()
{
System.out.println("base process");
process();
}
public String getInitiator()
{
return initiator;
}
private String initiator;
}
public class BaseUtil
{
public long start()
{
return System.currentTimeMillis();
}
public long stop()
{
return System.currentTimeMillis();
}
}
public class DerivedOne extends Base
{
public DerivedOne(String initiator)
{
super(initiator);
}
#Override
public void process()
{
long start = baseUtil.start();
System.out.println(getInitiator() + " process");
long stop = baseUtil.stop();
System.out.println(stop - start);
}
#javax.inject.Inject
private BaseUtil baseUtil;
}
public class DerivedTwo extends Base
{
public DerivedTwo(String initiator)
{
super(initiator);
}
#Override
public void process()
{
long start = baseUtil.start();
System.out.println(getInitiator() + " process");
long stop = baseUtil.stop();
System.out.println(stop - start);
}
#javax.inject.Inject
private BaseUtil baseUtil;
}
#Startup
#Singleton
public class Test
{
#PostConstruct
public void init()
{
String initiator = "two";
Base base = null;
if("one".equals(initiator))
{
base = new DerivedOne("DerivedOne");
}
else if("two".equals(initiator))
{
base = new DerivedTwo("DerivedTwo");
}
base.baseProcess();
}
}
If you want to select one implementation based on runtime conditions You can use a producer method with qualifiers.
For testing CDI application I highly recommend Arquillian.
http://arquillian.org/

Check if an AsyncSubject hasn't fired

AsycSubject<Unit>() sub;
// stuff
if(!sub.HasFired())
// Do stuff
Current best attempt is:
public static bool HasFired<T>(this AsyncSubject<T> sub)
{
AsyncSubject<bool> ret = new AsyncSubject<bool>();
sub.Timeout(TimeSpan.FromMilliseconds(20))
.Subscribe(_ =>
{
ret.OnNext(true);
ret.OnCompleted();
},
ex =>
{
ret.OnNext(false);
ret.OnCompleted();
});
return ret.First();
}
But it feels very ugly and long. I suspect I'm missing something simple. Any suggestions?
It's easier to wrap around the existing AsyncSubject and add the required state.
public class AsyncSubjectEx<T> : ISubject<T>, IDisposable
{
AsyncSubject<T> Subject = new AsyncSubject<T>();
public bool HasValue { get; protected set; }
public object Gate = new object();
public void OnCompleted()
{
Subject.OnCompleted();
}
public void OnError(Exception error)
{
Subject.OnError(error);
}
public void OnNext(T value)
{
lock (Gate)
{
Subject.OnNext(value);
HasValue = true;
}
}
public IDisposable Subscribe(IObserver<T> observer)
{
lock (Gate)
return Subject.Subscribe(observer);
}
public void Dispose()
{
Subject.Dispose();
}
}
Ironically, the original AsyncSubject upon reflection shows that there is a hasValue field, but it doesn't happen to be exposed. Consider reporting this to the Rx team - might be useful sometime.

How to respond to URLs with GWT's built-in MVP-framework?

I'm building a very simple calendar app to get familiar with the MVP-framework introduced with the 2.1 version of GWT.
What I want to achieve is being able to switch between a list of scheduled appointments and a list of the avialable time.
I have created the a CalendarPlace, CalendarActivity, CalendarView and CalendarViewImpl.
I know that to navigate to a different place i would call PlaceController.goTo(Place), so in my calendar app I would call:
clientFactory.getPlaceController.goTo(new CalendarPlace("freeTime");
The URL would be index.html#CalendarPlace:freeTime for the list of free time or
clientFactory.getPlaceController.goTo(new CalendarPlace("appointments");
for the list of scheduled appointments. The URL would be index.html#CalendarPlace:appointments
But the question is where do I respond to the different tokens? I guess the CalendarPlace would be the right place, but how would I do that?
Here is my source code(I took most of the boilerplate from the tutorial here:
CalendarPlace:
public class CalendarPlace extends Place {
private String calendarName;
public CalendarPlace(String token) {
this.calendarName = token;
}
public String getCalendarName() {
return calendarName;
}
public static class Tokenizer implements PlaceTokenizer<CalendarPlace> {
#Override
public CalendarPlace getPlace(String token) {
return new CalendarPlace(token);
}
#Override
public String getToken(CalendarPlace place) {
return place.getCalendarName();
}
}
}
CalendarActivity:
public class CalendarActivity extends AbstractActivity
implements
CalendarView.Presenter {
private ClientFactory clientFactory;
private String name;
public CalendarActivity(CalendarPlace place, ClientFactory clientFactory) {
this.name = place.getCalendarName();
this.clientFactory = clientFactory;
}
#Override
public void goTo(Place place) {
clientFactory.getPlaceController().goTo(place);
}
#Override
public void start(AcceptsOneWidget containerWidget, EventBus eventBus) {
CalendarView calendarView = clientFactory.getCalendarView();
calendarView.setName(name);
calendarView.setPresenter(this);
containerWidget.setWidget(calendarView.asWidget());
}
}
CalendarViewImpl:
public class CalendarViewImpl extends Composite implements CalendarView {
private VerticalPanel content;
private String name;
private Presenter presenter;
private OptionBox optionBox;
public CalendarViewImpl() {
//optionBox is used for navigation
//optionBox is where I call PlaceController.goTo() from
optionBox=new OptionBox();
RootPanel.get("bluebar").add(optionBox);
content=new VerticalPanel();
this.initWidget(content);
}
#Override
public void setPresenter(Presenter listener) {
this.presenter=listener;
}
#Override
public void setName(String calendarName) {
this.name = calendarName;
}
public void displayFreeTime() {
//called from somewhere to display the free time
}
public void getAppointments() {
//called from somewhere to display the appointments
}
}
In your CalendarActivity constructor you have access to the place, and therefore the token. Tuck it aside, and then in your start() method you can use it. Activities are meant to be lightweight objects, created for each new navigation.

GWT Void remote services fail for seemingly no reason

I'm working on a GWT project and have several void remote services that seem to execute just fine, but on the client side, end up firing the onFailure() method. No exceptions are thrown anywhere, and the expected behavior is observed on the backend. I have no idea what could be going wrong. Here is the relevant code:
Interfaces and implementation...
#RemoteServiceRelativePath("DeleteSearchService")
public interface DeleteSearchService extends RemoteService {
/**
* Utility class for simplifying access to the instance of async service.
*/
public static class Util {
private static DeleteSearchServiceAsync instance;
public static DeleteSearchServiceAsync getInstance(){
if (instance == null) {
instance = GWT.create(DeleteSearchService.class);
}
return instance;
}
}
public void delete(SearchBean search);
}
public interface DeleteSearchServiceAsync {
public void delete(SearchBean bean, AsyncCallback<Void> callback);
}
public class DeleteSearchServiceImpl extends RemoteServiceServlet implements DeleteSearchService {
private static final long serialVersionUID = 1L;
#Override
public void delete(SearchBean search) {
try {
Connection conn = SQLAccess.getConnection();
String sql = "DELETE FROM `searches` WHERE `id`=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, search.getSearchId());
ps.execute();
sql = "DELETE FROM `searchsourcemap` WHERE `search-id` = ?";
ps = conn.prepareStatement(sql);
ps.setInt(1, search.getSearchId());
ps.execute();
return;
} catch (Exception e) {
// TODO Log error
e.printStackTrace();
}
}
}
Calling code...
private class DeleteListener implements ClickListener {
public void onClick(Widget sender) {
DeleteSearchServiceAsync dss = DeleteSearchService.Util.getInstance();
SearchBean bean = buildBeanFromGUI();
dss.delete(bean, new AsyncCallback<Void>(){
//#Override
public void onFailure(Throwable caught) {
// TODO log
SearchNotDeleted snd = new SearchNotDeleted();
snd.show();
}
//#Override
public void onSuccess(Void result) {
SearchDeleted sd = new SearchDeleted();
sd.show();
searchDef.getParent().removeFromParent();
}
});
}
}
I know I'm a jerk for posting like 500 lines of code but I've been staring at this since yesterday and can't figure out where I'm going wrong. Maybe a 2nd set of eyes would help...
Thanks,
brian
LGTM I'm afraid.
Are you using the hosted mode or a full-fledged browser? You can try switching and see if it helps.
Also, it might help listening to that //TODO and perform a GWT.log when onFailure is invoked.