Cannot resolve method 'subscribe(anonymous io.reactivex.functionx.Consumer<java.util.List<...>>)' in rxjava2? - rx-java2

after toList operator performs, original Flowable<<\List>> converts to Single<<\List>>. and it turns out if I create Consumer to subscribe to Single,
the Consumer value type cannot be changed except Object?
#Override
public void loadBannerData(final ADFilterType adFilterType) {
remoteListDataSource.getBannerListData(adFilterType)
.flatMap(new Function<List<BannerBeanList.BannerBean>, Publisher<?>>() {
#Override
public Publisher<?> apply(List<BannerBeanList.BannerBean> bannerBeen) throws Exception {
return Flowable.fromIterable(bannerBeen);
}
})
.toList()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
/******************************Consume Value Type**************************
.subscribe(new Consumer<List<BannerBeanList.BannerBean>>() {
#Override
public void accept(List<BannerBeanList.BannerBean> bannerBeens) throws Exception {
mainTabView.showMainBanner(bannerBeens);
}
});
*****************************************************************************/
}

From my comment: this happens because you have Publisher<?> instead of Publisher<BannerBeanList.BannerBean> in your code. Often IDEs can't infer types of lambdas or functional interfaces and you'll end up with ? or Object as their type when using some generate/convert refactoring function.

Related

Can we use state variables in Flink's trigger?

I am using Apache Flink's sliding window with trigger. I would like to use a state variable in the trigger. However, I did not find any rich function corresponding to trigger function.
inputStream.keyBy(new KeySelector<Integer, String>() {
#Override
public String getKey(Integer i) throws Exception {
return i;
}
}).window(SlidingEventTimeWindows.of(Time.seconds(windowSize), Time.seconds(slideStep)))
.trigger(new Trigger<String, TimeWindow> {
#Override
public TriggerResult onElement(String str, long l, TimeWindow timeWindow, TriggerContext triggerContext) throws Exception {
return TriggerResult.CONTINUE;
}
#Override
public TriggerResult onProcessingTime(long l, TimeWindow timeWindow, TriggerContext triggerContext) throws Exception {
return TriggerResult.FIRE;
}
#Override
public TriggerResult onEventTime(long l, TimeWindow timeWindow, TriggerContext triggerContext) throws Exception {
return TriggerResult.FIRE;
}
#Override
public void clear(TimeWindow timeWindow, TriggerContext triggerContext) throws Exception {
})
.apply(new RichWindowFunction<String, String, String, TimeWindow>() {...}
So my question is, can we use state variables inside trigger block?
Yes, Triggers can be stateful. Look at CountTrigger for an example. You'll see that it keeps a count of how many elements have been added to the window in
private final ReducingStateDescriptor<Long> stateDesc =
new ReducingStateDescriptor<>("count", new Sum(), LongSerializer.INSTANCE);
It then uses that state in its onElement method
public TriggerResult onElement(Object element, long timestamp, W window, TriggerContext ctx)
throws Exception {
ReducingState<Long> count = ctx.getPartitionedState(stateDesc);
count.add(1L);
if (count.get() >= maxCount) {
count.clear();
return TriggerResult.FIRE;
}
return TriggerResult.CONTINUE;
}
and clears it in its clear method
public void clear(W window, TriggerContext ctx) throws Exception {
ctx.getPartitionedState(stateDesc).clear();
}
Keep in mind that if you are implementing a mergeable window type, then your Trigger will have to use state that can be merged, and then merge it when windows are merged. (Since you are using some flavor of sliding window, you can probably ignore this.)

How do I inherit from an Observable<T>?

I want to build an event broker class that inherits from Observable<EventArgs>. In the .NET implementation of Rx, you can simply implement IObservable<EventArgs>; furthermore, in .NET the publish() method just takes the argument that you want the subscribers to receive.
Can someone explain how this is done in Java? All I want is a class who inherently behaves as Observable<Foo>.
In most cases, there is no necessity to implement your own Observable inheritor. There is a bunch of fabrics methods to create Observable and handle it's behavior. For example:
Observable.create(new ObservableOnSubscribe<String>() {
#Override public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("New event");
emitter.onError(new Error());
emitter.onComplete();
}
});
But, if you really need to create exactly an inheritor it is not difficult either.
class MarkedObservable extends Observable<String> {
#Override protected void subscribeActual(Observer<? super String> observer) {
observer.onNext("Message");
observer.onError(new Error());
observer.onComplete();
}
}

Wrapping event listeners in Observables

I've seen a lot of examples of how to turn finite things like arrays or Iterables into Observables, but I'm not sure I understand how to make an Observable out of something live and effectively unbounded like an event receiver. I studied the RxJava2 docs and came up with this, using an Android LocationListener as an example.
Is there a simpler and/or more correct way to do this? I'm aware of the "RxBus" concept, but it seems like a way of clinging to the old event bus paradigm.
final Observable<Location> locationObservable = Observable.create(new ObservableOnSubscribe<Location>() {
final LocationManager mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
#Override
public void subscribe(final ObservableEmitter<Location> emitter) throws Exception {
final LocationListener listener = new LocationListener() {
#Override
public void onLocationChanged(final Location location) {
emitter.onNext(location);
}
#Override
public void onStatusChanged(final String s, final int i, final Bundle bundle) {
// TODO ???
}
#Override
public void onProviderEnabled(final String s) {
// TODO ???
}
#Override
public void onProviderDisabled(final String s) {
// TODO ???
}
};
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
emitter.setCancellable(new Cancellable() {
#Override
public void cancel() throws Exception {
mLocationManager.removeUpdates(listener);
}
});
emitter.setDisposable(new Disposable() {
private AtomicBoolean mDisposed;
#Override
public void dispose() {
if(mDisposed.compareAndSet(false, true)) {
mLocationManager.removeUpdates(listener);
}
}
#Override
public boolean isDisposed() {
return mDisposed.get();
}
});
}
});
using Observable.create() is indeed a correct way.
However, with RxJava2 the default way is to extend an Observable, you can see this answer for greater details.
some comments though regarding your implementation:
- there is no point setting both Cancellable and Disposable, as the later one will cancel/dispose the first one, you can see the difference between them here.
- I think it's best practice, to register cancellable/disposable before you start listening to update, in order to prevent weird edge cases races.

