Spring reactor doOnNext, is it getting executed? - spring

I was playing around with reactor
public #NotNull Mono<ServerResponse> findXXXXSse(final ServerRequest request) {
return request.bodyToMono(XXXXSearch.class)
.doOnNext(this::validate)
.flatMap(this::findXXXXSse)
.switchIfEmpty(this.emptyBodyException());
}
And I was wondering if the use of .doOnNext(this::validate) was correct or not. From my point of view, I'm not sure the validate is called before the findXXXXSse?
Am I wrong?

Flux.doOnNext method should always be used as a side-effect.
The documentation says "Add behavior (side-effect) triggered when the Flux emits an item." Refer : https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Flux.html#doOnNext-java.util.function.Consumer-
I assume you want to resume your chain only when the validation is successful, i.e., .flatMap(this::findXXXXSse) should only be called if validation succeeds.
You can use filter(this::validate) and add a validate(XXXXSearch.class) method to return true/false.

Related

NServiceBus - Aggregate Root - Saga - Synchronous Command

Having an aggregate root User modeled as NServiceBus Saga
User.cs
public class User {
....
public string Rename(string name) {
.// some validation logic
}
...
}
UserSagaData.cs
public class UserSagaData : ContainSagaData
{
public User User { get; set;}
}
UserSaga.cs
public partial class UserSaga : Saga<RenameUser>
{
...
public async Task Handle(RenameUserimportAttendees, IMessageHandlerContext context)
{
Data.User.rename(...
}
...
}
Now i have a requirement to accept RenameUser command via REST API and give the feedback in HTTP Response, hence sending RegisterUser to message broker from Controller.Action is not an option. I need to perform command synchronously, get feedback and send http response.
First thing that came to mind is to use ISagaPersister, that is, retrieve saga by id, then invoke a command and then persist saga back to the datastore with ISagaPersister (which takes care of optimistic locking). Any thoughts on that ?
Is there alternative solutions to this problem ?
What type of feedback would you expect the RenameUser command to result in?
Can’t you just return a HTTP OK and queue up the rename command? (assuming that you have validation of the new name in place the chances of something going wrong should be slim and could be dealt with offline should the command end up in the error queue?)
An option if you really have to wait for the response is to use our callbacks package, https://docs.particular.net/nservicebus/messaging/callbacks, to enable your REST API block until the response has arrived, this way you can still using messaging behind the scenes.
What do you think?

Why does the first AJAX call reset my view parameter?

I cannot find out why the first ajax call causes the setter of my view parameter to be called again while every subsequent call does not call the setter again.
I have the following simple view bean:
package test;
import java.io.Serializable;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
#Named
#ViewScoped
public class TestController implements Serializable {
private static final long serialVersionUID = 1L;
String param;
public String getParam() {
return param;
}
public void setParam(String param) {
System.out.println("param set to " + param);
this.param = param;
}
}
I also have a very basic .xhtml page which only contains a single button:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head></h:head>
<f:metadata>
<f:viewParam id="param" name="param" value="#{testController.param}"/>
</f:metadata>
<h:form id="form">
<h:commandButton id="button" value="Test">
<f:ajax execute="#this"></f:ajax>
</h:commandButton>
</h:form>
</html>
Now when testing this page I call https://localhost:8443/test/test.xhtml?param=foo in my browser. As I expected the log claims that the view parameter was set to "foo". Now where I'm struggling is that when I first press the button the log again claims that param was set to "foo" proving that the setter was called again. I do not understand why the view parameter is set again by the ajax request. It also puzzles me that any subsequent button click will not call the view parameter's setter again, especially as the first and all subsequent calls look exactly alike.
So my questions are:
Why is the view parameter's setter called on the first ajax call but not on subsequent calls?
Is there any way to prevent this behavior?
I'm running the example on Wildfly 19 which uses Mojarra 2.3.9.SP06 if that is of any help.
EDIT 1: To make it clearer, why this question is different from f:viewParam lost after ajax call. The other question asks why the view parameters are lost after the first ajax call and how to always send them. This is question asks exactly the opposite: Why are the view parameters send the first time anyway and how to prevent this?
The answer to the other question claims that one can call FacesContext.getCurrentInstance().isPostback(). I'm aware of this. While it of course works in the sense of detecting the ajax recall and enables me to not reset the view parameters in this case it does not prevent the view parameter's setter from being called in the first place. This is what I ideally want to achieve. I would also content myself with at least understanding why the view parameters are treated differently on the first ajax call. I guess there is something conceptually I have not understood.
EDIT 2: I filed a bug report under https://github.com/eclipse-ee4j/mojarra/issues/4714.
There is nothing you conceptually misunderstood. I don't understand it either.
I'm currently still investigating on the why the setter is called on the first and only on the first ajax callback. I would have expected it to be always or never called. The analysis of #fuggerjaki61 is somewhat in the right direction but it seems to be related to the bigger issue around null or not submitted values.
Lots of info can be read in what is the easiest solution: the OmniFaces o:viewParam instead of f:viewParam
And use
<o:viewParam id="param" name="param" value="#{testController.param}"/>
(do not forget to declare xmlns:o="http://omnifaces.org/ui", but since you should ;-) be using OmniFaces anyway, I assume it is already there :-) )
From al info I read I thought that maybe setting
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>
might solve it as well, but it does not. The setter is still called with the old value on the first ajax call and on the second and subsequent calls it only explicitly sets the value to null if it is not submitted. Also not what you seem to be wanting.
More details
The solution of #fuggerjaki61 might work, but I'm not sure about the consequences in other situations, since I can also get a fix for this issue by changing other things but breaking other cases. And if I try to compare the basics of o:viewParam with f:viewParam the submitted value (as referred to by #fuggerjaki61 in the other answer) does play a role. It is kept local in the o:viewParam
#Override
public String getSubmittedValue() {
return submittedValue;
}
#Override
public void setSubmittedValue(Object submittedValue) {
this.submittedValue = (String) submittedValue; // Don't delegate to statehelper to keep it stateless.
}
while in the f:viewParam it is being read from and set to the stateHelper
#Override
public Object getSubmittedValue() {
return getStateHelper().get(PropertyKeys.submittedValue);
}
/**
* PENDING (docs) Interesting that submitted value isn't saved by the parent
* #param submittedValue The new submitted value
*/
#Override
public void setSubmittedValue(Object submittedValue) {
getStateHelper().put(PropertyKeys.submittedValue, submittedValue);
}
Reading the java docs here I'd personally say on the "why" in your question to me looks like there is a bug (or omission) somewhere, yet to be identified, but either accidentilly or explicitly solved by o:viewParam
Quick Solutions
The best way to solve this problem is using the o:form with includeViewParams set to true (setParam called on every ajax request; only way when parameters can change in ajax requests).
OR
Already said by #Kukeltje using the o:viewParam (that does the same like overriding the UIViewParameter), so the setParam method is only called once at the beginning.
Explanation
Basically is the parameter value saved during the initial request to the first ajax request. After first ajax request the value is finally lost.
Probably the best way to understand this is to analyse phase for phase (looking at the source code to see what the methods do is also helpful):
Initial Request
Restore View Phase: nothing specific
Apply Request Values Phase: decode called and rawValue is set with the current parameter value
Process Validations Phase: nothing specific
Update Model Values Phase: setParam is called and after that UIInput.resetValues() that sets the submittedValue to null
Invoke Application Phase: nothing specific
Render Response Phase: setSubmittedValue (which was null) is called with rawValue (rawValue was already set; see Apply Request Values Phase)
First Ajax
Restore View Phase: rawValue is reinitialized to null
Apply Request Values Phase: decode called and rawValue is set with the current parameter value (parameter value is null)
Process Validations Phase: nothing specific
Update Model Values Phase: setParam is called with the submittedValue that was set to null but then set again in Render Response Phase; UIInput.resetValues() is called again and submittedValue is set to null.
Invoke Application Phase: nothing specific
Render Response Phase: setSubmittedValue is again called and set to rawValue which is null
Every following ajax request
submittedValue and rawValue is null so every possibility to restore the parameter value is destroyed. setParam is never called again.
All Solution
Overriding the encodeAll method to do nothing anymore, so UIInput.resetValues() resets values forever (see how to override components)
Using o:viewParam (doesn't have rawValue variable)
Using o:form
When the parameters don't change during ajax requests the top two solutions are the best.
Overriding UIViewParameter
To override the UIViewParameter create a class that extends the UIViewParameter and add this to the faces-config.xml:
<component>
<component-type>javax.faces.ViewParameter</component-type>
<component-class>com.example.CustomUIViewParameter</component-class>
</component>

How to handle Optional from Service to Controller in Spring?

Spring JPA returns an Optional. I return the Optional from the Service. There if Optional is not present I pass error to model. The other case if there is a database error for example database not available, I do not catch these exceptions. If that happens user will see this exception in browser. I do not know how to handle this very rare error. For me this should never happen and if it does, ok . I do not want to handle this exception all the time. What do you think about my architecture.
Service:
#Override
public Optional<Client> findClientById(Long id) {
return clientRepository.findById(id);
}
Controller:
Optional<Client> client= clientService.findClientById(id);
if(client.isPresent())
{
model.addAttribute("client", client.get());
}
else
{
model.addAttribute("error", "No clientfound with this ID!!");
}
Firstly, you shouldn't pass error as an attribute in your model - that's REST anti-pattern. The best way to hand this is to use HTTP codes, e.g. return 502. To do so, you may wrap your exceptions up your code into HttpResponse. To catch your exception, you may approach similar to method that explained here, i.e. catch spring data exception, wrap it up a way you wanted and throw on higher level for processing.

How to enforce Grails command objects have been validated?

We use the following general pattern with Grails controllers and command objects
SomeController {
def someAction() {
SomeCommandObject co = SomeCommandObject.valueOf(params)
if(!co.validate()) {
// return bad request
}
someService.doWork(co)
// return ok
}
SomeService {
def doWork(SomeCommandObject co) {
notTrue(!co.hasErrors(), 'cant have errors') // Commons validation
// do actual work
}
}
Apparently, if co.validate() has not been called, .hasErrors() will always return false. Is there a better way to enforce that .validate() has been called before a command object is passed between application layers? We don't want to pass around invalid command objects but we don't want to force every new method to re-validate the command object either.
Note: We aren't using the default controller/command object creation pattern because we need to do some custom parameter map checking, we use a static valueOf method instead to create the command object. Answers that change that practice are also welcome.
EDIT: A little more info on why we aren't using the 'default' controller/command object creation. Specifically why we aren't doing ..
def someAction(SomeCommandObject co) {
}
We have a requirement to disallow random query parameters, eg. endpoint/object?color=blue. To do that we need access to the parameter map in the command object to verify that it doesn't contain any 'unexpected' parameter keys. As I understand it, the default way would just create a member on the CO named color, and I don't see how to prevent arbitrary members using even custom validators. I'd happily entertain suggestions for doing so, thereby allowing us to use this default means.
Yes; what you can do is pass the command object as a parameter to the controller, and then the command will always be validated automatically.
Also, what you can do, is to make a filter or similar, so that you don't have to check for the hasErrors() each time, but handle all the cases in the same way (for example, by throwing an error, or returning with a specific response).
In an application we created, we had something like:
withValidCommand(cmd) {
// do work
}
Which worked pretty well. But maybe you can come up something even more elegant.
You should be doing this:
def someAction(SomeCommandObject co) {
if (!co.hasErrors()) {
someService.doWork(co)
}
}
By passing SomeCommandObject in as the argument grails will automatically populate it from params and validate. No need to do it manually.

Spring mvc controller null return handler

#RequestMapping(method = RequestMethod.GET)
#ResponseBody
public List<Country> getListOfCountries() {
return countryService.listAll();
}
It displays a json view of the object but if the service return null, then I want to display an error message, Any suggestions pls?
First of all, even if this does not directly answer the question, your objects should never ever return null instead of empty collections - you can find the reasoning in Effective Java 2nd Edition, Item 43 / p.201
So, if the situation when no countries were found is normal it must be processed by the client JS code that will check the count and display the respective message.
If something has gone wrong you can throw an exception(as Biju has pointed out +1) - I believe that it's the service who should throw the exception because it knows the reason why it happened, and not to return null anyway.
I'd like to add that in Spring 3.2(in pre Spring 3.2 returning response body is complicated) you can set an #ExceptionHandler that will both return JSON and set the HTTP status code which can be later processed by the client. I think that returning a custom JSON response with some error code is most optimal here.
#RequestMapping("/test")
#ResponseBody
public List<Country> getListOfCountries() {
//assuming that your service throws new NoCountriesFoundException();
//when something goes wrong
return countryService.listAll();
}
#ExceptionHandler(NoCountriesFoundException.class)
ResponseEntity<String> test() {
return new ResponseEntity<String>(
"We are sorry, our server does not know any countries yet.",
HttpStatus.I_AM_A_TEAPOT );
}
Then in the JS code, you can do specific processing depending on the returned status code.
Also, to avoid declaration of the same #ExceptionHandler in different controllers, in Spring 3.2 you can put #ExceptionHandler inside a #ControllerAdvice annotated class.
For details, see http://static.springsource.org/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-exceptionhandlers and http://www.springsource.org/node/3738 for 3.2 specific things
You have a couple of options I think:
If you return a null back, it will be returned as an empty string "", you can probably look for that and handle it.
Return a wrapper type on top of your list, this way if the wrapped list is null something like this will be returned back to the client {"countries":null} which can be more easily handled at the javascript end.
Throw an exception, which will propagate as a 500 status code back to the client, you can then have an error handler on the javascript side to handle this scenario.

Resources