Hi,
On 23/04/15 09:20, Francesco Chicchiriccò wrote:
On 22/04/2015 17:28, Sergey Beryozkin wrote:
Hi
I've done some basic local test and I expect it to work, can you give
me a bit more information:
- request URI example, does it end with something
like "/users;realm=a" or "/users/;realm=a"
Note an extra slash in the 2nd option - should not make a difference
but I'd like to know exactly the request URI structure
(the fact it may contain query parameters is not important)
I think you still have UserService selected - if you enable a TRACE
logging you should see it confirmed, can you please give me a favour
and confirm that ? The trace will also show what path is matched
against a given resource method's path. Can you please check ?
I have forked the Syncope repository at
https://github.com/ilgrosso/syncope
and pushed some changes there:
1. removed QueryResourceInfoComparator and changed configuration
accordingly
2. "squashed" all list() / search() methods into the version with more
arguments
with commit
https://github.com/ilgrosso/syncope/commit/b8de72cbbe9536093d22acd5f5f5e6981e5e7bea
At this point (still using @QueryParam instead of @MatrixParam for
realms) everything is still working - the only thing I don't like
particularly is to force client code to write something like as
userService.list(Arrays.asList("/even/two", "/odd"), null,
null, null);
e.g. those "null, null, null": isn't there any magic trick to avoid
that? (null values are naturally managed server-side).
Right, indeed at a pure Java level have the method overloading done helps.
These 'nulls' is the downside of using proxies were some of method
parameters are optional. I can think of 2 alternatives:
- do not put @QueryParam in the signature, have a "@Context UriInfo ui;"
field in the server code and use UriInfo.getQueryParameters - the
downside there is that WADL will now show these query parameters as the
method signature will be more generic.
- Use CXF WebClient or JAX-RS 2.0 Client/WebTarget - it is easy to use
and the code can also be type-safe and there's no need to add nulls for
optional parameters.
- Use JAX-RS 2.0 BeanParam bean that would have properties corresponding
to some of optional query parameters (and other optional parameters),
and have that in a list() signature. This should actually work for WADL
too...So say we have
list(@BeanParam ListQuery query)
examples:
list(new ListQuery(Arrays.asList("/even/two", "/odd")))
list(new ListQuery(Arrays.asList("/even/two", "/odd")), "a", "b")
list(new ListQuery(Arrays.asList("/even/two", "/odd")), "a", "b", "c")
assuming ListQuery has few helper constructors
Then I have also turned @QueryParam into @MatrixParam for UserService's
and GroupService's list() and search(), with commit
https://github.com/ilgrosso/syncope/commit/1d2be4938fcc7ec25d9bd388a3f5d6dff69a37de
At this point, when calling userService as shown above, the following
URL is generated:
http://localhost:9080/syncope/rest/users;realm=/even/two;realm=/odd
This explains it :-) A matrix value such as "/even/two" has slash
characters which serve as URI path component separators but they are not
percent-encoded - the server thinks you have 3 path segments in
"/users;realm=/even/two;realm=/odd" - hence no match.
I think it is a CXF client runtime bug. When a path parameter is
provided, a "/" is always kept by default, but there is an option to
control it directly when working with UriBuilder. However when a matrix
parameter is provided I guess "/" has to be encoded immediately by the
client runtime. I will still need to investigate it further as it is all
so sensitive around using "/" in paths...
But at least we have a workaround now: do
userService.list(Arrays.asList(replaceSlashInMatrix("/even/two"),
replaceSlashInMatrix("/odd")), ...);
String replaceSlashInMatrix(String matrix) {
return matrix.replaceAll("/", "%2F");
}
and
javax.xml.ws.WebServiceException: Remote exception with status code:
NOT_FOUND
is returned; FYI, this works for this URL
http://localhost:9080/syncope/rest/users;realm=/
but "/" is the @DefaultValue.
This works because effectively you get an empty 'realm' matrix value and
there's no extra path segment behind the last "/" path segment separator
- from the server point's of view.
When enabling TRACE for CXF, I read from logs:
[...]
10:08:45.885 DEBUG org.apache.cxf.jaxrs.utils.JAXRSUtils - Resource
class org.apache.syncope.core.rest.cxf.service.UserServiceImpl has been
selected, request path :
org.apache.syncope.core.rest.cxf.service.UserServiceImpl, resource class
@Path : /users;realm=/even/two;realm=/odd
[...]
10:08:45.885 DEBUG org.apache.cxf.jaxrs.utils.JAXRSUtils - Trying to
select a resource operation on the resource class
org.apache.syncope.core.rest.cxf.service.UserServiceImpl
[...]
10:08:45.896 DEBUG org.apache.cxf.jaxrs.utils.JAXRSUtils - No method
match, method name : list, request path : /even/two;realm=/odd, method
@Path : /, HTTP Method : GET, method HTTP Method : GET, ContentType :
*/*, method @Consumes : */*,, Accept : application/json,, method
@Produces : application/xml,application/json,.
[...]
10:08:45.897 WARN org.apache.cxf.jaxrs.utils.JAXRSUtils - No operation
matching request path "/syncope/rest/users;realm=/even/two;realm=/odd"
is found, Relative Path: /even/two;realm=/odd, HTTP Method: GET,
ContentType: */*, Accept: application/json,. Please enable FINE/TRACE
log level for more details.
Yes indeed, multiple path segments there due to a "/" in matrix params
being not encoded
So - thanks for the above analysis, please do the workaround for now,
and I will investigate if encoding a "/" in matrix params on the client
side should be done by default
Thanks, Sergey
Regards.
On 22/04/15 15:05, Francesco Chicchiriccò wrote:
On 22/04/2015 14:13, Francesco Chicchiriccò wrote:
On 22/04/2015 14:09, Sergey Beryozkin wrote:
Hi Francesco
Actually, you said two ClassResourceInfo candidates have been
checked ?
One is UserService, what is the other one (and what Path does it
have ?)
First time is SyncopeService Vs SyncopeService, second is
SyncopeService Vs UserService, the exception is thrown.
Now I see how this sentence
This all should work but I wonder if there's some subtle bug in CXF if
you have a default/empty Path as in UserService list...I'll need to
have
a look
is relevant and related to my sentence above, because SyncopeService is
annotated with Path("").
Regards.
On 22/04/15 12:37, Sergey Beryozkin wrote:
Hi
On 22/04/15 12:20, Francesco Chicchiriccò wrote:
On 22/04/2015 12:48, Sergey Beryozkin wrote:
Hi Francesco
I suppose the problem lies somewhere starting from
https://github.com/apache/syncope/blob/master/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/QueryResourceInfoComparator.java#L77
It is a custom implementation and I guess the rating becomes
problematic when both query and matrix parameters are used.
It may make sense, going forward, to strictly depend on a JAX-RS
only
matching logic (note Query and Matrix parameters can not affect the
selection process in a pure JAX-RS) but I agree it can be
sensitive to
migrate the code.
Well, the ongoing changes towards 2.0.0 are substantial, so I would
not
have problems in removing QueryResourceInfoComparator, if this means
improving our compliance with JAX-RS best practices.
Does this also mean that we need to remove all duplicate methods
(see
list() or search() with variable arguments)?
Yes, unless some of the methods are available on unique @Paths.
Can you please get a breakpoint at the above code ? We can chat and
see afterwards if a comparator can be tuned further?
I've already done this before deciding to (hopefully temporarily)
switch
back to @QueryParam: only the ClassResourceInfo's compare gets
invoked,
not OperationResourceInfo's; as a result, getMatchingRate() is not
invoked at all in this case.
So you are actually seeing 404... Sorry, you actually did say it. I
thought it was a case of multiple matching methods with the one
having a
Matrix parameter being one of them but not selected in the end :-)...
the request URI is something like
"/users;realm=a;realm=b"
?
This all should work but I wonder if there's some subtle bug in
CXF if
you have a default/empty Path as in UserService list...I'll need to
have
a look
Thanks, Sergey
Thanks for your support.
Regards.
On 22/04/15 11:36, Francesco Chicchiriccò wrote:
Hi,
I have recently experimented some troubles in matching REST
methods
using @MaxtrixParam.
If you take a look at [1], this works fine; when changing the
first
@QueryParam to @MatrixParam instead, CXF throws a "Not Found"
exception.
At first I thought that the problem might depend on the fact that
there
are many methods with same name, but the problem occurs even if I
leave
only the version with all parameters (e.g. the one at [1]).
FYI, we are using a custom OperationResourceInfoComparator [2].
Any idea?
TIA
Regards.
[1]
https://github.com/apache/syncope/blob/master/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java#L146
[2]
https://github.com/apache/syncope/blob/master/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/QueryResourceInfoComparator.java
--
Sergey Beryozkin
Talend Community Coders
http://coders.talend.com/
Blog: http://sberyozkin.blogspot.com