0

how to implement publish-subscribe pattern by ZK existing event infrastructure

asked 2009-05-22 06:49:21 +0800

jimmytan gravatar image jimmytan
60 2

Hi, I'm working on an ZK prototype which using the MVC pattern, such as Controller, Model and data binding as well. I have requirement such as, a desktop includes several portlet-like Views. Each portlet-line View has its own Controllers, Models and Views. The communication between plrtlet is by events. For example, portlet A sends an update event to all other portlets due to a data change. Just wondering, has anyone had some idea on how to achieve this. How can I send our an event, and ALL others can receive this event? This is more like a questoin on how to implement publish-subscribe pattern by ZK's event infrastructure. thanks.

delete flag offensive retag edit

8 Replies

Sort by ยป oldest newest

answered 2009-05-25 02:56:06 +0800

dennis gravatar image dennis
3669 1 6
http://www.javaworld.com....

there is a EventQueues, maybe is the what you need.

<window title="Test of event queue">
Type "AB" in the textbox, and then click the Test button.
You shall see three copies of "AB", i.e., "ABABAB"
<separator/>
<textbox id="tb"/><button label="Test" onClick="test()"/>
<separator bar="true"/>
<label id="l"/>
	<zscript>
	import org.zkoss.zkmax.ui.eq.EventQueues;
	EventListener listener = new EventListener() {
		public void onEvent(Event event) {
			l.value += tb.value;
		}
	};
	EventQueues.lookup("test").subscribe(listener);
	EventQueues.lookup("test").subscribe(listener);
	EventQueues.lookup("test").subscribe(listener);

	void test() {
		l.value = "";
		EventQueues.lookup("test").publish(event);
	}
	</zscript>
</window>

link publish delete flag offensive edit

answered 2009-05-27 08:14:46 +0800

jimmytan gravatar image jimmytan
60 2

yes, thanks, looks like this is what I need, thanks a lot

link publish delete flag offensive edit

answered 2009-05-27 09:47:59 +0800

jimmytan gravatar image jimmytan
60 2

Hi, sorry, I have some more questions as below:
1) per the requirements, I'm using the MVC pattern. I like to have the MODEL to send out events to all CONTROLLER by publish/subscribe pattern, so that the CONTROLLER can refresh the VIEW accordingly. I'm using the databinding as well. Where is the proper place to subscribe a queue for a CONTROLLER? the constructor of the CONTROLLER? the doAfterCompose method of a CONTROLLER?
2) I like to have the CONTROLLER to implement the EventListener interface, is this a good approach? Since the CONTROLLER has the responsibility to refresh the VIEW.
3) the CONTROLLER will not send out any data change event to other COMTROLLERs, only the MODEL has the responsibility to send out event to notice all CONTROLLERs. Any advices>???
4) I'm worry about the life-cycle of a CONTROLLER. Because a CONTROLLER subscribes a queue, and put himself as the subscriber of the queue. When a user pushs the F5 to refresh the page, a new CONTROLLER will be initiated and the previous one will still be one of the queue subscribers, this means the previous one became a orphan. Once the MODEL detects a data cahnge, it sends out a event to the queue, all the subscribers will get the event, asking for refreshing the VIEW, include the orphan CONTROLLER................. any advices for preventing this situation.

Sorry, I'm new to ZK, some questions may sound stupid. ;-D

link publish delete flag offensive edit

answered 2009-06-01 02:08:04 +0800

dennis gravatar image dennis
3669 1 6
http://www.javaworld.com....

1.try doaftercompose.
2.this depends on you, it is just a event-listener-interface isn't it.
3.no suggestion.
4.Events are restricted in a desktop, and desktop will be clean when number of desktop has exceed or session timeout.
when desktop been clean, any thing belong to this desktop will be release.

link publish delete flag offensive edit

answered 2009-06-15 01:55:10 +0800

jimmy gravatar image jimmy
45

thanks.

link publish delete flag offensive edit

answered 2011-02-19 01:09:18 +0800

yaryan997 gravatar image yaryan997
210 2

@dennis
HI... dennis

I am having some problems with " how to implement publish-subscribe pattern by ZK existing event infrastructure"
actually I am working with the project where I had to use MVC pattern with Spring I had all my gui pages in .zul and Spring managed Container.

I am having on problem with using EventQues. I had one filter bar which has two listbox one for ServiceId and another of SeasonId and then make a click on REFRESH button and after that below process executes

