Spring reactive with dynamic producers - java

I have reacently started to use reactive thinking together with java and Spring.
Would it be possible create a scenario where you have a dynamic number of producers? Im developing a product that listen to a particular hardware for events and It would be awsome if I could add (and possibly remove) listening to devices dynamicaly A,B...Z without ending the stream.
I imagine a something like:
#GetMapping("/")
public Flux<HardwareEvent> void test() {
return Flux.merge(
listenHardware(A),
listenHardware(B)
);
}
Flux<HardwareEvent> listenHardware(HardwareId id); // produced indefinite stream of events
Where you somehow could inject new producers to the merge dynamically without stopping the stream.
Is this possible?
If someone could point me to (or post) an example it would be awesome.
Regards.

You might need some glue code in the middle, but this looks like a good use case for Subjects
Instead of having a "regular" Observable, you'd have a Subject that you're seeing as an Observable. Good thing of Subjects is that you can emit new values on demand so you could do something like
Subject<Value> s = ...;
Observable<Value> getObservable() {
return s;
}
void addSource(Observable<Value> obs) {
obs.subscribe(v -> s.emit(s))
}
Notice that it's pseudocode and will probably not compile as is
Take a look to the Subject docs to see which one fits your needs better

Related

Correctly publish a Flux to multiple streams being merged later on

I am developing on a project utilizing Project Reactor, and due to requirements of the
project, I often have to retrieve values from an API, and then both store the result and return it.
What is the best way to do this?
Currently, I implemented it in the following way:
void main() {
getAndSaveBirds()
.subscribe(bird -> System.out.println(bird));
}
Flux<Bird> getAndSaveBirds() {
Flux<Bird> birds = api.getBirds().cache();
return birds.collectList()
.doOnSuccess(birdList -> performSideEffect(birdList))
.thenMany(birds);
}
But I am thinking that this might be a wasteful approach, as I now would save each Bird
unnecessarily.
I was considering the .share() operator, but the documentation regarding it is very sparse.
Which operator/program flow would be the correct here?

RxJava: How to extract object from observable?

