ActionResult , exception with new Jodd version - jodd

I have some code which works Ok with jodd 3.9.1 and I want to upgrade it to jodd version 4.1.4. but I have some errors:
Example:
#POST #Action
public String save(){
... some code for validation
if (!valid){
return VTOR_JSON; //Error
}
service.store(Object);
return NONE; //Error
}
Exception:
jodd.madvoc.MadvocException: Invalid result name:vtor_json (or Invalid result name:none)
at jodd.madvoc.component.ResultsManager.lookup(ResultsManager.java:181)
at jodd.madvoc.component.MadvocController.render(MadvocController.java:183)
at jodd.madvoc.ActionRequest.lambda$createExecutionArray$0(ActionRequest.java:208)
at jodd.madvoc.ActionRequest.invoke(ActionRequest.java:237)
at jodd.madvoc.component.MadvocController.invoke(MadvocController.java:154)
at jodd.madvoc.MadvocServletFilter.doFilter(MadvocServletFilter.java:108)
What is the problem?
How to solve this?

igr, Thanks for your answer.
I try your sugestion and that's works.
But, I have some additional code:
Example:
public Object save(){
if (!authorized()){
return Redirect.to(AuthAction.ALIAS_ACCESS_DENIED); //don't work
}
if (!valid){
return JsonResult.of(vtor.getViolations()); //work
}
....
return null; //work
}
Here is debug output
38675 [DEBUG] j.m.r.AbstractTemplateViewActionResult.render:79 - new target: /accessDenied:
38676 [DEBUG] j.m.r.ServletDispatcherActionResult.targetExists:99 - target check: /accessDenied.jspf
38676 [DEBUG] j.m.r.ServletDispatcherActionResult.targetExists:99 - target check: /accessDenied.jsp
38676 [DEBUG] j.m.r.AbstractTemplateViewActionResult.render:90 - target found: /accessDenied.jsp
But , never redirect to accessDenied.html.
I try with Object but it doesn't work.
Any suggest?
I found the solution:
if (!valid){
return JsonResult.of(VtorUtil.createViolationsJsonString(request, vtor.getViolations())).value();
}
It's very easy like you said, igr ;-)

Let me explain:)
With Jodd v4 we don't have anymore the VTOR_JSON type of results - those that return strings. (The string constant is still there, but it is not used). We had to remove this way of returning results as it is not scalable - simply can not add easily different result types.
How to fix it?
We are back to basic :) VTOR_JSON was returning the JSON with the error. So now you have few options (as you can see here):
return an object annotated with #RenderWith annotation;
put a #RenderWith annotation on the action;
return a PathResult helper object;
specify the result in the action configuration.
In a short, you should do this by yourself - but don't worry its super easy. For example, you can return:
if (!valid) {
return JsonResult.of(violations());
}
return null;
If null is not working, try returning new NoneActionResult() (sorry, we will add more convenient way).
Checkout the results package: results.
Sorry for this transition, it is really for good purpose. We will add more helpers like JsonResult. And of course, if you need any support, let us know.

Related

ExceptionConsumeContext filter in MassTransit

in this post I found it that how to send my Serilog enrichment properties to consumers. when I logging my informations, then every thing is correct. but when throws an exception in the consumers, I don't see my Serilog properties in the log file. as you can see:
ERR - - -
2022-01-03 12:25:40.346 - myApp - MassTransit.ReceiveTransport - ERR - - - => R-FAULT "rabbitmq://localhost/MyConsumer" "c8100000-568d-0050-407a-08d9ce96c99c"
well, I guess the exception logging occurred in another context. I guess the exception logging occurred in the ExceptionConsumeContext class.
well I Implemented a filter for ExceptionConsumeContext:
public class IntegrationEventExceptionConsumeFilter<T> : IFilter<ExceptionConsumeContext <T>> where T : class {
public IntegrationEventPublishFilter()
{
}
public Task Send(ExceptionConsumeContext <T> context, IPipe<ExceptionConsumeContext <T>> next)
{
return next.Send(context);
}
public void Probe(ProbeContext context)
{
}}
now I need to add this filter to MassTransit configuration:
cfg.UseConsumeFilter(typeof(IntegrationEventExceptionConsumeFilter<>), context);
well, I got the exception:
The scoped filter must implement GreenPipes.IFilter<MassTransit.ConsumeContext<MyEvent>> (Parameter 'scopedType')
well, I couldn't find any conumer filter registeration for type of ExceptionConsumeContext.
and Since the I saw ExceptionConsumeContext inherited from ConsumeContext, I guess can be register this filter as a ConsumeFilter!. but don't work this way.
public interface ExceptionConsumeContext : ConsumeContext, PipeContext, MessageContext, IPublishEndpoint, IPublishObserverConnector, ISendEndpointProvider, ISendObserverConnector{}
now, I don't know what I do!
There is no scoped filter registration for ExceptionConsumeContext. You would need to add your additional filter to the receive pipeline.
cfg.ConfigureError(x =>
{
x.UseFilter(new GenerateFaultFilter());
x.UseFilter(new IntegrationEventExceptionConsumeFilter());
x.UseFilter(new ErrorTransportFilter());
});
Note that there is no message-specific generic version of ExceptionConsumeContext.

how to properly implement attributeHasFieldErrors ( without 'AssertionError: No BindingResult for attribute: abc' error )

I am trying to use .andExpect(model().attributeHasFieldErrors in my unit test.
According to this page java.lang.AssertionError: No BindingResult for attribute: abc is caused because the view returned by tested controller is a redirect: "redirect:/xyz/add".
But at the same time, most of #PostMapping(/...) use redirect. Does it mean that in this kind of cases there is no way of knowing if attributeHasFieldErrors ?
It seems to be possible - in this sample it seems to be working - BUT I am confused on this:
There testProcessUpdateOwnerFormHasErrors test-method (second method from bottom in above link) performs POST [ i.e. mockMvc.perform(post(... ] , and expects view name that is returned by GET method in Controller class.
That is, #GetMapping("/owners/{ownerId}/edit") returns "owners/createOrUpdateOwnerForm" and #PostMapping("/owners/{ownerId}/edit") returns "redirect:/owners/{ownerId}" in Controller. And above test performing POST expects "owners/createOrUpdateOwnerForm". Should it not expect "redirect:/owners/{ownerId}" ?
I am confused.
Can someone explain proper way of implementing attributeHasFieldErrors?
Typically, you use redirect when there are no errors, to avoid multiple POSTS. When
there is an error, the normal way to proceed would be to redisplay the same view with the error messages.
Something like :
#PostMapping("/")
public String processForm(#Valid UserForm userForm, BindingResult bindingResult, Model model) {
if ( ! bindingResult.hasErrors()) {
Long id = service.saveUser(userForm.getUser());
return "redirect:/user/"+id;
} else {
return "calcForm";
}
}

Yii2 beginner. Display REST exception handling

In my controller, I extend the Controller class instead of ActiveController
I have a simple actionIndex() method:
public function actionIndex(){
return json_encode(["text" => "some text"]);
}
When I access the certain route in browser, in the debugger, I see that this function is executing (the breakpoint stops inside the function), but I get 500 status code (Internal server error). How can I find the cause of the error? I have implemented the actionError() method, but it is not executing.
public function actionError() {
$exception = Yii::$app->errorHandler->exception;
if ($exception !== null) {
return $this->render('error', ['exception' => $exception]);
}
}
If I put the logic of the actionError() method in the actionIndex(), the $exception variable is null
The only output I get is:
{
name: "PHP Warning",
message: "Expected array for frame 0",
code: 2,
type: "yii\base\ErrorException",
file: "Unknown",
line: 0,
stack-trace: []
}
but it's warning, not error. May this cause the status code 500?
How can I get the error? Thanks!
According to this thread https://github.com/yiisoft/yii2/issues/11120 this is related to Xdebug for Yii 2 < 2.0.9.
When handling an exception, XDebug modifies the exception and Yii2 was not able to handle it correctly.
So several possible solutions here
The best idea is to update Yii2 to a version >= 2.0.9
Also you sould correct the source of the exception (the warning). It is never a good idea to have warnings. It can hide some more issues.
And as a workaround, you can disable XDebug. It is very useful during development but must be disabled in production in all cases.
Don't know about your error, but there is generally no need to return a response as json encoded. Yii checks the Accept-header of the request and adjust output accordingly. In your case I would just use:
public function actionIndex()
{
return ["text" => "some text"];
}
Possibly it might also solve your error...

assertThat() is always successful

I have a test that doesn't fail when it should:
import static org.assertj.core.api.Assertions.assertThat;
#Test
public void testTransactionResponse() {
String id= "004";
long amount= 5000001L;
TransactionResource transactionResource = buildTransactionResource(amount, "EUR");
System.out.println(transactionController.create(id, transactionResource).getStatusCode()); //the output is 403
assertThat(transactionController.create(id, transactionResource).getStatusCode().equals(200)); //is true and test doesn't fail
}
How is it possible?
assertThat returns BooleanAssert and doesn't actually assert anything.
AssertJ provides fluent API so you're expected to call assert methods after that:
assertThat(
transactionController.create(id, transactionResource).getStatusCode().equals(200)
).isTrue();
But it doesn't seem that you need AssertJ for that. JUnit's own assertTrue would suffice:
assertTrue(transactionController.create(id, transactionResource).getStatusCode().equals(200));
or even better, assertEquals:
assertEquals(200, transactionController.create(id, transactionResource).getStatusCode());
I would use:
assertThat(operation.getStatusCode()).isEqualTo(200);
As #default locale stated, it is true that assertThat(false) does not check anything, you can detect this bad usage with findbugs as explained here http://joel-costigliola.github.io/assertj/assertj-core.html#faq-incorrect-api-usage.

Camel - Content based routing based on JSON Request body

I have a camel REST endpoint which receives a request of the form:-
{"method" : "getHello"}
Based on the value in the method field in the request body I want to route the request to different routes. So I tried something like this below:-
from("jetty:http://localhost:8888/hello").unmarshal().json(JsonLibrary.Jackson, RouteRequest.class)
.choice()
.when(method(DynamicRouter.class, "route").isEqualTo("getHello")).to("stream:out")
.otherwise()
.log("Processing Failed");
Dynamic Router class is like below:-
public class DynamicRouter {
public String route(RouteRequest req) {
switch (req.getMethod()) {
case "getHello":
return "xxxx";
}
return null;
}
}
Even though I am returning xxxx from route() but the below Predicate is always evaluating to true and it is never going to .otherwise
isEqualTo("getHello")).to("stream:out")
Can someone let me know what I am doing wrong? Also is there some better way of what I am trying to achieve?
I am on camel 2.16.3
This is working as expected. My log4j.properties was not properly configured on the classpath. So the log was not showing up.