cxf-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Gabriel Guardincerri <gguar...@gmail.com>
Subject Re: Problem with matrix params, works with one, but not with two (or more) params
Date Wed, 22 Jul 2009 22:38:10 GMT
Hi Sergey,
Sorry, I've just seen this post.

I did that change, that as far as I can see is just to add "@Path("/")" to
the class, but it didn't work. Anyway the problem seems to be here:

    private String getBaseURL(HttpServletRequest request) {
        String reqPrefix = request.getRequestURL().toString();
        String pathInfo = request.getPathInfo() == null ? "" :
request.getPathInfo();
        //fix for CXF-898
        if (!"/".equals(pathInfo) || reqPrefix.endsWith("/")) {
            // needs to be done given that pathInfo is decoded
            // TODO : it's unlikely servlet path will contain encoded values
so we're most
            // likely safe however we need to ensure if it happens then this
code works properly too
            reqPrefix = UrlUtils.pathDecode(reqPrefix);
            // pathInfo drops matrix parameters attached to a last path
segment
            int offset = 0;
            int index = getMatrixParameterIndex(reqPrefix,
pathInfo.length());
            if (index >= pathInfo.length()) {
                offset = reqPrefix.length() - index;
            }
            reqPrefix = reqPrefix.substring(0, reqPrefix.length() -
pathInfo.length() - offset); // MARK 1
        }
        return reqPrefix;
    }

    private int getMatrixParameterIndex(String reqPrefix, int
pathInfoLength) {
        int index = reqPrefix.lastIndexOf(';');
        int lastIndex = -1;
        while (index >= pathInfoLength) {
            lastIndex = index;
            reqPrefix = reqPrefix.substring(0, index);
            index = reqPrefix.lastIndexOf(';');
        }
        return lastIndex;
    }

At "// MARK 1" the values are

reqPrefix =
http://localhost:8080/__services/bridging/widgets/renderwidget/id/1/type/2/size/3/locale/4/properties;numResults=1;foo=bar
pathInfo
= /bridging/widgets/renderwidget/id/1/type/2/size/3/locale/4/properties;numResults=1
offset = 21
index = 101

And the result of executing that line is:

reqPrefix = http://localhost:80

So there's the problem.

On the other breakpoint

rawPath
= /__services/bridging/widgets/renderwidget/id/1/type/2/size/3/locale/4/properties;numResults=1;foo=bar

And when I entered into "HttpUtils.getPathToMatch(message, true)" I get to:

    public static String getPathToMatch(String path, String address, boolean
addSlash) {

        int ind = path.indexOf(address);
        if (ind == 0) {
            path = path.substring(ind + address.length());
        }
        if (addSlash && !path.startsWith("/")) {
            path = "/" + path;
        }

        return path;
    }

The value of "ind" is != 0, so it doesn't enter into the first if and the
result is:

path
= /__services/bridging/widgets/renderwidget/id/1/type/2/size/3/locale/4/properties;numResults=1;foo=bar

With one param the at the first breakpoint I get this

reqPrefix = http://localhost:8080/__services
pathInfo
= /bridging/widgets/renderwidget/id/1/type/2/size/3/locale/4/properties

And at the second one:

It enters into the if since "ind == 0" and

rawPath = /renderwidget/id/1/type/2/size/3/locale/4/properties;numResults=1

Hope this helps,

Best,

Gabriel

On Tue, Jul 14, 2009 at 10:27 AM, Sergey Beryozkin <sberyozk@progress.com>wrote:

> 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" <
> gguardin@gmail.com>
> To: <users@cxf.apache.org>
> 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 <sberyozk@progress.com
>> >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" <
>>>>> gguardin@gmail.com>
>>>>> To: <users@cxf.apache.org>
>>>>> 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.
>>>>
>>>>
>>>>
>>>
>>
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message