public void onClick$ref(Event event){
		
		if(lbox_service.getSelectedIndex() != 0 || lbox_season.getSelectedIndex() != 0)
		{
			if(lbox_service.getSelectedIndex() == 0)
			{
				setService_id("0");
			}
			else
			{
				setService_id(lbox_service.getSelectedItem().getValue().toString());
			}
			if(lbox_season.getSelectedIndex() == 0)
			{
				setSeason_id("0");
			}
			else
			{
				setSeason_id(lbox_season.getSelectedItem().getValue().toString());
			}
			
			
			System.out.println("Service Index 11 : "+ lbox_service.getSelectedIndex());
			System.out.println("Season Index 11 : "+ lbox_season.getSelectedIndex());
			
			EventQueue evtQ = EventQueues.lookup("myEventQueue", EventQueues.APPLICATION, true);
			//evtQ.publish(new Event("service_id", self, lbox_service.getSelectedItem().getValue().toString()));
			//evtQ.publish(new Event("season_id", self, lbox_season.getSelectedItem().getValue().toString()));
			
			evtQ.publish(new Event("service_id", self, getService_id()));
			evtQ.publish(new Event("season_id", self, getSeason_id()));
			
			
			
			//evtQ.publish(new Event("onClickRef", null, lbox_service.getSelectedItem().getValue().toString()));
			//evtQ.publish(new Event("onClickRef", null, lbox_season.getSelectedItem().getValue().toString()));
			
				/*.publish(new Event("onClickRef", null, lbox_service.getSelectedItem().getValue().toString()));
			
	
			 EventQueues.lookup("myEventQu", EventQueues.DESKTOP, true)
				
				.publish(new Event("onClickRef", null, lbox_season.getSelectedItem().getValue().toString()));*/
		}
		else
		{	
			setService_id("0");
			setSeason_id("0");

			EventQueue evtQ = EventQueues.lookup("myEventQueue", EventQueues.APPLICATION, true);
			evtQ.publish(new Event("service_id", self, getService_id()));
			evtQ.publish(new Event("season_id", self, getSeason_id()));
			
			System.out.println("Service Index : "+ lbox_service.getSelectedIndex());
			System.out.println("Season Index : "+ lbox_season.getSelectedIndex());
			
		}
		
	}

and after onClick$ref event my new traditional_retailers1.zul page loads with doAfterCompose method and below I have mentioned code

@Override
	public void doAfterCompose(Component comp) throws Exception {
		
		super.doAfterCompose(comp);
	<b >	EventQueues.lookup("myEventQueue", EventQueues.APPLICATION, true)</b>
			
		.subscribe(new EventListener() {
			
			public void onEvent(Event event) throws Exception {
				
				/*String service = (String) event.getData();
				
				logger.info("Servive $$$$$$$$$ " + service);
				//String season = (String) event.getData();
				//logger.info("Season $$$$$$$$$ " + season);
*/		
				if("service_id".equals(event.getName())) {
					setService_id((String) event.getData());
					baseController.setFilter_bar(true);
					System.out.println("Service Id :" +event.getData());
				}
				else if("season_id".equals(event.getName())) {
					setSeason_id((String) event.getData());
					baseController.setFilter_bar(true);
					System.out.println("Season Id :" +event.getData());
				}
				
				
				/*setService_id((String) event.getData());
				setSeason_id((String) event.getData());*/
				
				/*if("season_id".equals(event.getName())){
					setSeason_id((String) event.getData());
				}else
				{
					setSeason_id("0");
				}*/
				System.out.println("Filter bar :" +baseController.isFilter_bar());
				if(baseController.isFilter_bar() == true)
				{
				
					String dateFrom = "";
					String dateTo = "";
					String order = "2";
					List TDRetailers = verificationStoreHibernateDao.getTraditionalRetailers(getService_id(), getSeason_id(), dateFrom, dateTo, order);
					
					//VerificationStoreHibernateDao storeHibernateDao = new VerificationStoreHibernateDao();
					//List TDRetailers = this.verificationStoreHibernateDao.getTraditionalRetailers(service_id);
					//ListModel listModel = this.retailers.getModel();
					ListModelList listModelList = (ListModelList) retailer.getModel();
					listModelList.clear();
					listModelList.addAll(TDRetailers);
					baseController.setFilter_bar(true);
				}
			
			}
		});
}

can you help me that how can I separate the multiple publish valued to be used by subscribe separately and which further used to execute my condition base query.

help me to get out of this problem..
thanx for help in advance...

link publish delete flag offensive edit

answered 2011-02-21 01:57:18 +0800

yaryan997 gravatar image yaryan997
210 2

updated 2011-02-21 02:34:25 +0800

@jimmy

Hope your problem is resolved.. but my problem is still there and I thought that you can help me to get out of this problem.
actually I had multiple events to publish one by one as per user selection for eg: user select Season, Service, DateFrom and DateTo and then clicks on the refresh button.

When the refresh button is clicked I had used the above logic to get all the datas using the below mentioned code