Match or Join event and rule from two kafka topics in one datastream

i want to do join between two kafka topics in one Datastream.
In fact the two datastream must have the same id to make the join.
Event are the data coming from the sensors and rule contains rules that will be checked with the CEP(coming from User Interface).
Here is my test but it does not work, can anyone help me please ?
DataStream<Object> evtAndRule=inputEventStream.join(rulesStream)
.where(new KeySelector<TrackEvent, Object>() {
#Override
public Object getKey(Event event) throws Exception {
return event.getId();
}
}).equalTo(new KeySelector<RulesEvent, Object>() {
#Override
public Object getKey(RulesEvent rulesEvent) throws Exception {
return rulesEvent.getId();
}
}).window(TumblingTimeWindows.of(Time.of(10, TimeUnit.SECONDS)))
.apply(new FlatJoinFunction<TrackEvent, RulesEvent, Object>() {
#Override
public void join(TrackEvent trackEvent, RulesEvent rulesEvent, Collector<Object> collector) throws Exception {
....
}
});
I tried this but I do not know how to retrieve the desired rule and if this is the best solution
DataStream<Tuple2<Event , RulesEvent>> evtAndRule= inputEventStream.map(new MapFunction<Event , Tuple2<Event , RulesEvent>>() {
#Override
public Tuple2<Event , RulesEvent> map(final Event event) throws Exception {
return new Tuple2<Event , RulesEvent>(event, new RulesEvent());
}
});

Creating Custom Operators in RxJava2?

I'm having trouble finding an example of how to make a custom operator with RxJava 2. I've considered a few approaches:
Using Observable.create, and then flatMaping on it from the source observable. I can get this working, but it doesn't quite feel right. I end up creating a static function which I provide the source Observable, and then flatMap on the source. In the OnSubscribe, I then instantiate an object that I pass the emitter to, which handles and manages the Observable / Emitter (as it's not trivial, and I want everything as encapsulated as possible).
Creating an ObservableOperator and providing it to Observable.lift. I can't find any examples of this for RxJava 2. I had to debug into my own example to make sure my understanding of upstream and downstream were correct. Because I can't find any examples or documentation on this for RxJava 2 I'm a little worried I might accidentally do something I'm not supposed to.
Create my own Observable type. This seems to be how the underlying operators work, many of which extend AbstractObservableWithUpstream. There is a lot going on here though, and it seems easy to miss something or do something I shouldn't. I'm not sure if I'm supposed to take an approach like this or not. I stepped myself through the mental process, and it seems like it can get hairy pretty quickly.
I'm going to proceed forward with option #2, but thought it worthwhile to ask what the supported method for doing this was in RxJava2 and also find out if there was any documentation or examples for this.
Writing operators is not recommended for beginners and many desired flow patterns can be achieved via existing operators.
Have you looked at RxJava's wiki about writing operators for 2.x? I suggest reading it from top to bottom.
using create() is possible but most people use it to emit the elements of a List with a for-each loop, not recognizing that Flowable.fromIterable does that.
We kept this extension point although RxJava 2 operators don't use lift() themselves. If you want to avoid some boilerplate with option 3. then you may try this route.
This is how RxJava 2 operators are implemented. AbstractObservableWithUpstream is a small convenience and not necessary for external implementors.
This may help you. I implement operator RxJava2 to handle APiError. I used lift operator.
See the example.
public final class ApiClient implements ApiClientInterface {
...
#NonNull
#Override
public Observable<ActivateResponse> activate(String email, EmailData emailLinkData) {
return myApiService.activate(email, emailData)
.lift(getApiErrorTransformer())
.subscribeOn(Schedulers.io());
}
private <T>ApiErrorOperator<T> getApiErrorTransformer() {
return new ApiErrorOperator<>(gson, networkService);
}
}
And then you can find custom operator
public final class ApiErrorOperator<T> implements ObservableOperator<T, T> {
private static final String TAG = "ApiErrorOperator";
private final Gson gson;
private final NetworkService networkService;
public ApiErrorOperator(#NonNull Gson gson, #NonNull NetworkService networkService) {
this.gson = gson;
this.networkService = networkService;
}
#Override
public Observer<? super T> apply(Observer<? super T> observer) throws Exception {
return new Observer<T>() {
#Override
public void onSubscribe(Disposable d) {
observer.onSubscribe(d);
}
#Override
public void onNext(T value) {
observer.onNext(value);
}
#Override
public void onError(Throwable e) {
Log.e(TAG, "onError", e);
if (e instanceof HttpException) {
try {
HttpException error = (HttpException) e;
Response response = error.response();
String errorBody = response.errorBody().string();
ErrorResponse errorResponse = gson.fromJson(errorBody.trim(), ErrorResponse.class);
ApiException exception = new ApiException(errorResponse, response);
observer.onError(exception);
} catch (IOException exception) {
observer.onError(exception);
}
} else if (!networkService.isNetworkAvailable()) {
observer.onError(new NetworkException(ErrorResponse.builder()
.setErrorCode("")
.setDescription("No Network Connection Error")
.build()));
} else {
observer.onError(e);
}
}
#Override
public void onComplete() {
observer.onComplete();
}
};
}
}