[Seaside] WAResponse and XML

Philippe Marschall philippe.marschall at gmail.com
Sat Aug 6 18:09:23 UTC 2011


2011/8/6 Jay Hardesty <jayh at panix.com>:
>
> On Aug 5, 2011, at 8:01 AM, Philippe Marschall wrote:
>
>> 2011/8/4 Jay Hardesty <jayh at panix.com>:
>>>
>>> On Aug 4, 2011, at 8:04 AM, Philippe Marschall wrote:
>>>
>>>> 2011/8/4 Jay Hardesty <jayh at panix.com>:
>>>>>
>>>>> Hi - I'm having a problem returning XML as a response from within a Seaside app, after moving to 3.0.
>>>>>
>>>>> I used to return XML by:
>>>>>
>>>>>        self session returnResponse:
>>>>>                (WAResponse new
>>>>>                        contentType: 'text/xml';
>>>>>                        nextPutAll: xmlString;
>>>>>                        yourself)
>>>>>
>>>>> but t in Seaside 3.0 I get:
>>>>>        'You can no longer return a new WAResponse instance. You must instead modify the Response contained in the active RequestContext. Look for senders of #respond: and #response for examples.'
>>>>>
>>>>>
>>>>> Following the nearest examples I can find I tried:
>>>>>
>>>>>        self requestContext respond: [:response |
>>>>>                | document |
>>>>>                document := MIMEDocument
>>>>>                        contentType: 'text/xml';
>>>>>                        content: xmlString.
>>>>>                response document: document]
>>>>>
>>>>> and:
>>>>>
>>>>>        self requestContext respond: [:response |
>>>>>                response
>>>>>                        contentType: 'text/xml';
>>>>>                        nextPutAll: xmlString]
>>>>>
>>>>> but in both cases an html document arrives downstream (with XML in the body) rather than the XML itself as previously
>>>>>
>>>>> Think I'm missing something basic here... Thanks very much for any pointers,
>>>>
>>>> That should absolutely work. The sample code below works for me.
>>>> You'll probably want to test with Firefox because it renders XML
>>>> nicely.
>>>>
>>>> renderContentOn: html
>>>>       html anchor
>>>>               callback: [
>>>>                       self requestContext respond: [ :response |
>>>>                               response
>>>>                                       contentType: 'text/xml';
>>>>                                       nextPutAll: '<?xml version="1.0"
>>>> encoding="UTF-8"?><hello><world/></hello>' ] ];
>>>>               with: 'XML'
>>>>
>>>> Cheers
>>>> Philippe
>>>> _______________________________________________
>>>> seaside mailing list
>>>> seaside at lists.squeakfoundation.org
>>>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>>>
>>>
>>> Thank you Phillipe - Yes, your code works for me just as you described.
>>>
>>> I guess my problem is that I want my renderContentOn: to immediately return XML in certain circumstances without any user action.  As in this variation on your code example:
>>>
>>>        renderContentOn: html
>>>                self requestContext respond: [ :response |
>>>                        response
>>>                                contentType: 'text/xml';
>>>                                nextPutAll: '<?xml version="1.0" encoding="UTF-8"?><hello><world/></hello>' ]
>>
>> That doesn't work. Components are made to generate HTML and in this
>> case a lot of HTML (<DOCTYPE>, <head>, <body>, …) has already been
>> generated. You have two options. First you can configure your
>> components to generate XML. See Seaside-WebServices-Core and
>> Seaside-Tests-WebServices in the addons repository [1] for examples.
>> However unless you need #call: and callbacks and friends I found
>> recommend to use Seaside-REST, also from the addons repository. There
>> is a short overview on the wiki [2] and you can find some examples
>> here [3].
>>
>>
>>> If I call this from Firefox, then instead of XML (as in your example) I see
>>>        "XML Parsing Error: XML or text declaration not at start of entity[...]"
>>> and viewing the page source gives:
>>>        "<!DOCTYPE html PUBLIC [...]"
>>>
>>>
>>> Whereas my old code:
>>>
>>>        renderContentOn: html
>>>                self session returnResponse:
>>>                        (WAResponse new
>>>                                contentType: 'text/xml';
>>>                                nextPutAll: <?xml version="1.0" encoding="UTF-8"?><hello><world/></hello>' ;
>>>                                yourself)
>>>
>>> returned and displayed XML just as your example, but without any user action
>>>
>>> So what I'm apparently missing is whatever magic happens as a result of the anchor callback being fired in your example.  I wonder if there's any way to get that kind of callback behavior programatically(?)
>>>
>>>
>>>> What do you mean with non-Seaside client? Is it a non-browser
>>>> application, non-HTML application? I
>>>
>>>
>>> Yes, I'm using Seaside apps to serve (music score data) to
>>> - Seaside web client
>>> - Flash web client
>>> - iPhone app
>>> - code running in Second Life
>>> - Croquet environment
>>>
>>>> In those cases you can still use
>>>> Seaside. You can either directly write RequestHandlers or you can have
>>>> a look at Seaside-REST.
>>>
>>> Interesting - I'll try to find an example using WARequestHandler, though I suppose this will mean moving the functionality out of my Seaside app (WAComponent subclass)...
>>
>> Yes. You can look at WAFileHandler for a complicated examples, for
>> simple ones look at Seaside-Benchmark in the addons repository [1].
>>
>>> Thanks very much for the tips, and for your example which has helped me narrow the scope of the problem
>>>
>>
>> [1] http://www.squeaksource.com/Seaside30Addons
>> [2] http://code.google.com/p/seaside/wiki/SeasideRest
>> [3] http://www.squeaksource.com/orion
>>
>> Cheers
>> Philippe
>> _______________________________________________
>> seaside mailing list
>> seaside at lists.squeakfoundation.org
>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
>
> Among the possibilities you listed, I ended up subclassing WAXmlComponent to return XML programmatically, roughly as follows:
>
>        renderContentOn: xml
>                | query |
>                query := initialRequest fields keys first.

Where is initialRequest coming from? Do you set that in
#initialiRequest:? If so it's better to replace it with
self requestContext request

>                query = 'getAvailableScores' ifTrue: [

That's  quite brittle, something like this should be more reliable

self requestContext request includesKey: 'getAvailableScores'

>                        | anXMLDocument block |
>                        anXMLDocument := self class availableScoresAsXML.
>                        block := [:element |
>                                | tag |
>                                tag := xml tag: element name.
>                                element attributes keysAndValuesDo: [:name :value |
>                                        tag attributeAt: name put: value].
>                                        tag with: [element elements do: [:each |
>                                                block value: each]]].
>                        block value: anXMLDocument elements first].
>
>
> ...that is, building the tags for the WAXmlCanvas from an instance of XMLDocument.  This restores the functionality I had lost going to 3.0.
>
> Thank you once more for all your help!


Cheers
Philippe


More information about the seaside mailing list