Illustration based on three java classes: Producer, Consumer and a Main class. Find below examples for the same.
* Scenarios shown below are only basic examples to build preliminary understanding on how framework works. Check code snippets provided in link mentioned above for complete usage, and the examples are not provided for performance execution hence are not to be considered for use in Production environment.
** Check Instinct page to understand threading behavior to implement publishers and can validate them using snippet examples.
1. Simple event publisher and subscriber example where both configured methods can be either part of same class definition or be in different. In both cases Instinct framework will automatically scan for these configured methods and bind them.
@Publish(id="ch1")
public String m1(String in) {
System.out.println("m1 called");
return "1++" + in;
}
@Subscribe(id = "ch1")
public void m1(String in) {
System.out.println("m1:" + in);
}
Example above displays simple event type handling, but this event binding is also possible with methods having different data type in/out parameters as shown in the example below:
@Publish(id = "ch4")
public String getSimpleString(String inStr) {
return inStr;
}
@Publish(id = "ch4")
public String getFromDto(DTO dto) {
System.out.println("getFromDto");
return dto.getS();
}
@Subscribe(id = "ch4")
public void getFromDto(String s) {
System.out.println("getFromDto:" + s);
}
Important:
In order to achieve atomic and isolated event dispatch between configured publishers and subscribers, Instinct framework treats every user defined channel definition as a separate control dissipation channel, and if the channels are configured to be asynchronous using "SPC", "MPC" thread behavior for publishers Instinct will have one thread per configured channel, hence user should be very careful while defining asynchronous event channels.
2. In case if publisher output event type and subscriber input parameter types are completely different user can configure this publisher with an event transformer as show below, also described in method javaDocs:
/**
* Annotate a method with <b>@Publish</b> type to bind this method
* with user defined channel. Annotate same method with <b>@Transform</b>
* which excepts an array of <b>@Transformer</b> to define
* implementation of abstract AbstractEventTransformer class to transform
* publisher return type to Subscriber input type.
* @param in of type String
* @return custom data type.
*/
@Transform({@Transformer(channelId = "ch3", transformer = MyTransformer.class)})
@Publish(id="ch3")
public DTO getDto(String in) {
System.out.println("getDto called");
return new DTO("3++" + in, 1);
}
As shown in the example above "@Transform" annotation can accept array of Transformers that can hold configuration for respective user defined channels. Reason to give ability to configure array of transformers is, in case a publisher is configured with multiple channels and each need to have their respective event transformer, this can be achieved as shown in next example.
3. Configured publisher with multiple user defined event channels:
@Transform({@Transformer(channelId="ch_p_3_2", transformer = MyTransformer.class)})
@Publish(id = {"ch_p_3_1", "ch_p_3_2"})
public DTO getMultiple() {
return new DTO("3", 3);
}
@Subscribe(id="ch_p_3_1")
public void sub1(DTO dto) {
System.out.println("sub3_1:" + dto);
}
@Subscribe(id = "ch_p_3_2")
public void sub2(String in) {
System.out.println("sub3_2:"+in);
}
In the example above one configured subscriber accepts same event data type as published by the configured publisher on channel "ch_p_3_1
", but the second subscriber configured on channel "ch_p_3_2
" accepts String event type. In order to support both subscriber configurations Transformer annotation is required for event type change. Event transformer used in the example is shown below:
public static class MyTransformer extends AbstractEventTransformer<DTO, String>{
@Override
public String transform(DTO toTransform) {
return toTransform.getS();
}
}
A transformer can be configured with Generic parameters, where first parameter is event input and second is return type from the the transform implementation method.
Important:
@Transformer configuration is only supported with @Publish methods only and not @Subscribe, but currently framework does not throw any warning if the later is configured.
4. Instinct also supports event chaining. If a user wants to chain a sequence of event processors, this can be achieved using both @Publish and @Subscribe on same methods, with every annotation configuration pointing to each other via configured channel-id. If a same method is annotated with both Publish and Subscribe but with same channel-id then the framework will throw an exception as this can result in iterative calls, similarly if the chain is configured in such a way that the event path is cyclic then again framework will throw exception, as this can also result in iterative calls.
Shown below methods can be defined in same class or in different, also can be combined with other featured defined in examples above.
@Publish(id="link1")
public String link1() {
return "++1";
}
@Subscribe(id="link1", eventFilter = EventFilter.class)
@Publish(id="link2", threadBehavior = InstinctThreadBehavior.MPC)
public String linke2(String in) {
return "++2"+in;
}
@Subscribe(id="link2")
@Publish(id="link3", threadBehavior = InstinctThreadBehavior.MPC, behavior = InstinctWaitBehavior.PARK_WAIT)
public String linke3(String in) {
System.out.println("link3:"+in);
return "++3"+in;
}
@Transform(@Transformer(channelId="link4", transformer = MyTransformer.class))
@Subscribe(id="link3")
@Publish(id="link4", threadBehavior=InstinctThreadBehavior.MPC)
public DTO link3(String in) {
try {
Thread.sleep(2 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("link 3 called:"+in);
return new DTO(in, 4);
// return null;
}
@Subscribe(id="link4")
public String link4(String in) {
try {
Thread.sleep(2 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("link 4 called:" + in);
return "link4+" + in;
}
As shown in above example, user can combine threading behavior and event filter along with simple/complex event chaining. Also "link3" channel includes anther feature of threading behavior, this is the thread wait behavior of for the thread assigned to the user defined channel. In this case the thread assigned to link3 channel has PARK_WAIT behavior, that means the thread will be parked during its execution if the load on the system is not high; i.e. event dissipation count per second is not very high.
Event filter configured in the example above with @Subscribe for channel "link1
" is shown below:
public static class EventFilter extends AbstractEventFilter<String>{
@Override
public boolean filterEvent(String event) {
System.out.println("filter called");
return true;
}
}
That concludes a brief set of examples on features available in this version of Instinct. And these in combination can also be used to cater to complex scenarios like producer-consumer paradigm.
"Happy Event-ing !!!"