Hi Gabriel
I'd like to ask you for one more favor and do a bit more debugging.
here's what I did.
Service class :
@Path("/")
public class WidgetsService {
@GET
@Path("/renderwidget/id/{widgetID}/type/{widgetType}/size/{size}/locale/{locale}/{properties}")
public int getWidgetId(@PathParam("widgetID") Long widgetID,
@PathParam("widgetType") Integer widgetType,
@PathParam("size") Long containerSize,
@PathParam("locale") String locale,
@PathParam("properties") PathSegment props) {
return 1;
}
}
Client code :
@Test
public void testgetWidgetIdWithTwoMatrixParam() {
WebClient wc =
WebClient.create("http://localhost:9081/__services/bridging/widgets");
wc.accept("text/plain");
wc.path("/renderwidget/id/{widgetID}/type/{widgetType}/size/{size}/locale/{locale}/{properties}",
1, 2, 3, "en_US", "props").matrix("a", "b").matrix("c", "d");
int status = wc.get(Integer.class);
assertEquals(1, status);
}
cxfservlet : /__services/*
jaxrs:server/@address= "/bridging/widgets"
It all works nicely, request URI looks like this :
GET
/__services/bridging/widgets/renderwidget/id/1/type/2/size/3/locale/en_US/props;a=b;c=d
Would it be possible for you, whenever you get a chnace, to put 2 breakpoints,
one in
org.apache.cxf.transport.servlet.ServletController.getBaseURL();
and another one in
JAXRSInInterceptor, on the line which reads
String rawPath = HttpUtils.getPathToMatch(message, true);
and let me know at what point of time '/__services/bridging/widgets/' gets in
the way...Hopefully we can get to the botom of it :-)
thanks, Sergey
----- Original Message -----
From: "Gabriel Guardincerri" <[email protected]>
To: <[email protected]>
Sent: Monday, July 13, 2009 6:18 PM
Subject: Re: Problem with matrix params, works with one, but not with two (or
more) params
On Mon, Jul 13, 2009 at 5:54 AM, Sergey Beryozkin <[email protected]>wrote:
/__services/bridging/widgets/renderwidget2/id/1007/type/1/size/1/locale/en_US/properties;numResults=1;foo=bar
so "/__services/bridging/widgets/" is an extra bit which was not available
at the URITemplate creation time and it would explain why the match is
failing.
Nice catch!
Can you please post a sample root resource class, as well as the value of
jaxrs:server/@address.
Is it something like this :
More or less, we don't have a class path, just
public class Widgets {
@GET
@Path("/renderwidget/id/{widgetID}/type/{widgetType}/size/{size}/locale/{locale}/{properties}")
WSWidget renderWidget2(@PathParam("widgetID") Long widgetID,
@PathParam("widgetType") Integer widgetType,
@PathParam("size") Long containerSize,
@PathParam("locale") String locale,
@PathParam("properties") PathSegment props)
throws RemoteBridgeException;
}
and jaxrs:server/@adress="/bridging"
it is /bridging/widgets
and CXFServlet url pattern is "/__services/*" ?
yes that's the pattern
Or is it jaxrs:server/@adress="__services/bridging" and CXFServlet url
pattern = "/*" ?
What are absolute working/broken URIs (lets assume 'webAppName' is the name
of the web application, and localhost:8080), is it something like :
working :
http://localhost:8080/webAppName/__services/bridging/widgets/renderwidget2/id/1007/type/1/size/1/locale/en_US/properties;numResults=1
broken :
http://localhost:8080/webAppName/__services/bridging/widgets/renderwidget2/id/1007/type/1/size/1/locale/en_US/properties;numResults=1;foo=bar
We are testing without webAppName just
http://localhost:8080/__services/...
And both absolute URIs have the same beginning.
By the way is it a double underscore in '__services' ?
I just a way to be sure that we won't have conflicts with other URIs that
the server may have
thanks, Sergey
Hi Sergey,
I'm sorry again for the delay.
Debugging it I couldn't understand why it isn't working. But here is what
I
found:
With the working URL
"renderwidget2/id/1007/type/1/size/1/locale/en_US/properties;numResults=1":
1) At line 144 of URITemplate
143 Matcher m = templateRegexPattern.matcher(uri);
144 if (!m.matches()) {
145 if (uri.contains(";")) {
The value of the variables are:
uri =
/renderwidget2/id/1007/type/1/size/1/locale/en_US/properties;numResults=1
m =
java.util.regex.Matcher[pattern=/renderwidget2/id/([^/]+?)/type/([^/]+?)/size/([^/]+?)/locale/([^/]+?)/([^/]+?)(/.*)?
region=0,73
lastmatch=/renderwidget2/id/1007/type/1/size/1/locale/en_US/properties;numResults=1]
template =
/renderwidget2/id/{widgetID}/type/{widgetType}/size/{size}/locale/{locale}/{properties}
templateRegexPattern =
/renderwidget2/id/([^/]+?)/type/([^/]+?)/size/([^/]+?)/locale/([^/]+?)/([^/]+?)(/.*)?
And m.matches() returns true, so that if is skipped and the method returns
true. After that our implementation of the service is called.
With the NOT working URL
"renderwidget2/id/1007/type/1/size/1/locale/en_US/properties;numResults=1;foo=bar":
At that same line 144, the variable values are:
uri =
/__services/bridging/widgets/renderwidget2/id/1007/type/1/size/1/locale/en_US/properties;numResults=1;foo=bar
m =
java.util.regex.Matcher[pattern=/renderwidget2/id/([^/]+?)/type/([^/]+?)/size/([^/]+?)/locale/([^/]+?)/([^/]+?)(/.*)?
region=0,109 lastmatch=]
template =
/renderwidget2/id/{widgetID}/type/{widgetType}/size/{size}/locale/{locale}/{properties}
templateRegexPattern =
/renderwidget2/id/([^/]+?)/type/([^/]+?)/size/([^/]+?)/locale/([^/]+?)/([^/]+?)(/.*)?
But m.matches() returns false. So we enter in the if. We also enter in the
if of line 145 "if (uri.contains(";"))".
Then the uri is rebuilded, and at line 162:
160 uri = sb.toString();
161 m = templateRegexPattern.matcher(uri);
162 if (!m.matches()) {
163 return false;
The value of the variables are:
uri =
/__services/bridging/widgets/renderwidget2/id/1007/type/1/size/1/locale/en_US/properties;numResults=1;foo=bar
m =
java.util.regex.Matcher[pattern=/renderwidget2/id/([^/]+?)/type/([^/]+?)/size/([^/]+?)/locale/([^/]+?)/([^/]+?)(/.*)?
region=0,109 lastmatch=]
That are the same values that we had at the beginning. So again
m.matches()
returns false, so we enter to that if on line 162, and the method returns
false.
I really don't know which is the problem, since as far as I can see both
uri
should match the pattern. Also I don't know what that first if should do,
since we get the same uri.
I hope that this help, if you need any other test, please feel free to
ping
me.
Best,
Gabriel
Sergey Beryozkin-2 wrote:
I did few more tests today (with/without CXFServlet, with PathSegments)
and I still can't reproduce it so I will give up for a
moment.
But I'm still nervous you managed to hit a problem somehow - can you
please give me a favor and help to get to the bottom of it ?
It should take 30 mins max of your time, download
http://www.apache.org/dyn/closer.cgi?path=%2Fcxf%2F2.2.2%2Fapache-cxf-2.2.2-src.zip
and put a breakpoint in URITemplate.match()
A better news is that after trying to reproduce it, I added a new method
to WebClient which can make it simpler for users to deal
with template parameters, such that they can avoid dealing with
UriBuilder
directly.
So you can do
WebClient client = WebClient.create("http://widgets");
cleint.path("("/renderwidget/id/{widgetID}/type/{widgetType}/size/{size}/locale/{locale}/{properties}",
idValue, widgetTypeValue, 1, "en_US",
"properties;1=2").get(Widget.class)
cheers, Sergey
----- Original Message ----- From: "Gabriel Guardincerri" <
[email protected]>
To: <[email protected]>
Sent: Wednesday, July 01, 2009 10:35 PM
Subject: Problem with matrix params, works with one, but not with two (or
more) params
Hello,
I'm having a problem where matrix parameters are not recognized past the
first parameter. When I have one matrix parameter, the method below is
invoked and the PathSegment.getMatrixParameters() returns the single
result.
However, if I append a second matrix parameter (or more), the service
method is not invoked at all and I receive the following error message:
"No operation matching request".
Service interface:
@GET
@Path("/renderwidget/id/{widgetID}/type/{widgetType}/size/{size}/locale/{locale}/{properties}")
WSWidget renderWidget(@PathParam("widgetID") Long widgetID,
@PathParam("widgetType") Integer widgetType,
@PathParam("size") Long containerSize,
@PathParam("locale") String locale,
@PathParam("properties") PathSegment props)
throws RemoteBridgeException;
Working
URL:
/renderwidget/id/1007/type/1/size/1/locale/en_US/properties;numResults=1
Broken:
URL:
/renderwidget/id/1007/type/1/size/1/locale/en_US/properties;numResults=1;foo=bar
The reason I'm trying to use matrix parameters is that I have an
arbitrary map of name/value for a widget class. I can't try to parse
them out individually using @MatrixParam, because they vary by widget
class and are not known at the service level.
Thanks for your help.
--
View this message in context:
http://www.nabble.com/Problem-with-matrix-params%2C-works-with-one%2C-but-not-with-two-%28or-more%29-params-tp24297533p24297533.html
Sent from the cxf-user mailing list archive at Nabble.com.
--
View this message in context:
http://www.nabble.com/Problem-with-matrix-params%2C-works-with-one%2C-but-not-with-two-%28or-more%29-params-tp24297533p24413449.html
Sent from the cxf-user mailing list archive at Nabble.com.