[Seaside] WAResponse and XML

Jay Hardesty jayh at panix.com
Sat Aug 6 18:24:14 UTC 2011


On Aug 6, 2011, at 8:09 PM, Philippe Marschall wrote:

> 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:?

Yes, exactly.


> 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'


Super -    yes, Bob N. mentioned that pattern in his reply as well  

(was pretty sure my line of code couldn't possibly point to the intended API)

Thanks as always
Jay


> 
>>                        | 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
> _______________________________________________
> seaside mailing list
> seaside at lists.squeakfoundation.org
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside



More information about the seaside mailing list