How can I access a state using the same-id across multiple transformers, for example the following stores an Order object via ValueState in OrderMapper class:
env.addSource(source1()).keyBy(Order::getId).flatMap(new OrderMapper()).addSink(sink1());
Now I would like to access the same Order object via a SubOrderMapper class:
env.addSource(source2()).keyBy(SubOrder::getOrderId).flatMap(new SubOrderMapper()).addSink(sink2());
Edit: Looks like it's not possible to have state maintained across multiple operators, is there a way to have one operator accept multiple inputs, lets say 5 sources?
Take a look at CoProcessFunction
To realize low-level operations on two inputs, applications can use
CoProcessFunction or KeyedCoProcessFunction. This function is bound to
two different inputs and gets individual calls to processElement1(...)
and processElement2(...) for records from the two different inputs.
Also side outputs might be useful for you. side output
Edit:
Union operator my be an option.
Union
You can create a custom EitherOfFive class that contains one of your five different stream values (I'm assuming they are all different). See Flink's Either class for the one of two case.
Each input stream would use a Map function that converts the input class type to an EitherOfFive type.
There would be a getKey() method that would figure out (based on which of the five values is actually set) what key to return. And then you can have a single KeyedProcessFunction that takes as input this EitherOfFive type.
If the output is always the same, then you're all set. Otherwise you'll want side outputs, one per type, that feed the five different sinks.
Related
I am currently working on a Rest API, in a get method which suppose to return an Array of objects in json format I now have the requirement to sort the result by a field passed as a parameter to the method. Consider for example the object to be
public class ExampleType {
int firstField ;
String secondField ;
}
Now according to the requirements the Rest API user should be able to pass as a parameter among other things either "firstField" or "secondField" and I should be sorting the array containing the result objects using this field.
Apparently my model is not so simplistic as the example, I do have more than 15 fields which could potentially be the one that I need to sort by, so an else if statement is not a choice at this point. My question is does anybody had a similar requirement for a rest api and if so how did you tackle it ? Or any recommendation on what could potentially by an elegant solution to my problem would be greatly appreciated.
You should create a Comparator and then use this to sort your data.
The comparators could be stored in a static map to avoid a switch/case if/else:
map.put("fieldName", Comparator.comparing(ExampleType::getFirstField));
You can combine two or more comparators using the thenComparing method.
The only other option is to create the appropriate comparators using reflection.
Note: requirements of API consumers often are not requirements that should be implemented in the API itself. You may also consider that sorting output is in fact a display problem and not something that an API needs to be concerned with.
It depends on the situation though, if data needs to be paginated then you may have no option other than to sort at the API level.
This question is more about the convention or approach to follow.
So, I have an scenario in which there are four input text fields on the view in two pairs, lets say they are:
first pair : FirstName and LastName
second pair : Department and designation
and there is only one search button. Here, if user starts enter into the first pair, the second pair got disabled/non-editable and vice-versa.
When user clicks on the search button, request goes to some controller/servlet/action,
Now, in my business logic, what should be the approach to write method(s) for this search.
write a single method for all four fields then check the value of the arguments, and decide what would be the query to perform.
write two methods with specified paired parameters only.
The less arguments the better (if your following the "Clean Code" school, as taught by Robert Martin for example).
In your case: isn't the best option to pass down some sort of Map? Keys could be the various search "categories"; and values would be the corresponding values. That way, there is always only one parameter; and your business logic is written right from the beginning to simply deal with all map entries?
That way, you can always add/remove categories, without changing the interface.
EDIT: as you are still asking about the "conceptional" 2 vs 4 parameter thing; for that I would suggest: do some research; you can start studying here!
Number one is the worst solution imho. I'd write a simple container for the four values and pass that container to one specific function. That way you can put validation logic in that container and have the function simply do its work.
I have a class with 10s of parameters. I want to encode and decode (back to) this class with limited number of parameters (let's say 3). It means, I am not worried if other parameters change. Assume those keys to be primary keys of the table and we are only concerned about them.
I can obviously use Base64 encoding/decoding to do the final job but handing different object types among those parameters was coming out to be multiple lines of code (with type checks).
One better thing I can think of it using JSON parsing to convert objects first to a JSON then use the encoding but that will again need specifically choosing the parameters. What could be the best way to perform this?
I've got loads of the following to implement.
validateParameter(field_name, field_type, field_validationMessage, visibleBoolean);
Instead of having 50-60 of these in a row, is there some form of nested hashmap/4d array I can use to build it up and loop through them?
Whats the best approach for doing something like that?
Thanks!
EDIT: Was 4 items.
What you could do is create a new Class that holds three values. (The type, the boolean, and name, or the fourth value (you didn't list it)). Then, when creating the HashMap, all you have to do is call the method to get your three values. It may seem like more work, but all you would have to do is create a simple loop to go through all of the values you need. Since I don't know exactly what it is that you're trying to do, all I can do is provide an example of what I'm trying to do. Hope it applies to your problem.
Anyways, creating the Class to hold the three(or four) values you need.
For example,
Class Fields{
String field_name;
Integer field_type;
Boolean validationMessageVisible;
Fields(String name, Integer type, Boolean mv) {
// this.field_name = name;
this.field_type = type;
this.validationMessageVisible = mv;
}
Then put them in a HashMap somewhat like this:
HashMap map = new HashMap<String, Triple>();
map.put(LOCAL STRING FOR NAME OF FIELD, new Field(new Integer(YOUR INTEGER),new Boolean(YOUR BOOLEAN)));
NOTE: This is only going to work as long as these three or four values can all be stored together. For example if you need all of the values to be stored separately for whatever reason it may be, then this won't work. Only if they can be grouped together without it affecting the function of the program, that this will work.
This was a quick brainstorm. Not sure if it will work, but think along these lines and I believe it should work out for you.
You may have to make a few edits, but this should get you in the right direction
P.S. Sorry for it being so wordy, just tried to get as many details out as possible.
The other answer is close but you don't need a key in this case.
Just define a class to contain your three fields. Create a List or array of that class. Loop over the list or array calling the method for each combination.
The approach I'd use is to create a POJO (or some POJOs) to store the values as attributes and validate attribute by attribute.
Since many times you're going to have the same validation per attribute type (e.g. dates and numbers can be validated by range, strings can be validated to ensure they´re not null or empty, etc), you could just iterate on these attributes using reflection (or even better, using annotations).
If you need to validate on the POJO level, you can still reuse these attribute-level validators via composition, while you add more specific validations are you´re going up in the abstraction level (going up means basic attributes -> pojos -> pojos that contain other pojos -> etc).
Passing several basic types as parameters of the same method is not good because the parameters themselves don't tell much and you can easily exchange two parameters of the same type by accident in the method call.
There are often times when I have need for a RowCallbackHandler, because in processing the result set I don't map each row to a single type, nor each result set to a single data structure. Instead, I may map the majority rows to a specific Java bean, and add the remainder to a list for post-processing.
In these cases, I need a callback with return type void, and the only callback which satisfies this is RowCallbackHandler.
But I don't come across many examples of this, and I have to admit, it's aesthetically nicer to use JDBC and loop through a ResultSet, than to use the clunky Spring callbacks. Is RowCallbackHandler more common than I think? I'm curious what people have to say...
Edit: Some people have asked for my data model. Okay, there's a nodes table and an edges table. If there's an edge between nodes A and B, that edge can signify two things:
A and B are disjoint nodes that interact
A is a member of B, or vice versa
In the second case, I need to add these group nodes to a list. They can't be mapped to a Java bean yet, because they don't signify interactions between disjoint nodes.
Perhaps what I should be doing, instead, is to have 2 queries, one that retrieves case (1), another that retrieves case (2). Case (1) could be mapped to a Java bean, case (2) to a List.
If this is indeed better, then maybe RowCallbackHandler is a bad code smell?
If what you want is to process the whole result set, without returning anything, simply use a ResultSetExtractor<Void> (and one of the JdbcTemplate methods taking it as argument).
You can create a new class that's composed of your bean objects(s), plus the list. Then fill it in a ResultSetExtractor or RowCallbackHandler. Then your return type can change from void to the new class' type.