Some quick & dirty testing shows that doing a transparent read & reset
on the InputStream before wrapping it in a GWTObjectInputStream (using
iterator semantics) does actually let you access the parameters in
series.

I see your point about the API and the annotations. I'm mildly
annotation-phobic so have preferred the XML configuration approach to
date along these lines:

<resource name="com.myservice.cxf.gwt.server.JaxRsGwtServiceImpl" path="/">
    <operation name="processGwt" verb="POST" path="/processGwt"
        consumes="text/x-gwt-rpc;charset=utf-8"
produces="text/x-gwt-rpc;charset=utf-8">
        <param name="username" type="REQUEST_BODY" />
        <param name="password" type="REQUEST_BODY" />
    </operation>
</resource>

I'll have a go at overriding the REQUEST_URI mapping - any chance you
can post a link to an example in the documentation? Having not looked
at the way the URI parameters are stored, does the approach you've
suggested come unstuck if the payload represents non-String,
potentially complex objects? Or is a Map involved (which solves the
problem)?

I anyone's been following this thread I have posted the code I've
knocked up (in a hurry) so far at pastebin:

GWTRequestHandler.java http://pastebin.com/f66e8e3ce
GWTIterableObjectInputStream.java http://pastebin.com/f6b97cbe8
GWTMessageBodyReader.java http://pastebin.com/fafcb133

Cheers

Mike

On 8 February 2010 16:33, Sergey Beryozkin <[email protected]> wrote:
> Hi Michael
>
> Introducing the Iterable InputStream impl should also work, sounds like a
> neat idea... but the runtime itself will unlikely use it itself, you'd need
> to check in MessageBodyReader.readFrom().
>
> As far as JAXRS is concerned, the portable approach is not to have more than
> one method parameter which is assumed to represent a request body as opposed
> to request parameters. Ex,
>
> public String greetServer(String greeting, String subject);
>
> may not be recognized as a JAXRS resource method, while
>
> public String greetServer(@PathParam("1") String greeting, String subject);
>
> or
>
> public String greetServer(@PathParam("1") String greeting, @PathParam("2")
> String subject);
>
> would be accepted. CXF JAXRS server runtime is lenient here but the client
> (proxy) code will report a failure. The server runtime will eventually
> become more restrictive too but I will introduce a property which will let
> users to continue working with method signatures like the one used in your
> case.
>
> Thus, perhaps another idea, instead of relying on a MessageBodyReader is to
> do annotate the method like this :
>
> public String greetServer(@QueryParam("1") String greeting, @QueryParam("2")
> String subject);
>
> and then in a request filter, to override a Message.REQUEST_URI, ex, given
> the sequence below and the request uri
>
> /myservice/remote/service/path
>
> you can override the Message.REQUEST_URI like this :
>
> /myservice/remote/service/path?1=hello&2=world
>
> one possible advantage of this approach is that non GWT clients will also be
> able to invoke on the same method...
>
> what do you think...I'd be interested to know which approach works for you
> best
>
> cheers, Sergey
>
> Hi Sergey,
>
> I've mocked up something which produces a similar output to the
> payload referred to in the linked page (see older post). The HTTP
> request, Java service interface and the relevant parts of the web.xml
> appear below:
>
> POST /myservice/remote/service/path HTTP/1.1
>
> Host: 127.0.0.1:8888
>
> User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.4)
> Gecko/20091016 Firefox/3.5.4
>
> Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
>
> Accept-Language: en-us,en;q=0.5
>
> Accept-Encoding: gzip,deflate
>
> Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
>
> Keep-Alive: 300
>
> Connection: keep-alive
>
> X-GWT-Permutation: HostedMode
>
> X-GWT-Module-Base: http://127.0.0.1:8888/myservice/
>
> Content-Type: text/x-gwt-rpc; charset=utf-8
>
> Referer: http://127.0.0.1:8888/myservice/hosted.html?myservice
>
> Content-Length: 189
>
> Pragma: no-cache
>
> Cache-Control: no-cache
>
>
>
> 5|0|7|http://127.0.0.1:8888/myservice/|0EBF8645C6C142BAE05961AFDE515F13|com.myservice.gwttest.client.GreetingService|greetServer|java.lang.String/2004016611|hello|world|1|2|3|4|2|5|5|6|7|
>
> ----------------------8<-----------------------
>
> package com.myservice.gwttest.client;
>
>
> public interface GreetingService extends RemoteService {
>
> public String greetServer(String greeting, String subject);
>
> }
>
> ----------------------8<-----------------------
>
> <web-app>
>
> <servlet>
> <servlet-name>greetServlet</servlet-name>
> <servlet-class>com.myservice.gwttest.server.GreetingServiceImpl</servlet-class>
> </servlet>
> <servlet-mapping>
> <servlet-name>greetServlet</servlet-name>
> <url-pattern>/remote/service/path</url-pattern>
> </servlet-mapping>
>
> </web-app>
>
> ----------------------8<-----------------------
>
> I'm sorry but I haven't really had time to think about your proposed
> solutions. Just extemporizing briefly, what do you think of wrapping
> the InputStream of the message (as per your suggestion) in some sort
> of parameter-aware, Iterable InputStream? The parsing would be done at
> construction time after which it could reset itself for reading by
> other components. The additional methods it could provide may then be:
>
> boolean hasNextParameter();
> Object nextParameter();
>
> You could avoid having to track the index or use a thread-local Map that
> way.
>
> Cheers
>
> Mike
>
>
>
> On 5 February 2010 17:08, Sergey Beryozkin <[email protected]>
> wrote:
>>
>> Hi
>>
>> Sorry, was about to reply earlier on....
>>
>> That is a useful link indeed. Can you please let me know how does the the
>> method signature look like ?
>> I'd like to understand how a GWT RPC sequence is supposed to mapped to a
>> real method....Then we can see what is the best option is...
>>
>> Perhaps one option is to replace an incoming InputStream with the
>> ByteArrayInputStream on the incoming message from a custom CXF JAXRS
>> filter,
>> given that the sequences seem to be quite small :
>>
>> ByteArrayInputStream bos =
>> IOUtils.loadIntoBais(message.getContent(InputStream.class))
>> message.setContent(bos);
>>
>> Next build some sort of the map by passing this stream and set it as a
>> message property, say message.put("gwt.map", map);
>>
>> this all can be done in a filter.
>>
>> Next your message reader can have a CXF @MessageContext injected and you
>> can
>> get the map out of it.
>> Finally, in readFrom(), you can try to retrieve the value, perhaps using
>> some of the readFrom parameters ?
>>
>> If needed you can also have a thread local map which will be used to
>> increment the parameters index ?
>>
>> If you could post the sample method signature then it would help
>>
>> cheers, Sergey
>>
>>
>> Michael Guyver-3 wrote:
>>>
>>> Hi everyone,
>>>
>>> I've been having a closer look at how to implement a MessageBodyReader
>>> for the GWT RPC protocol, and while I'm aware of a JSON-related
>>> project (http://hiramchirino.com/blog/tag/json/), it's not a solution
>>> for GWT-RPC.
>>>
>>> I'm a relative GWT noob but I think you gain much greater type-safety
>>> from using the GWT-RPC mechanism over JSON as your application
>>> receives the strongly-typed response object from your remote service,
>>> possibly replete with methods to afford encapsulation, rather than
>>> just some opaque data-only JavaScriptObject. Perhaps someone can set
>>> me straight here?
>>>
>>> The problem so far as implementing a MessageBodyReader is, as I see
>>> it, that the GWT RPC protocol describes its payload types and values
>>> in a non-sequential way. This is summarised in a very helpful article
>>> here (search for the string "This is where the Payload gets a little
>>> more interesting" to get to the payload section):
>>>
>>> http://www.gdssecurity.com/l/b/2009/10/08/gwt-rpc-in-a-nutshell/
>>>
>>> I anticipate that the initial part of the payload can be disregarded
>>> as it contains routing information for the RemoteServiceServlet,
>>> contrary to the routing for JAX-RS where it is derived from the path
>>> itself - /path/to/my/service. The data-portion of the payload is the
>>> bit that's important, but I don't see that it is amenable to
>>> sequential processing as per the normal operation of the JAXRS call
>>> stack:
>>>
>>> JAXRSInInterceptor.processRequest(Message): 78
>>> JAXRSUtils.processParameters(OperationResourceInfo,MultivaluedMap<String,
>>> String>,Message): 502
>>>
>>> JAXRSUtils.processParameter(Class<?>,Type,Annotation[],Parameter,MultivaluedMap<String,
>>> String>,Message,OperationResourceInfo): 538
>>>
>>> JAXRSUtils.readFromMessageBody(Class<T>,Type,Annotation[],InputStream,MediaType,List<MediaType>,Message):
>>> 933
>>>
>>> MessageBodyReader.readFrom(Class,Type,Annotation[],MediaType,MultivaluedMap<String,
>>> String>,InputStream)
>>>
>>> It's even unfortunate that a parameter index is not passed to the
>>> MessageBodyReader, so you could suffer the cost of parsing the payload
>>> on each invocation. As almost all of these methods are static there's
>>> no chance of introducing a custom processor - unless I've missed
>>> something?
>>>
>>> Is there a way of hooking into the request processing system such that
>>> you can return a parameter Object[] from the request body rather than
>>> being invoked as if the payload were a nicely sequential stream? Can
>>> anyone suggest an approach to this problem?
>>>
>>> Cheers
>>>
>>> Mike
>>>
>>> On 19 January 2010 00:09, Michael Guyver <[email protected]>
>>> wrote:
>>>>
>>>> Hi there,
>>>>
>>>> This is a borderline hypothetical question - but say I had a GWT
>>>> application
>>>> that existed within a custom static HTML/Velocity/Trimpath/Spring MVC
>>>> application and I wanted to have GWT's AJAX requests handled by the CXF
>>>> JAXRS implementation, how would I go about parsing and writing GWT-JSON
>>>> (IIRC it's worlds apart from "normal" JSON). Would you create some sort
>>>> of
>>>> MessageBodyReader and MessageBodyWriter implementation analogous to the
>>>> AbstractJAXBProvider?
>>>>
>>>> Cheers
>>>>
>>>> Mike
>>>>
>>>
>>>
>>
>> --
>> View this message in context:
>> http://old.nabble.com/GWT-service-from-CXF--tp27218968p27470896.html
>> Sent from the cxf-user mailing list archive at Nabble.com.
>>
>>
>
>

Reply via email to