-
Notifications
You must be signed in to change notification settings - Fork 121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Clarify if ReaderInterceptor must be applied without an entity parameter #659
Comments
Proposal: We change the spec in 2.2-SNAPSHOT so it is clear about the fact that an interceptor MUST NOT be called around parsing the HTTP entity, but it MUST be called around invocation of an MessageBodyReader ONLY. Would that be sufficient? |
No! 😄 See my latest response on the mailing list. |
Personally, I feel that interceptors should be called regardless of how data is bound in a JAX-RS application. The JAX-RS processing pipeline (see spec appendix) should not be affected by a developer's choice of @FormParam or @Form or any new binding annotation we define in the future. If there's an HTTP entity that needs to be processed, there must be a reader/writer and an interceptor chain. If implementations want to provide optimizations for the case when the length of the interceptor chain is 0, then that would be fine. |
Unfortunately this is not what JAX-RS 2.1 specification says currently:
This is pretty unambiguous about the fact that only entity parameters are to be created by MBRs, and that
This does not require that MBR (and ReaderInterceptor) is to be called, and IMHO it does so by good reason: MBRs are not a general means for HTTP entity parsing, these are solely providers for 3.3.2.1 entity parameter instances. Conclusion: I am -1 for invoking MBR for @FormParam. I am +1 for changing Jersey. FormParam must have the freedom of completely separate parsing technology, just any other param types have. |
Having said that: The former is only valid in the context of v2.1.2 clarifications . I am +1 for rephrasing the mentioned paragraphs in v3.0 as a separate enhancement issue, so vendors and third party extension providers have a chance to get comfortable with the new situation then (i. e. explicitly mandating invocation of MBRs and Interceptors for non-3.3.2.1 entity parameter use cases, including |
I disagree. This section states that:
It does not state that:
So in my view it would be perfectly fine for a JAX-RS implementation to use the entity provider API to create an entity if there is a request body even if the resource method doesn't declare an entity parameter.
Correct, it does not require it. But it is also not forbidden to do so. I think it all boils down to the question of how a JAX-RS implementation should handle the case I described on the mailing list. Imagine a @POST
public Response processForm( @FormParam("value") String value, Form form ) {
System.out.println( "@FormParam: " + value );
System.out.println( "Form entity: " + form.asMap().getFirst( "value" ) );
} I see three possible ways this situation could be handled.
Obliviously, I prefer option (2), because it is the most consistent one. IMO the
I don't think that there is anything in the spec today that would prevent us to define the |
You are wrong here. 3.3.2.1 explains what to do with entity parameters. It is part of a list describing the contents a resource method signature is comprised of. Please do not cut single lines out of context. MBRs had been invented solely to provide a means to build entity parameters, nothing else. As I said, we can change that, but for now, it is simply a clear misuse by seeing it out of context. Regarding not forbidding: We invented MBRs for exatly that case, so we only described it in that very particular context. It simply is not a standalone Lego brick but we can make it one. We cannot simply say we interprete it differently in just a bug fix, we really must turn that into a feature, because it has side effects: As of 3.3, it is implied that only one single MBR runs for each call. After our change, any number can run. This could trouble vendors. So +1 for 3.0, but -1 for 2.x. |
Don't get me wrong. My suggestion definitely goes beyond a simple clarification. Although I think that adding it in 2.x may work. But we can discuss the target version later after we find an agreement.
I don't get this. Why would the suggestion allow multiple MBRs to be executed? My idea was that if there are |
I agree with @chkal 100%. As as I stated before, binding to Java should not alter how pipelines are configured and executed in JAX-RS. This cannot be more clear than when a JAX-RS client uses a Form entity and the corresponding JAX-RS service binds it to @FormParam(s) (if a client uses an interceptor to, say, encrypt data then the service should use the corresponding one to decrypt!). Option (2) as described by @chkal above is the way to clarify this in the spec. Implementations could still provide optimizations as long as the behavior is not changed. |
I am neither +1 nor -1 about the next major specification implying changes to existing implementations, mandating the invocation of a MBR in case of no entity parameter being there. For me it is ok if we clearly say in 3.0 that a To sum up, I need to say that a clarification of 2.x on the idea behind and the actual existing spec text, by all respect to rules of logic and textual semantics, can only be that For 3.0, I am happy to accept a complete rewrite of chapter 3 to allow the "front-to-back" or "pipeline always" interpretation. |
What? This does not make any sense. The pipeline includes pre and post-matching filters. There is always a pipeline. AFAICT, there's a single implementation that has decided to optimize this. As as I stated, the optimization should still valid when no interceptors are available. I think this is a rather simple clarification. @andymc12 Would it be possible to suggest to the CXF team to only optimize in the absence of interceptors? That should make the behavior compatible with the other two major implementations and help MVC in the process. |
@spericas It looks like CXF uses the method signature to determine how to process in the incoming request. I'll continue to investigate an approach that allows CXF to invoke interceptors and MBRs in this scenario, but at this point it looks non-trivial. That said, I think Markus's interpretation is correct. The text in section 3.3 of the spec talks about the parameter values determining the processing pipeline, not the content of the HTTP request.
My take (and @mkarg 's, IIUC) is that if there is no entity parameter on the method, then there is no requirement to invoke the entity provider (MBR) or it's processing pipeline (including the interceptors for any MBR). If the user wants to manipulate the content of the form, they still can - but they would need to use |
Ok, great.
I don't think that is what it is saying. I interpret it as "If there's an entity parameter then an entity provider must be used". That is certainly not logically equivalent to "If there's NO entity parameter then NO entity provider must be used". In other words, you cannot go from A->B to not(A)->not(B). |
+1! That was also my interpretation. Of course the spec states that you need an MBR if there is an entity parameter. But saying that this implies that you must not invoke the MBR if there is no entity parameter doesn't make sense. However, I agree that my proposal (2) may be more than a simple clarification. However, I strongly believe that my proposal makes sense and leads a much more consistent handling of request bodies. |
Again, I have no problem with making MBR invocation mandatory in the future, but for the sake of a clarification we have to stick with the original intention of the spec authors. And that original intention simply is method invocation: See Appendix C. It clearly shows that interceptors and MBRs only are invoked for the sake of method invocation, and method invocation is clearly described in chapters cited already, and it clearly says when to call what. It is obvious that all other cases are valid but not mandatory. So what CXF does is not an "optimization", it is what the spec wants, but simply literally, while Jersey implements a case not covered by the spec. You cannot turn it the other way and say "the undocumented case is the norm, and the literal case is an optimization"! Update: The graphic in Appendix C even explicitly says that the invocation of the method is the normal case, while the invocation of the MBR and Interceptors is not! Look at the shaded background with the words (optional)! It allows Jersey to invoke the MBR, but the normal case (non-shaded) is to not invoke it! Apparently we have 2:2 votes, so I would says, the spec should stay as it is and the outcome is:
Agreed? |
@mkarg I agree with your assessment, but I don't agree that the spec is "clear" - otherwise, we wouldn't be having this conversation. :) In the mean time, for anybody who got here by googling something like "why don't my interceptors fire in CXF when they do in Jersey", the best way to ensure portability in this case is to use |
Well, of course the MBR pipeline is optional. But my understanding of the "optional" was actually that you can only invoke the MBR pipeline if there is a request body. Of course you cannot invoke it for GET requests, so the MBR pipeline is optional. But anyway, I think it is pretty obvious that the current spec wording isn't clear enough. As @andymc12 already mentioned: Otherwise this discussion wouldn't exist. 😆
As already mentioned before, I agree that fixing this issue is more than a simple clarification. So maybe we should adjust the title and tag of this issue to reflect this. But I strongly believe that JAX-RS would behave much more consistent if we enhance the spec as proposed with option (2) in my previous post. Whether this change should get into 2.2 or 3.0 can be discussed later. IMO we should first find the optimal solution and then decide whether we can justify to put it into 2.2 or if we have to wait for 3.0. Maybe I should file a new issue containing my proposal just to keep the discussion clean enough!? IMO this makes sense, because (2) actually defines how a JAX-RS implementation should obtain |
That is exactly right.
Agreed with @chkal and @andymc12 on this one.
As I stated before, I very much agree with option (2). |
+1 for separate issue with a clear proposal what the spec / Javadocs shall be changed like |
@mkarg Sure, let's create another issue. Hopefully others will get involved in the discussion and we can move this forward. |
In one of @chkal's comments, there was the issue that CXF was showing different results for an Please note that there is still the main issue addressed here as to whether MBRs/ReaderInterceptors should be invoked if there is no entity parameter. Even with this change, CXF will not invoke the MBRs/ReaderInterceptors unless the resource method has an entity parameter - it sounds like this behavior is different than Jersey and RESTEasy. |
Hi guys, I'm facing a strange behavior with both jersey and resteasy about invocation of ReaderInterceptor. I was reading at your discussion hopping I will find an answer but it's not that clear. Here is my case: consider following resource and providers registered in my JAX-RS application:
When calling the GET method of
So based on the spec and what @chkal and @spericas said above
should the MBR pipeline and |
To be honest, I'm also surprised that the interceptor is called even for GET requests. However, I don't think the spec is very strict here. So IMO this is currently no violation of the spec. |
And a second thought: I'm pretty sure that CXF won't invoke it in this case. |
Yes but there is something to clarify here. |
@NicoNes I tend to agree that it shouldn't be called in this case. Is this in general or a result of using a |
@spericas It's general, it happens for GET, PUT and POST as well |
I finally found some time to prepare a pull request for the idea I mentioned in #659 (comment). Please refer to #695 for details. If merged, the original problem described in #659 (comment) will be resolved automatically. |
I just merged #695. So I guess we can close this now. To sum up: The values of Feel free to reopen this issue if you think that this needs more clarification. |
Do we need to mention this in the spec, at least in the history appendix? |
Given the following interceptor:
And a resource like this:
In this scenario JAX-RS implementation aren't consistent regarding whether the interceptor is invoked or not. This should be clarified in the spec.
The original use case is the CSRF protection implementation in the JSR 371 RI. It uses a special ReaderInterceptor which checks for the required CSRF token in the request body. This interceptor is NOT executed in CXF. Please see mvc-spec/ozark#202 for details.
The text was updated successfully, but these errors were encountered: