How do I return different response in the webflux based on whether the Flux object has elements? - flux

I know there is a function named "hasElements" on a Flux object. But it behaves a bit strangeļ¼
Flux<RoomBO> rooms=serverRequest.bodyToMono(PageBO.class).flatMapMany(roomRepository::getRooms);
return rooms.hasElements().flatMap(aBool -> aBool?ServerResponse.ok().body(rooms,RoomBO.class):ServerResponse.badRequest().build());
return ServerResponse.ok().body(rooms,RoomBO.class)
The second return statement can return the right things I need when the flux object is not empty,but the first return statement only returns a empty array,which likes "[]" in json.I don't know why this could happen!I use the same data to test.The only difference is that I call the hasElements function in the first situation.But I need to return badRequest when the flux object is empty. And the hasElements function seems to make my flux object empty,though I know it doesn't do this actually.

well, finally I decide to call switchIfEmpty(Mono.error()) to throw an error and then I deal with the special error globally(Sometimes it's not suitable to use onErrorReturn or onErrorResume). I think this can avoid the collect operation in memory when meets big data. But it's still not a good solution for the global error handler can be hard to maintain. I'd expect someone to give a better solution.

In your example you are transforming class Flux to class RoomBO, it is one of the reasons, why you get an empty array.
If you need to return the processed list of rooms, then, I think, collectList should be your choice. https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Flux.html#collectList--
Flux<RoomBO> roomsFlux = serverRequest.bodyToMono(PageBO.class)
.flatMapMany(roomRepository::getRooms);
return rooms
.collectList()
.flatMap(rooms -> !rooms.isEmpty() ? ServerResponse.ok().bodyValue(rooms) : ServerResponse.badRequest().build());

Related

Spring Webflux: efficiently using Flux and/or Mono stream multiple times (possible?)

I have the method below, where I am calling several ReactiveMongoRepositories in order to receive and process certain documents. Since I am kind of new to Webflux, I am learning as I go.
To my feeling the code below doesn't feel very efficient, as I am opening multiple streams at the same time. This non-blocking way of writing code makes it complicated somehow to get a value from a stream and re-use that value in the cascaded flatmaps down the line.
In the example below I have to call the userRepository twice, since I want the user at the beginning and than later as well. Is there a possibility to do this more efficiently with Webflux?
public Mono<Guideline> addGuideline(Guideline guideline, String keycloakUserId) {
Mono<Guideline> guidelineMono = userRepository.findByKeycloakUserId(keycloakUserId)
.flatMap(user -> {
return teamRepository.findUserInTeams(user.get_id());
}).zipWith(instructionRepository.findById(guideline.getInstructionId()))
.zipWith(userRepository.findByKeycloakUserId(keycloakUserId))
.flatMap(objects -> {
User user = objects.getT2();
Instruction instruction = objects.getT1().getT2();
Team team = objects.getT1().getT1();
if (instruction.getTeamId().equals(team.get_id())) {
guideline.setAddedByUser(user.get_id());
guideline.setTeamId(team.get_id());
guideline.setDateAdded(new Date());
guideline.setGuidelineStatus(GuidelineStatus.ACTIVE);
guideline.setGuidelineSteps(Arrays.asList());
return guidelineRepository.save(guideline);
} else {
return Mono.error(new InstructionDoesntBelongOrExistException("Unable to add, since this Instruction does not belong to you or doesn't exist anymore!"));
}
});
return guidelineMono;
}
i'll post my earlier comment as an answer. If anyone feels like writing the correct code for it then go ahead.
i don't have access to an IDE current so cant write an example but you could start by fetching the instruction from the database.
Keep that Mono<Instruction> then you fetch your User and flatMap the User and fetch the Team from the database. Then you flatMap the team and build a Mono<Tuple> consisting of Mono<Tuple<User, Team>>.
After that you take your 2 Monos and use zipWith with a Combinator function and build a Mono<Tuple<User, Team, Instruction>> that you can flatMap over.
So basically fetch 1 item, then fetch 2 items, then Combinate into 3 items. You can create Tuples using the Tuples.of(...) function.

How to Extract the String value from MONO/FLUX -

I am new to reactor programming,and need some help on MONO/Flux
I have POJO class
Employee.java
class Employee {
String name
}
I have Mono being returned on hitting a service, I need to extract the name from Mono as a string.
Mono<Employee> m = m.map(value -> value.getName())
but this returns again a Mono but not a string. I need to extract String value from this Mono.
You should do something like this:
m.block().getName();
This solution doesn't take care of null check.
A standard approach would be:
Employee e = m.block();
if (null != e) {
e.getName();
}
But using flux you should proceed using something like this:
Mono.just(new Employee().setName("Kill"))
.switchIfEmpty(Mono.defer(() -> Mono.just(new Employee("Bill"))))
.block()
.getName();
Keep in mind that requesting for blocking operation should be avoided if possible: it blocks the flow
You should be avoiding block() because it will block indefinitely until a next signal is received.
You should not think of the reactive container as something that is going to provide your program with an answer. Instead, you need to give it whatever you want to do with that answer. For example:
employeeMono.subscribe(value -> whatYouWantToDoWithName(value.getName()));

Extracting all children belongs to specific parent in graphql

I am using GrapgQL and Java. I need to extract all the children belongs to specific parent. I have used the below way but it will fetch only the parent and it does not fetch any children.
schema {
query: Query
}
type LearningResource{
id: ID
name: String
type: String
children: [LearningResource]
}
type Query {
fetchLearningResource: LearningResource
}
#Component
public class LearningResourceDataFetcher implements DataFetcher{
#Override
public LearningResource get(DataFetchingEnvironment dataFetchingEnvironment) {
LearningResource lr3 = new LearningResource();
lr3.setId("id-03");
lr3.setName("Resource-3");
lr3.setType("Book");
LearningResource lr2 = new LearningResource();
lr2.setId("id-02");
lr2.setName("Resource-2");
lr2.setType("Paper");
LearningResource lr1 = new LearningResource();
lr1.setId("id-01");
lr1.setName("Resource-1");
lr1.setType("Paper");
List<LearningResource> learningResources = new ArrayList<>();
learningResources.add(lr2);
learningResources.add(lr3);
learningResource1.setChildren(learningResources);
return lr1;
}
}
return RuntimeWiring.newRuntimeWiring().type("Query", typeWiring -> typeWiring.dataFetcher("fetchLearningResource", learningResourceDataFetcher)).build();
My Controller endpoint
#RequestMapping(value = "/queryType", method = RequestMethod.POST)
public ResponseEntity query(#RequestBody String query) {
System.out.println(query);
ExecutionResult result = graphQL.execute(query);
System.out.println(result.getErrors());
System.out.println(result.getData().toString());
return ResponseEntity.ok(result.getData());
}
My request would be like below
{
fetchLearningResource
{
name
}
}
Can anybody please help me to sort this ?
Because I get asked this question a lot in real life, I'll answer it in detail here so people have easier time googling (and I have something to point at).
As noted in the comments, the selection for each level has to be explicit and there is no notion of an infinitely recursive query like get everything under a node to the bottom (or get all children of this parent recursively to the bottom).
The reason is mostly that allowing such queries could easily put you in a dangerous situation: a user would be able to request the entire object graph from the server in one easy go! For any non-trivial data size, this would kill the server and saturate the network in no time. Additionally, what would happen once a recursive relationship is encountered?
Still, there is a semi-controlled escape-hatch you could use here. If the scope in which you need everything is limited (and it really should be), you could map the output type of a specific query as a (complex) scalar.
In your case, this would mean mapping LearningResource as a scalar. Then, fetchLearningResource would effectively be returning a JSON blob, where the blob would happen to be all the children and their children recursively. Query resolution doesn't descent deeper once a scalar field is reached, as scalars are leaf nodes, so it can't keep resolving the children level-by-level. This means you'd have to recursively fetch everything in one go, by yourself, as GraphQL engine can't help you here. It also means sub-selections become impossible (as scalars can't have sub-selections - again, they're leaf nodes), so the client would always get all the children and all the fields from each child back. If you still need the ability to limit the selection in certain cases, you can expose 2 different queries e.g. fetchLearningResource and fetchAllLearningResources, where the former would be mapped as it is now, and the latter would return the scalar as explained.
An object scalar implementation is provided by the graphql-java ExtendedScalars project.
The schema could then look like:
schema {
query: Query
}
scalar Object
type Query {
fetchLearningResource: Object
}
And you'd use the method above to produce the scalar implementation:
RuntimeWiring.newRuntimeWiring()
.scalar(ExtendedScalars.Object) //register the scalar impl
.type("Query", typeWiring -> typeWiring.dataFetcher("fetchLearningResource", learningResourceDataFetcher)).build();
Depending on how you process the results of this query, the DataFetcher for fetchLearningResource may need to turn the resulting object into a map-of-maps (JSON-like object) before returning to the client. If you simply JSON-serialize the result anyway, you can likely skip this. Note that you're side-stepping all safety mechanisms here and must take care not to produce enormous results. By extension, if you need this in many places, you're very likely using a completely wrong technology for your problem.
I have not tested this with your code myself, so I might have skipped something important, but this should be enough to get you (or anyone googling) onto the right track (if you're sure this is the right track).
UPDATE: I've seen someone implement a custom Instrumentation that rewrites the query immediately after it's parsed, and adds all fields to the selection set if no field had already been selected, recursively. This effectively allows them to select everything implicitly.
In graphql-java v11 and prior, you could mutate the parsed query (represented by the Document class), but as of v12, it will no longer be possible, but instrumentations in turn gain the ability to replace the Document explicitly via the new instrumentDocument method.
Of course, this only makes sense if your schema is such that it can not be exploited or you fully control the client so there's no danger. You could also only do it selectively for some types, but it would be extremely confusing to use.

Design choice: Any good reason for 'ToArray()' LINQ extension to throw an exception for null collections?

Unsurprisingly, following code will throw an ArgumentNullException
IEnumerable<string> collection = null;
string[] collectionViewAsAnArray = collection.ToArray();
This looks obvious at first sight ... but ain't incoherent to argue that returning null may have been a reasonnable alternative (Accounting that ToArray() is an extension method and therefor can be called, even on null).
While I acknowledge, this way, extension behave like a real method, I can't help finding the other approach really smart too ... but this may lead to other issues?
Granted IEnumerable is an interface used in collections but the underlying implementation is an object and you have set that collection variable to point to null, hence the exception.
If on the other hand you initialized collection with:
IEnumerable<string> collection = Enumerable.Empty<string>();
OR
IEnumerable<string> collection = new List<string>();
You would have an empty list object that you could act on. The ArgumentNullException exception is thrown because the collection argument is in fact null and that is what ToArray() is trying to act on. So logically, to me anyways, this was the only design choice.
Edit
On the other hand, in practice, I've made the conscious decision to always return a valid IEnumerable<T> when the return type on my class methods are supposed to return an IEnumerable<T>.
For example; a method signature that looks like IEnumerable<T> GetAll() would always return a valid enumerable and If there was nothing to return then I would return return Enumerable.Empty<T>();
The difference here to me is that GetAll() is not acting on a collection argument. You could really look at this like the collection is really nothing more than a parameter to the method and if you passed in a null parameter to a regular method you would probably throw an ArgumentNullException.
The short answer is that your collection variable is an expected argument (or parameter) to the ToArray() method and it is null so it makes sense to throw an ArgumentNullException.
Why push the error to some other spot in your code? If you expect that something can be null, check it before you use it. Otherwise throw an error exactly at the spot where your assumption was false, namely when you tried to convert it to an array.
I understand it can be debatable when you're chaining operations but in those cases I've found it easier to work with an empty IEnumerable rather than a null one.

Which syntax is better for return value?

I've been doing a massive code review and one pattern I notice all over the place is this:
public bool MethodName()
{
bool returnValue = false;
if (expression)
{
// do something
returnValue = MethodCall();
}
else
{
// do something else
returnValue = Expression;
}
return returnValue;
}
This is not how I would have done this I would have just returned the value when I knew what it was. which of these two patterns is more correct?
I stress that the logic always seems to be structured such that the return value is assigned in one plave only and no code is executed after it's assigned.
A lot of people recommend having only one exit point from your methods. The pattern you describe above follows that recommendation.
The main gist of that recommendation is that if ou have to cleanup some memory or state before returning from the method, it's better to have that code in one place only. having multiple exit points leads to either duplication of cleanup code or potential problems due to missing cleanup code at one or more of the exit points.
Of course, if your method is couple of lines long, or doesn't need any cleanup, you could have multiple returns.
I would have used ternary, to reduce control structures...
return expression ? MethodCall() : Expression;
I suspect I will be in the minority but I like the style presented in the example. It is easy to add a log statement and set a breakpoint, IMO. Plus, when used in a consistent way, it seems easier to "pattern match" than having multiple returns.
I'm not sure there is a "correct" answer on this, however.
Some learning institutes and books advocate the single return practice.
Whether it's better or not is subjective.
That looks like a part of a bad OOP design. Perhaps it should be refactored on the higher level than inside of a single method.
Otherwise, I prefer using a ternary operator, like this:
return expression ? MethodCall() : Expression;
It is shorter and more readable.
Return from a method right away in any of these situations:
You've found a boundary condition and need to return a unique or sentinel value: if (node.next = null) return NO_VALUE_FOUND;
A required value/state is false, so the rest of the method does not apply (aka a guard clause). E.g.: if (listeners == null) return null;
The method's purpose is to find and return a specific value, e.g.: if (nodes[i].value == searchValue) return i;
You're in a clause which returns a unique value from the method not used elsewhere in the method: if (userNameFromDb.equals(SUPER_USER)) return getSuperUserAccount();
Otherwise, it is useful to have only one return statement so that it's easier to add debug logging, resource cleanup and follow the logic. I try to handle all the above 4 cases first, if they apply, then declare a variable named result(s) as late as possible and assign values to that as needed.
They both accomplish the same task. Some say that a method should only have one entry and one exit point.
I use this, too. The idea is that resources can be freed in the normal flow of the program. If you jump out of a method at 20 different places, and you need to call cleanUp() before, you'll have to add yet another cleanup method 20 times (or refactor everything)
I guess that the coder has taken the design of defining an object toReturn at the top of the method (e.g., List<Foo> toReturn = new ArrayList<Foo>();) and then populating it during the method call, and somehow decided to apply it to a boolean return type, which is odd.
Could also be a side effect of a coding standard that states that you can't return in the middle of a method body, only at the end.
Even if no code is executed after the return value is assigned now it does not mean that some code will not have to be added later.
It's not the smallest piece of code which could be used but it is very refactoring-friendly.
Delphi forces this pattern by automatically creating a variable called "Result" which will be of the function's return type. Whatever "Result" is when the function exits, is your return value. So there's no "return" keyword at all.
function MethodName : boolean;
begin
Result := False;
if Expression then begin
//do something
Result := MethodCall;
end
else begin
//do something else
Result := Expression;
end;
//possibly more code
end;
The pattern used is verbose - but it's also easier to debug if you want to know the return value without opening the Registers window and checking EAX.

Resources