public void onClick$ref(Event event){
		
		if(lbox_service.getSelectedIndex() != 0 || lbox_season.getSelectedIndex() != 0)
		{
			if(lbox_service.getSelectedIndex() == 0)
			{
				setService_id("0");
			}
			else
			{
				setService_id(lbox_service.getSelectedItem().getValue().toString());
			}
			if(lbox_season.getSelectedIndex() == 0)
			{
				setSeason_id("0");
			}
			else
			{
				setSeason_id(lbox_season.getSelectedItem().getValue().toString());
			}
			
			
			System.out.println("Service Index 11 : "+ lbox_service.getSelectedIndex());
			System.out.println("Season Index 11 : "+ lbox_season.getSelectedIndex());
			
			EventQueue evtQ = EventQueues.lookup("myEventQueue", EventQueues.APPLICATION, true);
			//evtQ.publish(new Event("service_id", self, lbox_service.getSelectedItem().getValue().toString()));
			//evtQ.publish(new Event("season_id", self, lbox_season.getSelectedItem().getValue().toString()));
			
			evtQ.publish(new Event("service_id", self, getService_id()));
			evtQ.publish(new Event("season_id", self, getSeason_id()));
			
			
			
			//evtQ.publish(new Event("onClickRef", null, lbox_service.getSelectedItem().getValue().toString()));
			//evtQ.publish(new Event("onClickRef", null, lbox_season.getSelectedItem().getValue().toString()));
			
				/*.publish(new Event("onClickRef", null, lbox_service.getSelectedItem().getValue().toString()));
			
	
			 EventQueues.lookup("myEventQu", EventQueues.DESKTOP, true)
				
				.publish(new Event("onClickRef", null, lbox_season.getSelectedItem().getValue().toString()));*/
		}
		else
		{	
			setService_id("0");
			setSeason_id("0");

			EventQueue evtQ = EventQueues.lookup("myEventQueue", EventQueues.APPLICATION, true);
			evtQ.publish(new Event("service_id", self, getService_id()));
			evtQ.publish(new Event("season_id", self, getSeason_id()));
			
			System.out.println("Service Index : "+ lbox_service.getSelectedIndex());
			System.out.println("Season Index : "+ lbox_season.getSelectedIndex());
			
		}
		
	}

now i had publish all my value and after that my new Controller run that will subscribe those published values. using the below code

public void doAfterCompose(Component comp) throws Exception {
		
		super.doAfterCompose(comp);
	<b >	EventQueues.lookup("myEventQueue", EventQueues.APPLICATION, true)</b>
			
		.subscribe(new EventListener() {
			
			public void onEvent(Event event) throws Exception {
				
				/*String service = (String) event.getData();
				
				logger.info("Servive $$$$$$$$$ " + service);
				//String season = (String) event.getData();
				//logger.info("Season $$$$$$$$$ " + season);
*/		
				if("service_id".equals(event.getName())) {
					setService_id((String) event.getData());
					baseController.setFilter_bar(true);
					System.out.println("Service Id :" +event.getData());
				}
				else if("season_id".equals(event.getName())) {
					setSeason_id((String) event.getData());
					baseController.setFilter_bar(true);
					System.out.println("Season Id :" +event.getData());
				}
				
				
				/*setService_id((String) event.getData());
				setSeason_id((String) event.getData());*/
				
				/*if("season_id".equals(event.getName())){
					setSeason_id((String) event.getData());
				}else
				{
					setSeason_id("0");
				}*/
				System.out.println("Filter bar :" +baseController.isFilter_bar());
				if(baseController.isFilter_bar() == true)
				{
				
					String dateFrom = "";
					String dateTo = "";
					String order = "2";
					List TDRetailers = verificationStoreHibernateDao.getTraditionalRetailers(getService_id(), getSeason_id(), dateFrom, dateTo, order);
					
					//VerificationStoreHibernateDao storeHibernateDao = new VerificationStoreHibernateDao();
					//List TDRetailers = this.verificationStoreHibernateDao.getTraditionalRetailers(service_id);
					//ListModel listModel = this.retailers.getModel();
					ListModelList listModelList = (ListModelList) retailer.getModel();
					listModelList.clear();
					listModelList.addAll(TDRetailers);
					baseController.setFilter_bar(true);
				}
			
			}
		});
}

but actully my problem is with running the query and with getting those published values. Based on them I will be able to run my Traditional getTraditionalRetailers queries.

My problem is
1. how to publish multiple events values. Is it the right way that I had done.
2.as I had done separate publish, everytime I publish new value The query runs, the result is that i had mutiple time query execution. for example If i will publish two values the queries run's for the two times and if I publish three values the query executes for three time.

I don't know what is their problem. .
help me to solve my error..

link publish delete flag offensive edit

answered 2011-02-21 22:48:55 +0800

samchuang gravatar image samchuang
4084 4

Hi

you can refer to Event Queues

I look at your code quickly, you mentioned.

	evtQ.publish(new Event("service_id", self, getService_id()));
	evtQ.publish(new Event("season_id", self, getSeason_id()));

if the two event do the same thing, you can just publish one event with two param.

link publish delete flag offensive edit
Your reply
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow

RSS

Stats

Asked: 2009-05-22 06:49:21 +0800

Seen: 1,139 times

Last updated: Feb 21 '11

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More