You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@sling.apache.org by Lars Trieloff <la...@day.com> on 2008/05/23 18:05:52 UTC

Support for additional content types in SlingPostServlet

Hi,

I am planning to add support for additional content types to the  
SlingPostServlet that would allow processing Web Forms 2.0, JSON  
(allowing an effective-round-tripping from Sling.js), XML (in JCR  
document notation), ATOM (in terms of the Atom publishing protocol).  
To do this I would like to propose a small API change: extracting a  
ResponseBuilder interface from our current HtmlResponse and renaming  
HtmlResponse subsequently to HtmlResponseBuilder. This would allow us  
to create a doPost method that would start like this (I think we  
should OSGi-ify this later to make content type handling pluggable)

protected void doPost(SlingHttpServletRequest request,
             SlingHttpServletResponse response) throws IOException {

     	log.info("content-type: " + request.getContentType());
     	String responseType;
     	//try to determine the request content type and set the response  
accordingly. Ordinary
     	//web forms (multipart/form-data or application/x-www-form- 
urlencoded) are getting HTML
     	//response
     	if (request.getContentType().equals("application/x-www-form 
+xml")) {
     		responseType = "application/x-www-form+xml";
     		
     		//TODO: handle Web Forms 2.0 POST
     	} else if (request.getContentType().equals("application/json")|| 
request.getContentType().equals("text/x-json")) {
     		responseType = "application/json";
     		
     		//TODO: handle JSON POST
     	} else if (request.getContentType().equals("text/xml")) {
     		responseType = "text/xml";
     		
     		//TODO: handle XML POST
     	} else if (request.getContentType().equals("application/atom 
+xml")) {
     		responseType = "application/atom+xml";
     		
     		//TODO: handle Atom POST
     	} else {
     		responseType = "text/html";
     	}
     	
     	//check for user-specified override of response type
     	if (request.getHeader("Accept")! 
=null&&request.getHeader("Accept").length()!=0) {
     		
     		responseType = request.getHeader("Accept");
     	}
     	
     	ResponseBuilder responseBuilder;
     	if (responseType.equals("application/json")) {
     		responseBuilder = new JsonResponseBuilder();
     	} else if (responseType.equals("application/x-www-form+xml")) {
     		responseBuilder = new WebForms20ResponseBuilder();
     	} else if (responseType.equals("text/xml")) {
     		responseBuilder = new XmlResponseBuilder();
     	} else if (responseType.equals("application/atom+xml")) {
     		responseBuilder = new AppResponseBuilder();
     	} else {
     		responseBuilder = new HtmlResponseBuilder();
     	}

the general idea is not to break the current API, so that HtmlResponse  
stays the default, but that users sending a JSON request will get a  
JSON response, unless they explicitly request a different responseType  
using the Accept header.

If this sounds good to you, I would go on by writing the Web Forms 2.0  
part first and submitting a patch (on Youtube) including the proposed  
API changes.

regards,

Lars

Re: Support for additional content types in SlingPostServlet

Posted by Lars Trieloff <la...@trieloff.net>.
Hi,

I did a bit of additional research, implemented the Web Forms 2.0  
standalone as an Servlet Filter and have come to following conclusions:
- WebForms 2.0 and (XML, JSON, ATOM) need to be treated differently,  
as only Web Forms 2.0 can have Attachments, and only Web Forms 2.0 can  
have attachments
- This is why I would implement Web Forms 2.0 at  
org.apache.sling.engine.impl.parameters.ParameterSupport (patch will  
follow)
- using :import for XML, JSON, ATOM is a good idea, but we have to  
make sure it will also work if there are no parameters, only a request  
body.

the main advantage of this approach is that you can still use the Web  
Forms 2.0 parameters in your own servlets and scripts transparently.

For the output handling of the PostServlet, I am still fond of the  
idea of having multiple OutputBuilders that would allow for all kinds  
of responses, HTML+Table, HTML+JSON-in-textarea, pure JSON, pure XML,  
pure ATOM.

regards,

Lars

On May 25, 2008, at 8:04 , Felix Meschberger wrote:

> Hi,
>
> Am Freitag, den 23.05.2008, 12:05 -0400 schrieb Lars Trieloff:
>> Hi,
>>
>> I am planning to add support for additional content types to the
>> SlingPostServlet that would allow processing Web Forms 2.0, JSON
>> (allowing an effective-round-tripping from Sling.js), XML (in JCR
>> document notation), ATOM (in terms of the Atom publishing protocol).
>
> As I said in another mail, we might want to separate support for
> multiple transfer formats for operation feeding from the ":import"
> operation stipulated by the roundtripping of JSON (and XML) exports   
> --
> maybe not. Let's see below
>
>> To do this I would like to propose a small API change: extracting a
>> ResponseBuilder interface from our current HtmlResponse and renaming
>> HtmlResponse subsequently to HtmlResponseBuilder. This would allow us
>> to create a doPost method that would start like this (I think we
>> should OSGi-ify this later to make content type handling pluggable)
>>
>> protected void doPost(SlingHttpServletRequest request,
>>             SlingHttpServletResponse response) throws IOException {
>>
>>     	log.info("content-type: " + request.getContentType());
>>     	String responseType;
>>     	//try to determine the request content type and set the response
>> accordingly. Ordinary
>>     	//web forms (multipart/form-data or application/x-www-form-
>> urlencoded) are getting HTML
>>     	//response
>>     	if (request.getContentType().equals("application/x-www-form
>> +xml")) {
>>     		responseType = "application/x-www-form+xml";
>>     		
>>     		//TODO: handle Web Forms 2.0 POST
>>     	} else if (request.getContentType().equals("application/json")||
>> request.getContentType().equals("text/x-json")) {
>>     		responseType = "application/json";
>>     		
>>     		//TODO: handle JSON POST
>>     	} else if (request.getContentType().equals("text/xml")) {
>>     		responseType = "text/xml";
>>     		
>>     		//TODO: handle XML POST
>>     	} else if (request.getContentType().equals("application/atom
>> +xml")) {
>>     		responseType = "application/atom+xml";
>>     		
>>     		//TODO: handle Atom POST
>>     	} else {
>>     		responseType = "text/html";
>>     	}
>>     	
>>     	//check for user-specified override of response type
>>     	if (request.getHeader("Accept")!
>> =null&&request.getHeader("Accept").length()!=0) {
>>     		
>>     		responseType = request.getHeader("Accept");
>>     	}
>>     	
>>     	ResponseBuilder responseBuilder;
>>     	if (responseType.equals("application/json")) {
>>     		responseBuilder = new JsonResponseBuilder();
>>     	} else if (responseType.equals("application/x-www-form+xml")) {
>>     		responseBuilder = new WebForms20ResponseBuilder();
>>     	} else if (responseType.equals("text/xml")) {
>>     		responseBuilder = new XmlResponseBuilder();
>>     	} else if (responseType.equals("application/atom+xml")) {
>>     		responseBuilder = new AppResponseBuilder();
>>     	} else {
>>     		responseBuilder = new HtmlResponseBuilder();
>>     	}
>>
>> the general idea is not to break the current API, so that  
>> HtmlResponse
>> stays the default, but that users sending a JSON request will get a
>> JSON response, unless they explicitly request a different  
>> responseType
>> using the Accept header.
>>
>> If this sounds good to you, I would go on by writing the Web Forms  
>> 2.0
>> part first and submitting a patch (on Youtube) including the proposed
>> API changes.
>
>
> I think, this sounds interesting -- and I would make it configurable
> right from the start. What you are proposing is, that we properly
> separate the request data parsing and response data generation from  
> the
> actual processing.
>
> <thinking_loudly>
> We would have an input processor selected by the request content type
> and defaulting to plain old request parameter support as available
> through SlingHttpServletRequest.getParameter (e.a.). The input  
> processor
> would also provide the ResponseBuilder.
>
> Processing would be along these lines:
>
> InputProcessor ip = getInputProcessor(request);
> if (ip == null) {
>   ip = httpInputProcessor;
> }
>
> String operation = ip.getOperation();
> Operation op = getOperation(operation);
> op.execute(ip.getRequestParameters(), ip.getResponseBuilder());
> ip.getResponseBuilder.send();
>
> That is the InputProcessor would provide the input data as abstract
> parameters for the operations to uniformly access them.
>
> The operations would the operate solely on the parameters and write  
> back
> response data to the ResponseBuilder.
> </thinking_loudly>
>
> Now, looking at this mechanism, the ":import" operation being built by
> Paul Noden could in fact just be a InputProcessor for JSON (or  
> whatever
> format). In this respect :import is just a content creation/ 
> modification
> operation [which in fact it is to a certain extent].
>
> Regards
> Felix
>
>>
>> regards,
>>
>> Lars
>


Re: Support for additional content types in SlingPostServlet

Posted by Felix Meschberger <fm...@gmail.com>.
Hi,

Am Freitag, den 23.05.2008, 12:05 -0400 schrieb Lars Trieloff:
> Hi,
> 
> I am planning to add support for additional content types to the  
> SlingPostServlet that would allow processing Web Forms 2.0, JSON  
> (allowing an effective-round-tripping from Sling.js), XML (in JCR  
> document notation), ATOM (in terms of the Atom publishing protocol).  

As I said in another mail, we might want to separate support for
multiple transfer formats for operation feeding from the ":import"
operation stipulated by the roundtripping of JSON (and XML) exports  --
maybe not. Let's see below

> To do this I would like to propose a small API change: extracting a  
> ResponseBuilder interface from our current HtmlResponse and renaming  
> HtmlResponse subsequently to HtmlResponseBuilder. This would allow us  
> to create a doPost method that would start like this (I think we  
> should OSGi-ify this later to make content type handling pluggable)
> 
> protected void doPost(SlingHttpServletRequest request,
>              SlingHttpServletResponse response) throws IOException {
> 
>      	log.info("content-type: " + request.getContentType());
>      	String responseType;
>      	//try to determine the request content type and set the response  
> accordingly. Ordinary
>      	//web forms (multipart/form-data or application/x-www-form- 
> urlencoded) are getting HTML
>      	//response
>      	if (request.getContentType().equals("application/x-www-form 
> +xml")) {
>      		responseType = "application/x-www-form+xml";
>      		
>      		//TODO: handle Web Forms 2.0 POST
>      	} else if (request.getContentType().equals("application/json")|| 
> request.getContentType().equals("text/x-json")) {
>      		responseType = "application/json";
>      		
>      		//TODO: handle JSON POST
>      	} else if (request.getContentType().equals("text/xml")) {
>      		responseType = "text/xml";
>      		
>      		//TODO: handle XML POST
>      	} else if (request.getContentType().equals("application/atom 
> +xml")) {
>      		responseType = "application/atom+xml";
>      		
>      		//TODO: handle Atom POST
>      	} else {
>      		responseType = "text/html";
>      	}
>      	
>      	//check for user-specified override of response type
>      	if (request.getHeader("Accept")! 
> =null&&request.getHeader("Accept").length()!=0) {
>      		
>      		responseType = request.getHeader("Accept");
>      	}
>      	
>      	ResponseBuilder responseBuilder;
>      	if (responseType.equals("application/json")) {
>      		responseBuilder = new JsonResponseBuilder();
>      	} else if (responseType.equals("application/x-www-form+xml")) {
>      		responseBuilder = new WebForms20ResponseBuilder();
>      	} else if (responseType.equals("text/xml")) {
>      		responseBuilder = new XmlResponseBuilder();
>      	} else if (responseType.equals("application/atom+xml")) {
>      		responseBuilder = new AppResponseBuilder();
>      	} else {
>      		responseBuilder = new HtmlResponseBuilder();
>      	}
> 
> the general idea is not to break the current API, so that HtmlResponse  
> stays the default, but that users sending a JSON request will get a  
> JSON response, unless they explicitly request a different responseType  
> using the Accept header.
> 
> If this sounds good to you, I would go on by writing the Web Forms 2.0  
> part first and submitting a patch (on Youtube) including the proposed  
> API changes.


I think, this sounds interesting -- and I would make it configurable
right from the start. What you are proposing is, that we properly
separate the request data parsing and response data generation from the
actual processing.

<thinking_loudly>
We would have an input processor selected by the request content type
and defaulting to plain old request parameter support as available
through SlingHttpServletRequest.getParameter (e.a.). The input processor
would also provide the ResponseBuilder.

Processing would be along these lines:

InputProcessor ip = getInputProcessor(request);
if (ip == null) {
   ip = httpInputProcessor;
}

String operation = ip.getOperation();
Operation op = getOperation(operation);
op.execute(ip.getRequestParameters(), ip.getResponseBuilder());
ip.getResponseBuilder.send();

That is the InputProcessor would provide the input data as abstract
parameters for the operations to uniformly access them.

The operations would the operate solely on the parameters and write back
response data to the ResponseBuilder.
</thinking_loudly>

Now, looking at this mechanism, the ":import" operation being built by
Paul Noden could in fact just be a InputProcessor for JSON (or whatever
format). In this respect :import is just a content creation/modification
operation [which in fact it is to a certain extent].

Regards
Felix

> 
> regards,
> 
> Lars


Re: Support for additional content types in SlingPostServlet

Posted by Lars Trieloff <la...@day.com>.
This sounds like a good option. How do I do this?

Lars

On May 23, 2008, at 15:34 , Tobias Bocanegra wrote:

> if the code is very different from the default post servlet, i would
> create individual ones, that decline service if the headers do not
> match (felix: this is possible, right?)


Re: Support for additional content types in SlingPostServlet

Posted by Felix Meschberger <fm...@gmail.com>.
Hi,
Am Freitag, den 23.05.2008, 21:34 +0200 schrieb Tobias Bocanegra:
> On 5/23/08, Lars Trieloff <la...@day.com> wrote:
> <snip />
> >  the general idea is not to break the current API, so that HtmlResponse
> > stays the default, but that users sending a JSON request will get a JSON
> > response, unless they explicitly request a different responseType using the
> > Accept header.
> 
> does it really make sense to add all those types to the default post
> servlet? can you reuse any code of the servlet? if it's just an
> 'import' i would go for the "import" operation as paul suggested.
> 
> if the code is very different from the default post servlet, i would
> create individual ones, that decline service if the headers do not
> match (felix: this is possible, right?)

Theoretically, this would be possible, but then you would loose the
option to share functionality.

If I understand Lars correctly, he would propose to make the transfer
format of request and response data flexible while keeping the internal
processing format independent. I think this is really a good idea.

Regarding the JSON (and XML) roundtripping: I agree with Toby here, that
for roundtripping of content exports generated by the default GET
servlets (which can be seen as an export), we should go for the :import
operation Paul Noden is working on.

Regards
Felix

> 
> regards, toby


Re: Support for additional content types in SlingPostServlet

Posted by Tobias Bocanegra <to...@day.com>.
On 5/23/08, Lars Trieloff <la...@day.com> wrote:
> Hi,
>
>  I am planning to add support for additional content types to the
> SlingPostServlet that would allow processing Web Forms 2.0, JSON (allowing
> an effective-round-tripping from Sling.js), XML (in JCR document notation),
> ATOM (in terms of the Atom publishing protocol). To do this I would like to
> propose a small API change: extracting a ResponseBuilder interface from our
> current HtmlResponse and renaming HtmlResponse subsequently to
> HtmlResponseBuilder. This would allow us to create a doPost method that
> would start like this (I think we should OSGi-ify this later to make content
> type handling pluggable)
>
>  protected void doPost(SlingHttpServletRequest request,
>             SlingHttpServletResponse response) throws IOException {
>
>         log.info("content-type: " + request.getContentType());
>         String responseType;
>         //try to determine the request content type and set the response
> accordingly. Ordinary
>         //web forms (multipart/form-data or
> application/x-www-form-urlencoded) are getting HTML
>         //response
>         if
> (request.getContentType().equals("application/x-www-form+xml"))
> {
>                 responseType = "application/x-www-form+xml";
>
>                 //TODO: handle Web Forms 2.0 POST
>         } else if
> (request.getContentType().equals("application/json")||request.getContentType().equals("text/x-json"))
> {
>                 responseType = "application/json";
>
>                 //TODO: handle JSON POST
>         } else if
> (request.getContentType().equals("text/xml")) {
>                 responseType = "text/xml";
>
>                 //TODO: handle XML POST
>         } else if
> (request.getContentType().equals("application/atom+xml"))
> {
>                 responseType = "application/atom+xml";
>
>                 //TODO: handle Atom POST
>         } else {
>                 responseType = "text/html";
>         }
>
>         //check for user-specified override of response type
>         if
> (request.getHeader("Accept")!=null&&request.getHeader("Accept").length()!=0)
> {
>
>                 responseType = request.getHeader("Accept");
>         }
>
>         ResponseBuilder responseBuilder;
>         if (responseType.equals("application/json")) {
>                 responseBuilder = new JsonResponseBuilder();
>         } else if
> (responseType.equals("application/x-www-form+xml")) {
>                 responseBuilder = new WebForms20ResponseBuilder();
>         } else if (responseType.equals("text/xml")) {
>                 responseBuilder = new XmlResponseBuilder();
>         } else if
> (responseType.equals("application/atom+xml")) {
>                 responseBuilder = new AppResponseBuilder();
>         } else {
>                 responseBuilder = new HtmlResponseBuilder();
>         }
>
>  the general idea is not to break the current API, so that HtmlResponse
> stays the default, but that users sending a JSON request will get a JSON
> response, unless they explicitly request a different responseType using the
> Accept header.

does it really make sense to add all those types to the default post
servlet? can you reuse any code of the servlet? if it's just an
'import' i would go for the "import" operation as paul suggested.

if the code is very different from the default post servlet, i would
create individual ones, that decline service if the headers do not
match (felix: this is possible, right?)

regards, toby

Re: Support for additional content types in SlingPostServlet

Posted by Alexander Klimetschek <ak...@day.com>.
On Fri, May 23, 2008 at 6:05 PM, Lars Trieloff <la...@day.com> wrote:
> ... and submitting a patch (on Youtube) ....

This is so 2006. All ASF projects switched to RTF printouts of the
patch and filming them on Seesmic ;-)

Alex

-- 
Alexander Klimetschek
alexander.klimetschek@day.com