[Seaside] WAResponse and XML

Jay Hardesty jayh at panix.com
Sat Aug 6 17:31:26 UTC 2011


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. 

		query = 'getAvailableScores' ifTrue: [
			| 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!

Jay







More information about the seaside mailing list