Hi, Fabio,
Thanks a lot for detailed reply.
I agree with you that the approach of defining a MessageBodyWriter to
produce html is more modularized and easier to maintain the code
compared with adding another method of producing html for all of the
xwiki resource classes.
In the previous email, I proposed something similar to JAXBProvder and
JSONProvider in restlet:
@Provider
@Produces("text/html")
class HTMLProvider extends AbstractProvider
In restlet api, AbstractProvider implements MessageBodyWriter and
MessageBodyReader. Regarding the implementation, I thought of using XML
transformation at the beginning as I did not know there is a mothod of
document.getRenderedContent(), which can produce HTML content.
When I look more into the source code, I think one possible way to
re-factor the REST API would be to enhance XWikiResource class and its
inherited classess instead of adding more code to the auto generated
JAXB classes. In the current PageResource implementation, more methods
in getRenderedContent() may be provided so that different media type can
be supported.
@GET
public PageResource getPage() {
return the getRenderedContent()
}
implement getRenderedContent() with the following methods
getRenderedContent(MediaType)
|-- getRenderContentXML
|-- getRenderContentHTML
|-- getRenderContentPDF
Bridge pattern or adapter pattern may be applied in this case, which can
separate the implementation of ContentProvider and actual XWikiResource
itself.
Thomas also pointed out the Android client project also needs to use
REST API. I prefer re-factoring it as soon as possible, if REST API
needs further re-factoring in the future anyway.
Best regards
Jun Han
On Thu, May 19, 2011 at 6:22 AM, Fabio Mancinelli
<[email protected]> wrote:
> On Thu, May 19, 2011 at 7:53 AM, Jun Han <[email protected]> wrote:
>> Hi Fabio,
>>
>> Thanks a lot for your clarification.
>>
>> Following RootResource class, I created a class called PageHTMLResource,
>> which extends XWikiResource. This class defines a new endpoint
>> (/wikis/{wikiName}/spaces/{spaceName}/pagesHTML/{pageName}) and produces
>> "text/html" content.
>>
>> This link shows the class implementation as well as curl request and
>> server response.
>> https://docs.google.com/document/d/18xfQBSBxXT31a_QY5uBQ7c5MTbt9UEvk6zXO9F32iqk/edit?hl=en&authkey=CID73rEJ
>> I hope I understand the requirement this time.
>>
>> I was also trying to use the same end point as PageResource class.
>> However, it does not work as the restlet complains "WARNING: There is
>> already a root resource class with path
>> /wikis/{wikiName}/spaces/{spaceName}/pages/{pageName}".
>> Therefore, adding a new end point seems like the way to go.
>>
>> If this is case, how many resources are needed to provide HTML content?
>> page, space, links, etc.?
>> Another question would be how to design the new end points?
>> For now, "HTML" is appended after "pages" for PageHTMLResource, which
>> gives /wikis/{wikiName}/spaces/{spaceName}/pagesHTML/{pageName}.
>> This is just a quick and dirty design.
>> Do you have better ideas?
>>
> Well, I think this solution is not good because if we want to add more
> media types (e.g., PDF, etc.) we should introduce a lot of URIs.
> Instead we can leverage the current ones and use HTTP metadata to
> produce the right output.
>
> To do this we have 2 ways:
>
> 1) Either we define a MessageBodyWriter
> (http://jsr311.java.net/nonav/javadoc/javax/ws/rs/ext/MessageBodyWriter.html)
> that @Produces("text/html") for an org.xwiki.rest.model.jaxb.Page
> object that is returned by PageResource.getPage() (i.e., the method
> that is called when GET is called on the
> /wikis/{wikiName}/spaces/{spaceName}/pages/{pageName} URI)
>
> 2) Or we enhance the PageResource class by providing a new method,
> e.g., getPageHTML that @Produces("text/html") and returns a String
> which is the actual rendered content.
>
> @Produces is the annotation that enables content negotiation. If a
> client requests a specific media type, the @Produces is used by the
> framework to locate the entity that should provide the response.
>
> The first option is better wrt modularity but it has a problem. The
> org.xwiki.rest.model.jaxb.Page doesn't have any link to the original
> XWiki Document from where it has been built, so we cannot directly
> call getRenderedContent. A quick solution would be to re-get the
> associated XWiki Document based on the information present in the
> org.xwiki.rest.model.jaxb.Page object and call getRenderedContent(). A
> bit ugly because this makes the work done in the getPage() method
> useless.
>
> The second option is straightforward, works fine and doesn't have the
> drawbacks of the first but introduces a second way for adding media
> format support. I mean this is perfectly legal in JAX-RS, it's just
> that from an architectural point of view, it is nice to have media
> type support using body writers because they are XWiki components and
> they can be injected in the system without touching existing code
> (giving more flexibility and better extensibility)
>
> So how do we proceed?
>
> To do 1) I think we should refactor a the whole system in order to
> make original XWiki entities to be accessible from JAXB objects. Since
> we are using a JAXB compiler to automatically generate these classes
> from an XSD schema, I am not sure that we can tell the compiler to
> "add an Object entity field to the generated classes" (have to check
> if). If this is possible then we're done, otherwise we might need to
> stop using the compiler and write explicitly the classes using JAXB
> annotations for serializing only the relevant fields.
>
> 2) as I said is straightforward.
>
> Since my idea was to give you some insights about how the REST API
> works, I think you can implement 2) because 1) is too much (though, if
> you feel comfortable you might try :)). This mail and your
> implementation should provide you enough background to understand how
> things work under the hood in case we'll need to patch some things
> server side while working on XEclipse.
>
> So try to go for 2). You can also have a look at the JAX-RS
> specification that details all the concepts I've mentioned before and
> that we use in the RESTful API backend.
>
> Thanks,
> Fabio
>
>
>
>
>> Best regards
>> Jun Han
>>
>> On 05/18/2011 08:23 AM, Fabio Mancinelli wrote:
>>> Hi Jun
>>>
>>> On Wed, May 18, 2011 at 5:49 AM, Jun Han<[email protected]> wrote:
>>>> Hi Fabio and Thomas,
>>>>
>>>> Thanks a lot.
>>>>
>>>> I took some time to look at how to produce XML output in Xwiki REST API.
>>>>
>>>> The job of marshaling Java object to XML is done by
>>>> restlet.ext.JAXBProvider via Restlet 1.1.10.
>>>> |@Provider
>>>> @Consumes("application/xml")
>>>> @Produces("application/xml")
>>>> class JAXBProvider extends AbstractProvider|
>>>>
>>>> Similarly, our HTMLProvider can also be devised if we want to provide a
>>>> HTML output.
>>>> |@Provider
>>>> @Produces("text/html")
>>>> class HTMLProvider extends AbstractProvider|
>>>>
>>>> As discussed earlier, another issue is about html page's format and
>>>> content.
>>>> An easy way would be to transform XML to html page via XSLT.
>>>> I also checked the current version of Restlet (2.0.7 stable). They added
>>>> Representation class in v2.0 and plan to add Representation
>>>> transformation (i.e., XML -> HTML) in version v2.2 via XSLT. see
>>>> http://wiki.restlet.org/developers/175-restlet.html
>>>> Therefore, I think XSLT approach might work for plain html.
>>>>
>>>> Take a simple page as an example,
>>>>
>>>> |<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
>>>> <page xmlns="http://www.xwiki.org">
>>>> <title>New title</title>
>>>> <content>New content</content>
>>>> </page>|
>>>>
>>>> What would be the output of html page?
>>>>
>>>> |<html>
>>>> <H1>Page<H1>
>>>> <p>namespace: http://www.xwiki.org</p>
>>>> <p>title: New title</p>
>>>> <p>content: New content</p>
>>>> </html>
>>>> |
>>>> Best regards
>>>> Jun Han
>>>>
>>> I think you misunderstood what is the purpose of this functionality...
>>> We don't want to render in HTML the XML produced by the standard REST
>>> response. We simply want to return the HTML that comes from the
>>> rendering of the page content.
>>>
>>> Basically, in its simplest form, this boils down to write a resource
>>> that returns what is generated by Document.getRenderedContent()
>>>
>>> As a side note keep in mind that we are using JAX-RS in top of
>>> Restlet, so when defining a resource you need to create a @Component
>>> Class that extends XWikiResource and also list it in the
>>> META-INF/components.txt
>>>
>>> You can have a look at
>>> https://github.com/xwiki/xwiki-platform/blob/master/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/main/java/org/xwiki/rest/resources/RootResource.java
>>> and
>>> https://github.com/xwiki/xwiki-platform/blob/master/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/main/resources/META-INF/components.txt
>>> to see what I am talking about.
>>>
>>> Thanks,
>>> Fabio
>>>
>>>
>>>
>>>> On 5/17/2011 5:29 AM, Fabio Mancinelli wrote:
>>>>> Hi Jun
>>>>>
>>>>> On Tue, May 17, 2011 at 9:16 AM, Jun Han<[email protected]> wrote:
>>>>>> Dear all,
>>>>>>
>>>>>> Regarding REST API for XWiki,
>>>>>> Source codes are in
>>>>>> xwiki-trunk/xwiki-platform/xwiki-platform-core/xwiki-platform-rest.
>>>>>> Test codes are in
>>>>>> xwiki-trunk/xwiki-enterprise/xwiki-enterprise-test/xwiki-enterprise-test-rest.
>>>>>> I hope I am looking at the correct places.
>>>>>>
>>>>> Correct.
>>>>>
>>>>>> XWiki-5820 is related to adding an endpoint for providing a rendered
>>>>>> version of the page.
>>>>>> Does REST API need to invoke xwiki-rendering library in order to render
>>>>>> the html content?
>>>>>>
>>>>> There are several getRenderedContent() methods in the Document
>>>>> class... It should be enough to call them.
>>>>>
>>>>>> The current implementation will return various resources, (e.g., pages,
>>>>>> tags, attachments), and produce XML responses in most cases.
>>>>>> In XWiki-5820, only page resources will be rendered, right?
>>>>>>
>>>>>> A straight-forward way may be to add additional end point (getPage and
>>>>>> getPageInHTML), and they will be invoked according to different Accept
>>>>>> http headers.
>>>>>>
>>>>>> It would be great that an example can be given to show the expected
>>>>>> input and output.
>>>>>>
>>>>> Actually this is a good question...
>>>>>
>>>>> The original purpose of this resource was to provide a rendered
>>>>> version of a page (typically in HTML).
>>>>> Now, provided that we render in HTML, how this HTML should be returned?
>>>>>
>>>>> If we render with the complete skin we would end up with the same
>>>>> content already available from http://.../xwiki/bin/view/Space/Page
>>>>> So the idea was to return the "bare HTML" that could be emdedded in
>>>>> other contexts.
>>>>>
>>>>> For the input we can consider Accept headers and media parameters
>>>>> (already handled by the backend)
>>>>>
>>>>> Thanks,
>>>>> Fabio
>>>>>
>>>>>> Best regards
>>>>>> Jun Han
>>>>>> _______________________________________________
>>>>>> devs mailing list
>>>>>> [email protected]
>>>>>> http://lists.xwiki.org/mailman/listinfo/devs
>>>>>>
>>>>> _______________________________________________
>>>>> devs mailing list
>>>>> [email protected]
>>>>> http://lists.xwiki.org/mailman/listinfo/devs
>>>> _______________________________________________
>>>> devs mailing list
>>>> [email protected]
>>>> http://lists.xwiki.org/mailman/listinfo/devs
>>>>
>>> _______________________________________________
>>> devs mailing list
>>> [email protected]
>>> http://lists.xwiki.org/mailman/listinfo/devs
>>
>> _______________________________________________
>> devs mailing list
>> [email protected]
>> http://lists.xwiki.org/mailman/listinfo/devs
>>
> _______________________________________________
> devs mailing list
> [email protected]
> http://lists.xwiki.org/mailman/listinfo/devs
>
--
Jun Han
Computer Science Department,
the University of Georgia
http://sites.google.com/site/junhan37/
_______________________________________________
devs mailing list
[email protected]
http://lists.xwiki.org/mailman/listinfo/devs