I feel like this is a dumb question, but I couldn't find any answer for a while, so I'm gonna ask it, sorry :)
So, I need a function that does the following:
1) Calls another function to create an Observable User
2) Gets the User object from the Observable User
3) Gets some info about the user and runs through some logic
4) Returns Observable User
I am having troubles with step #2. How do I do that? Or, is this approach somehow fundamentally wrong?
Here's the "model" of the function:
#Override protected Observable buildUseCaseObservable(){
Observable<User> userObservable = userRepository.findUserByUsername(username);
//User user = ??????
//if (...) {...}
return userObservable;
}
Thank you :)
You can use operators(map, flatMap, doOnNext, etc) to get the object wrapped by your observable through the pipeline
Observable.just("hello world")
.map(sentence-> sentence.toUpperCase) --> do whatever you need.
.subscribe(sentence -> println(sentence)
By design Observable follow the Observer patter, which subscribe to the observable and receive the item once has been emitted through the pipeline.
Also what you can do is instead use observer patter, just extract the object from the pipeline using toBlocking. But that´s is consider an anti pattern and means you´re not applying a good design.
#Test
public void observableEvolveAndReturnToStringValue() {
assertTrue(Observable.just(10)
.map(String::valueOf)
.toBlocking()
.single()
.equals("10"));
}
You can see more examples about to Blocking here https://github.com/politrons/reactive/blob/master/src/test/java/rx/observables/utils/ObservableToBlocking.java
You cannot 'extract' something from an observable. You get items from observable when you subscribe to them (if they emit any). Since the object you are returning is of type Observable, you can apply operators to transform your data to your linking. The most common and easy to use operator in RxJava is 'map' which changes one form of data to other by applying a function.
In your case, you can use 'map' operator directly on Observable<user>:
return userRepository.findUserByUsername(username)
.map(new Func1<User, Object>() {
#Override
public Object call(User u) {
// ..
// apply your logic here
// ..
return myDataObject; // return you data here to subcribers
}
});
I hope you know the basics of RxJava and doesn't need any introduction about how to use operators. For map documentation, follow this link

How can I use .doOnNext() with Action2 (RxJava)

Observables only emit one object, so doOnNext() is always called with an Action1. How can I use Action2 in a similar fashion?
Can I combine 2 observables call an Action2?
EDIT: Why would I want to do this? I am working on a checkout app. I have a view that in order to display correctly, it needs two pieces of data (1: tip% and 2: total cost). So if this view could react to an observable sequence as an Action2, I would be happy.
EDIT2: Here's a method on the view mentioned previously. If this were an Action1, I could easily call it like I do with .doOnNext(). Are there operators that can operate similarly to .doOnNext() but take in an Action2 as a parameter? Maybe something like withLatestFrom() that takes in an Action2 instead of a Func2?
public Action2<Money, List<Integer>> displayGratuityOptions() {
return (subtotal, gratuityPercents) -> {
removeAllTabs();
for (final Integer percent : gratuityPercents) {
addTab(createTab(subtotal, percent));
}
addTab(createCustomGratuityTab());
};
}
Operators like withLatestFrom are there to combine multiple sequences into a single sequence. I think you will be better placed to work with Rx if you can adopt this way of thinking i.e. single data type sequences.
To this end I would suggest creating a type that has both the data types you want. You can then merge your data and then pass the single value to your doOnNext handler*.
This is simple stuff in most languages that Rx is used in (C#, F#, JS, Scala) but in Java, you may have to actually declare/define a type to do this. See - A Java collection of value pairs? (tuples?)
*Please try to avoid using the Do side-effect operators. There is almost always a better way. In you example it looks like you are doing some significant work in that handler (Creating, Adding and Removing tabs which I assume are Visual Controls)

Protect access to Java methods depending on custom conditions

In short: I want to allow/forbid the execution of Java methods depending on certain conditions. What is the best available solution/mechanism/technique?
Long question, via an (admittedly dumb) example:
Say I have several methods in a vehicle controller, like void openWindow(Window w), void openRoof(), void keepSpeed(double speedKmh). If it rains, the openRoof should not be called, and we want to put in place a mechanism to ensure it. Similarly, if the speed is below 60 km/h, keepSpeed is forbidden, like openWindow if it rains a lot or if the speed if above 100 km/h.
Since accessing the rain/speed sensors requires several lines of code, and these conditions are used everywhere, I don't want to use use assertions or conditions in the body of the methods, but I'd rather make them easily used by domain developers. Besides, I'd like the security concern to be separated from the actual logic of opening the windows, etc. More complex, custom conditions should be easy to configure too.
For instance, I'd like to have this:
#ForbidIf('default:rain') openWindow();
#ForbidIf('default:speedBelow(60)') keepSpeed();
#ForbidIf('default:speedAbove(100)', 'custom:rainsALot') openWindow();
If it helps, this application is a Spring-powered client-server application.
You can use a simple Spring AOP aspect, something like this (untested):
#Aspect
public class SecurityAspect{
#Pointcut("execution(#ForbidIf * *(*))")
public void annotatedMethodCalled(){}
#Before("annotatedMethodCalled() && #target(annotation) && target(bean)")
public void beforeRestrictedMethodCall(
final ForbidIf annotation, final Object bean){
final Expression expression =
new SpelExpressionParser().parseExpression(annotation.value());
if(!Boolean.TRUE.equals(expression.getValue(bean))){
throw new IllegalArgumentException();
}
}
}
Something similar is implemented in Spring Security as expression based access control, but I think it's not suitable in your case.
However, it should be easy to implement similar functionality from scratch by creating an aspect that can evaluate SpEL expressions against a certain context.
OP, commenting to Andreas_D's answer: "If the execution is forbidden, I want a runtime exception to be raised. In this case, if the condition is false, it means this method should have never been called under the current circumstances."
What's wrong with:
public void openWindow() {
if (itsRaining()) {
throw new IllegalStateException("Window should not open if it's raining");
}
}
? I mean, doing an annotation is effectively the same thing, only more complex (especially if your conditions for the method grow in complexity, for example if the window should not be opened if it's raining, snowing, vehicle speed > 100 KPh, wind speed > 6, temperature below freezing, etc).
Of course, I could also just be missing the point. Just wanted to give the hint that overthinking, -engineering or -complicating the problem aren't the only paths to take. Don't want to say that using AOP or annotations are overthinking/engineering/complication a problem, of course. Probably basing this post on the simplified example, too.
This is an interesting idea, although I see some real problems. You may annotate a method and refer to some environment settings. But if execution is forbidden, what should be done instead?
Consider this example:
#ForbidIf('default:durationIs(0))') double getSpeed(double distance);
and use it like
double speed = getSpeed(distance); // the duration is set globally in this example
What should happen if the duration value is set to 0 - what should be assigned to speed in that case? Or do you want to raise a runtime exception?
In your case, we already have two ways to implement conditional execution:
// check before calling
if (isSaveToOpenWindow())
openWindow();
and
public void openWindow() {
if (!isSaveToOpenWindow())
return;
// open window
}
Do you need AOP here? the Decorator pattern can be a lot simpler and requires a lot less magic. Just wrap the implementation with:
class ProtectedWindowOpener implements WindowOpener {
WindowOpener delegate ...
void openWindow(Window w) {
if (!allowOpen(w)) {
throw new PermissionDeniedException...
}
delegate.openWindow(w);
}
boolean allowOpen(Window w) {
// security logic here
}
}
Which keeps the security logic separate and also has the advantage of not embedding code in a string, which means eclipse can do its business.

Application design for processing data prior to database

I have a large collection of data in an excel file (and csv files). The data needs to be placed into a database (mysql). However, before it goes into the database it needs to be processed..for example if columns 1 is less than column 3 add 4 to column 2. There are quite a few rules that must be followed before the information is persisted.
What would be a good design to follow to accomplish this task? (using java)
Additional notes
The process needs to be automated. In the sense that I don't have to manually go in and alter the data. We're talking about thousands of lines of data with 15 columns of information per line.
Currently, I have a sort of chain of responsibility design set up. One class(Java) for each rule. When one rule is done, it calls the following rule.
More Info
Typically there are about 5000 rows per data sheet. Speed isn't a huge concern because
this large input doesn't happen often.
I've considered drools, however I wasn't sure the task was complicated enough for drols.
Example rules:
All currency (data in specific columns) must not contain currency symbols.
Category names must be uniform (e.g. book case = bookcase)
Entry dates can not be future dates
Text input can only contain [A-Z 0-9 \s]
etc..
Additionally if any column of information is invalid it needs to be reported when
processing is complete
(or maybe stop processing).
My current solution works. However I think there is room for improvement so I'm looking
for ideals as to how it can be improved and or how other people have handled similar
situations.
I've considered (very briefly) using drools but I wasn't sure the work was complicated enough to take advantage of drools.
If I didn't care to do this in 1 step (as Oli mentions), I'd probably use a pipe and filters design. Since your rules are relatively simple, I'd probably do a couple delegate based classes. For instance (C# code, but Java should be pretty similar...perhaps someone could translate?):
interface IFilter {
public IEnumerable<string> Filter(IEnumerable<string> file) {
}
}
class PredicateFilter : IFilter {
public PredicateFilter(Predicate<string> predicate) { }
public IEnumerable<string> Filter(IEnumerable<string> file) {
foreach (string s in file) {
if (this.Predicate(s)) {
yield return s;
}
}
}
}
class ActionFilter : IFilter {
public ActionFilter(Action<string> action) { }
public IEnumerable<string> Filter(IEnumerable<string> file) {
foreach (string s in file) {
this.Action(s);
yield return s;
}
}
}
class ReplaceFilter : IFilter {
public ReplaceFilter(Func<string, string> replace) { }
public IEnumerable<string> Filter(IEnumerable<string> file) {
foreach (string s in file) {
yield return this.Replace(s);
}
}
}
From there, you could either use the delegate filters directly, or subclass them for the specifics. Then, register them with a Pipeline that will pass them through each filter.
I think your method is OK. Especially if you use the same interface on every processor.
You could also look to somethink called Drules, currently Jboss-rules. I used that some time ago for a rule-heavy part of my app and what I liked about it is that the business logic can be expressed in for instance a spreadsheet or DSL which then get's compiled to java (run-time and I think there's also a compile-time option). It makes rules a bit more succint and thus readable. It's also very easy to learn (2 days or so).
Here's a link to the opensource Jboss-rules. At jboss.com you can undoubtedly purchase an offically maintained version if that's more to your companies taste.
Just create a function to enforce each rule, and call every applicable function for each value. I don't see how this requires any exotic architecture.
A class for each rule? Really? Perhaps I'm not understanding the quantity or complexity of these rules, but I would (semi-pseudo-code):
public class ALine {
private int col1;
private int col2;
private int coln;
// ...
public ALine(string line) {
// read row into private variables
// ...
this.Process();
this.Insert();
}
public void Process() {
// do all your rules here working with the local variables
}
public void Insert() {
// write to DB
}
}
foreach line in csv
new ALine(line);
Your methodology of using classes for each rule does sound a bit heavy weight but it has the advantage of being easy to modify and expand should new rules come along.
As for loading the data bulk loading is the way to go. I have read some informaiton which suggests it may be as much as 3 orders of magnitude faster than loading using insert statements. You can find some information on it here
Bulk load the data into a temp table, then use sql to apply your rules.
use the temp table, as a basis for the insert into real table.
drop the temp table.
you can see that all the different answers are coming from their own experience and perspective.
Since we don't know much about the complexity and number of rows in your system, we tend to give advice based on what we have done earlier.
If you want to narrow down to a 1/2 solutions for your implementation, try giving more details.
Good luck
It may not be what you want to hear, it isn't the "fun way" by any means, but there is a much easier way to do this.
So long as your data is evaluated line by line... you can setup another worksheet in your excel file and use spreadsheet style functions to do the necessary transforms, referencing the data from the raw data sheet. For more complex functions you can use the vba embedded in excel to write out custom operations.
I've used this approach many times and it works really well; its just not very sexy.

Categories

Resources