Author: tolusha
Date: 2010-05-28 05:59:52 -0400 (Fri, 28 May 2010)
New Revision: 2442
Added:
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/central-authentication-service-configuration.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd-cluster-bench.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd-cluster.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/exo-ws-2-0-1.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/exo-ws-2-0.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/framework-for-cross-domain-ajax.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/groovy-scripts-as-rest-services.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/introduction-to-rest.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/javascript-webdav-library.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/kerberos-sso-on-active-directory.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/oauth.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-framework.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-migration-to-jsr311.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-service-tutorial.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/soap-service-tutorial.xml
jcr/trunk/docs/reference/en/src/main/resources/images/ajax-how-it-works.png
jcr/trunk/docs/reference/en/src/main/resources/images/ajax.gif
jcr/trunk/docs/reference/en/src/main/resources/images/cometd-bench.png
jcr/trunk/docs/reference/en/src/main/resources/images/cometd-cluster.png
jcr/trunk/docs/reference/en/src/main/resources/images/groovy-console1.png
jcr/trunk/docs/reference/en/src/main/resources/images/groovy-console2.png
jcr/trunk/docs/reference/en/src/main/resources/images/groovy-console3.png
jcr/trunk/docs/reference/en/src/main/resources/images/javascript-webdav.png
jcr/trunk/docs/reference/en/src/main/resources/images/oauth-scheme.png
jcr/trunk/docs/reference/en/src/main/resources/images/rest-build-process.png
jcr/trunk/docs/reference/en/src/main/resources/images/rest-run-process.png
jcr/trunk/docs/reference/en/src/main/resources/images/rest-scheme-detailed.png
jcr/trunk/docs/reference/en/src/main/resources/images/rest-scheme.png
Modified:
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws.xml
Log:
EXOJCR-731: move ws doc to docboof format
Added:
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/central-authentication-service-configuration.xml
===================================================================
---
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/central-authentication-service-configuration.xml
(rev 0)
+++
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/central-authentication-service-configuration.xml 2010-05-28
09:59:52 UTC (rev 2442)
@@ -0,0 +1,442 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>Central Authentication Service Configuration</title>
+
+ <section>
+ <title>Introduction</title>
+
+ <para>Central Authentication Service (CAS) is a Web Single Sign-On
+ (WebSSO), developped by JA-SIG as an open-source project. CAS, like any
+ WebSSO, is very interesting in information systems where many applications
+ share a common users repository. When you enable CAS on all the
+ application, a user would log once and only once and will be recognized
+ and authentified into all the applications.</para>
+
+ <para>CAS documentation explains how to configure in details any
+ environment, that is mainly a configuration of a Web application to
+ authenticate itself against the CAS Server instead of an internal
+ mechanism. This documentation explain how to configure eXo Platform to
+ delegate the authentication to the CAS server and let it ensure the
+ single-sign-one between all the applications of an IS.</para>
+ </section>
+
+ <section>
+ <title>CAS configuration</title>
+
+ <para>This article try to explain how to configure CAS server and client
+ for exo. For this example we will use 2 the same tomcat instance, but one
+ for it has additation CAS server.</para>
+
+ <para>This configuration is not very useful, but very good example for
+ configuration CAS.</para>
+
+ <para>Tomcat 1 deployed on windows 2003 - this is CAS server, tomcat 2 on
+ Ubuntu 7.10.</para>
+
+ <section>
+ <title>Configure CAS server</title>
+
+ <para><command>(DNS name:
test01-srv.exoua-int)</command></para>
+
+ <para>1.Certificates.</para>
+
+ <programlisting>E:/Program Files>cd java
+E:/Program Files/Java>cd jre1.5.0_11
+E:/Program Files/Java/jre1.5.0_11>cd bin
+E:/Program Files/Java/jre1.5.0_11/bin>keytool -genkey -alias tomcat -keypass
123456 -keyalg RSA
+Enter keystore password: 123456
+What is your first and last name?
+ [Unknown]: test01-srv.exoua-int
+What is the name of your organizational unit?
+ [Unknown]: .
+What is the name of your organization?
+ [Unknown]: .
+What is the name of your City or Locality?
+ [Unknown]: .
+What is the name of your State or Province?
+ [Unknown]: .
+What is the two-letter country code for this unit?
+ [Unknown]: UA
+Is CN=test01-srv.exoua-int, OU=., O=., L=., ST=., C=UA correct?
+ [no]: yes
+
+E:/Program Files/Java/jre1.5.0_11/bin>keytool -export -alias tomcat -keypass
123456 -file server.crt
+Enter keystore password: 123456
+Certificate stored in file <server.crt></programlisting>
+
+ <para>This is optional, I just want to have the same password for
+ storage %JRE_HOME%/lib/security/cacerts.</para>
+
+ <programlisting>E:/Program Files/Java/jre1.5.0_11/bin>keytool
-storepasswd -keystore ../lib/security/cacerts
+Enter keystore password: changeit
+New keystore password: 123456
+Re-enter new keystore password: 123456</programlisting>
+
+ <para>Continue with certificates.</para>
+
+ <programlisting>E:/Program Files/Java/jre1.5.0_11/bin>keytool -import
-file server.crt -keypass 123456 -keystore ../lib/security/cacerts
+Enter keystore password: 123456
+Owner: CN=test01-srv.exoua-int, OU=., O=., L=., ST=., C=UA
+Issuer: CN=test01-srv.exoua-int, OU=., O=., L=., ST=., C=UA
+Serial number: 4810c6c5
+Valid from: Fri Apr 24 20:33:36 HST 2008 until: Thu Jul 23 20:33:36 HST 2008
+Certificate fingerprints:
+MD5: CC:3B:FB:FB:AE:12:AD:FB:3E:D 5:98:CB:2E:3B:0A:AD
+SHA1: A1:16:80:68:39:C7:58:EA:2F:48:59:AA:1D:73:5F:56:78:CE:A4:CE
+Trust this certificate? [no]: yes
+Certificate was added to keystore
+
+E:/Program Files/Java/jre1.5.0_11/bin></programlisting>
+
+ <para>2. Now edit server.xml file for tomcat (we are using 6.0.13
+ everywhere).Uncomment configuration for SSL connection end edit it, it
+ must looks as this:</para>
+
+ <programlisting><Connector port="8443"
protocol="HTTP/1.1" SSLEnabled="true"
+maxThreads="150" scheme="https" secure="true"
+clientAuth="false" sslProtocol="TLS"
+keystoreFile="E:/Documents and Settings/admin/.keystore"
+keystorePass="123456"
+keyAlias="tomcat"
+truststoreFile="E:/Program Files/Java/jre1.5.0_11/lib/security/cacerts"
+truststorePass="123456" /></programlisting>
+
+ <para>3. Now configure client part of CAS, as example we will use
+ portal/private/* .Edit file /portal/WEB-INF/web.xml.</para>
+
+ <programlisting><context-param>
+ <param-name>serverName</param-name>
+
<param-value>http://test01-srv.exoua-int:8080</param-value>
+</context-param></programlisting>
+
+ <para>Configure client, in this example we will protect
+ /portal/private/* resource. Note: These filter must be add before this
+ filter "SetCurrentIdentityFilter", the same think for
+ filter-mapping.</para>
+
+ <programlisting><filter>
+ <filter-name>SingleSignOutFilter</filter-name>
+
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
+</filter>
+<filter>
+ <filter-name>AuthenticationFilter</filter-name>
+
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
+ <init-param>
+ <param-name>casServerLoginUrl</param-name>
+
<param-value>https://test01-srv.exoua-int:8443/cas/login</param-value>
+ </init-param>
+</filter>
+<filter>
+
<filter-name>Cas20ProxyReceivingTicketValidationFilter</filter-name>
+
<filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
+ <init-param>
+ <param-name>casServerUrlPrefix</param-name>
+
<param-value>https://test01-srv.exoua-int:8443/cas</param-value>
+ </init-param>
+ <init-param>
+ <param-name>redirectAfterValidation</param-name>
+ <param-value>true</param-value>
+ </init-param>
+</filter>
+<filter>
+ <filter-name>HttpServletRequestWrapperFilter</filter-name>
+
<filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
+</filter>
+<!-- eXo -->
+<filter>
+
<filter-name>BaseIdentityInitializerFilterImpl</filter-name>
+
<filter-class>org.exoplatform.services.security.cas.client.impl.BaseIdentityInitializerFilterImpl</filter-class>
+</filter>
+<!-- end exo -->
+....
+<filter-mapping>
+ <filter-name>SingleSignOutFilter</filter-name>
+ <url-pattern>/private/*</url-pattern>
+</filter-mapping>
+<filter-mapping>
+ <filter-name>AuthenticationFilter</filter-name>
+ <url-pattern>/private/*</url-pattern>
+</filter-mapping>
+<filter-mapping>
+
<filter-name>Cas20ProxyReceivingTicketValidationFilter</filter-name>
+ <url-pattern>/private/*</url-pattern>
+</filter-mapping>
+<filter-mapping>
+ <filter-name>HttpServletRequestWrapperFilter</filter-name>
+ <url-pattern>/private/*</url-pattern>
+</filter-mapping>
+<!-- exo -->
+<filter-mapping>
+
<filter-name>BaseIdentityInitializerFilterImpl</filter-name>
+ <url-pattern>/private/*</url-pattern>
+</filter-mapping>
+<!-- end exo -->
+....
+<listener>
+
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
+</listener>
+....
+<!-- exo -->
+<servlet>
+ <servlet-name>LogoutServlet</servlet-name>
+
<servlet-class>org.exoplatform.services.security.cas.client.impl.LogoutServlet</servlet-class>
+ <init-param>
+ <param-name>casServerLogoutUrl</param-name>
+
<param-value>https://test01-srv.exoua-int:8443/cas/logout</param-value>
+ </init-param>
+ <init-param>
+ <param-name>redirectToUrl</param-name>
+
<param-value>http://test01-srv.exoua-int:8080/portal/public/classic</param-value>
+ </init-param>
+</servlet>
+<!-- end exo -->
+.....
+<!-- exo -->
+<servlet-mapping>
+ <servlet-name>LogoutServlet</servlet-name>
+ <url-pattern>/logout/*</url-pattern>
+</servlet-mapping>
+<!-- end exo -->
+....</programlisting>
+
+ <para>4. Download and build code from <link
+
linkend="???">http://svn.exoplatform.org/svnroot/exoplatform...
+
+ <para>5. Download and put cas-client-core-3.1.1.jar in
+ CATALINA_HOME%/lib directory.</para>
+
+ <para>6. Download CAS server source code and build it or download
+ binary. Put cas.war in webapps directoryChange configuration in file
+ /cas/WEB-INF/deployConfigContext.xml. Comment test authenticator and add
+ new one.</para>
+
+ <programlisting><!--
+<bean
class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler"
/>
+-->
+<!-- will check username and password at remote host -->
+<bean
class="org.exoplatform.services.security.cas.server.HTTPAuthenticationHandler"
+p:authenticationURL="https://ubu.exoua-int:8443/portal/login"
/></programlisting>
+
+ <para>7. Download and build code which can do remote
+ authentication.Download and build code from <link
+
linkend="???">http://svn.exoplatform.org/svnroot/exoplatform...;,
+ andput it cas/WEB-INF/lib directory. This CAS server side handler which
+ can call remote eXo authenticatiob service via HTTP.In this case
+ validation of username/password wiil be done at ubu.exoua-int, but
+ authentication sever (CAS) will be at test01-srv.exoua-int</para>
+ </section>
+
+ <section>
+ <title>Configure other tomcat instance</title>
+
+ <para><command>Configure other tomcat instance, deploy it on Ubuntu
7.10
+ (DNS name: ubu.exoua-int).</command></para>
+
+ <para>1. Generate certificates for CAS client. The same as for previous
+ but change name to ubu.exoua-int.</para>
+
+ <para>2. Edit server.xml file for tomcat.</para>
+
+ <programlisting><Connector port="8443"
protocol="HTTP/1.1" SSLEnabled="true"
+maxThreads="150" scheme="https" secure="true"
+clientAuth="false" sslProtocol="TLS"
+keystoreFile="/home/andrew/.keystore"
+keystorePass="123456"
+keyAlias="tomcat"
+truststoreFile="/home/andrew/lib/java/jre/lib/security/cacerts"
+truststorePass="123456" /></programlisting>
+
+ <para>3. Edit file portal/WEB-INF/web.xml, add next strings in it.
+ Change context parameter.</para>
+
+ <programlisting><context-param>
+ <param-name>serverName</param-name>
+ <param-value>http://ubu.exoua-int:8080</param-value>
+</context-param></programlisting>
+
+ <para>Filters configuration must be the same as in client part on
+ tomcat1. But add one more servlet which will check
+ username/password.</para>
+
+ <programlisting><filter>
+ <filter-name>SingleSignOutFilter</filter-name>
+
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
+</filter>
+<filter>
+ <filter-name>AuthenticationFilter</filter-name>
+
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
+ <init-param>
+ <param-name>casServerLoginUrl</param-name>
+
<param-value>https://test01-srv.exoua-int:8443/cas/login</param-value>
+ </init-param>
+</filter>
+<filter>
+
<filter-name>Cas20ProxyReceivingTicketValidationFilter</filter-name>
+
<filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
+ <init-param>
+ <param-name>casServerUrlPrefix</param-name>
+
<param-value>https://test01-srv.exoua-int:8443/cas</param-value>
+ </init-param>
+ <init-param>
+ <param-name>redirectAfterValidation</param-name>
+ <param-value>true</param-value>
+ </init-param>
+</filter>
+<filter>
+ <filter-name>HttpServletRequestWrapperFilter</filter-name>
+
<filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
+</filter>
+<!-- exo -->
+<filter>
+
<filter-name>BaseIdentityInitializerFilterImpl</filter-name>
+
<filter-class>org.exoplatform.services.security.cas.client.impl.BaseIdentityInitializerFilterImpl\
+</filter-class>
+</filter>
+<!-- end exo -->
+....
+<filter-mapping>
+ <filter-name>SingleSignOutFilter</filter-name>
+ <url-pattern>/private/&#42;</url-pattern>
+</filter-mapping>
+<filter-mapping>
+ <filter-name>AuthenticationFilter</filter-name>
+ <url-pattern>/private/&#42;</url-pattern>
+</filter-mapping>
+<filter-mapping>
+
<filter-name>Cas20ProxyReceivingTicketValidationFilter</filter-name>
+ <url-pattern>/private/&#42;</url-pattern>
+</filter-mapping>
+<filter-mapping>
+ <filter-name>HttpServletRequestWrapperFilter</filter-name>
+ <url-pattern>/private/&#42;</url-pattern>
+</filter-mapping>
+<!-- exo -->
+<filter-mapping>
+
<filter-name>BaseIdentityInitializerFilterImpl</filter-name>
+ <url-pattern>/private/&#42;</url-pattern>
+</filter-mapping>
+<!-- end exo -->
+....
+<listener>
+
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
+</listener>
+....
+<!-- exo -->
+<servlet>
+
<servlet-name>BaseHTTPUsernamePasswordValidator</servlet-name>
+
<servlet-class>org.exoplatform.services.security.cas.client.impl.BaseHTTPUsernamePasswordValidatorImpl</servlet-class>
+</servlet>
+<servlet>
+ <servlet-name>LogoutServlet</servlet-name>
+
<servlet-class>org.exoplatform.services.security.cas.client.impl.LogoutServlet</servlet-class>
+ <init-param>
+ <param-name>casServerLogoutUrl</param-name>
+
<param-value>https://test01-srv.exoua-int:8443/cas/logout</param-value>
+ </init-param>
+ <init-param>
+ <param-name>redirectToUrl</param-name>
+
<param-value>http://ubu.exoua-int:8080/portal/public/classic</param-value>
+ </init-param>
+</servlet>
+<!-- end exo -->
+.....
+<!-- exo -->
+<servlet-mapping>
+
<servlet-name>BaseHTTPUsernamePasswordValidator</servlet-name>
+ <url-pattern>/login/&#42;</url-pattern>
+</servlet-mapping>
+<servlet-mapping>
+ <servlet-name>LogoutServlet</servlet-name>
+ <url-pattern>/logout/&#42;</url-pattern>
+</servlet-mapping>
+<!-- end exo -->
+<!-- not use default authentification-->
+<!--
+<security-constraint>
+ <web-resource-collection>
+ <web-resource-name>user
authentication</web-resource-name>
+ <url-pattern>/private/&#42;</url-pattern>
+ <http-method>POST</http-method>
+ <http-method>GET</http-method>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>users</role-name>
+ </auth-constraint>
+ <user-data-constraint>
+ <transport-guarantee>NONE</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint>
+
+ <login-config>
+ <auth-method>FORM</auth-method>
+ <realm-name>exo-domain</realm-name>
+ <form-login-config>
+
<form-login-page>/login/jsp/login.jsp</form-login-page>
+
<form-error-page>/login/jsp/login.jsp</form-error-page>
+ </form-login-config>
+ </login-config>
+
+ <security-role>
+ <description>a simple user role</description>
+ <role-name>users</role-name>
+ </security-role>
+
+ <security-role>
+ <description>the admin role</description>
+ <role-name>admin</role-name>
+ </security-role>
+-->
+<!-- end web.xml file-->
+....</programlisting>
+
+ <para>4. Download and build code from <link
+
linkend="???">http://svn.exoplatform.org/svnroot/exoplatform...
+
+ <para>5. Download and put cas-client-core-3.1.1.jar in
+ CATALINA_HOME%/lib directory.</para>
+
+ <para>6. Now get trusted certificate for CAS server instance. To do this
+ download and compile this file: <link
+
linkend="???">http://blogs.sun.com/andreas/resource/InstallC...
+ Then run it:</para>
+
+ <programlisting>java InstallCert test01-srv.exoua-int:8443
123456</programlisting>
+
+ <para>Change 123456 to actual password for keystore. You can see some
+ exception but finally you must see info about certificates and prompt
+ about adding it in storage. Select certificate, usually type 1 end press
+ Enter.</para>
+
+ <para>Finish!!!</para>
+ </section>
+
+ <section>
+ <title>Usage</title>
+
+ <para>Run both servers, and try open one of protected URLs, for example
+ <link
+
linkend="???">http://test01-srv.exoua-int:8080/portal/private/classic</link>.
+ Accept certificates, and in login page username/password: root/exo. You
+ must get private area in portal as root, then open other protected
+ resource on server 'ubu.exoua-int', <link
+
linkend="???">http://ubu.exoua-int:8080/portal/private/classic</link>.
+ And you must get this private area in other portal <command>without
+ login</command>. If you get it then SSO for login work as well.</para>
+
+ <para>No try logout on 'ubu.exoua-int'. To do it directly from
portal
+ one groovy script must be modified, but it is not described here.</para>
+
+ <para>After logout from 'ubu.exoua-int' you should be asked about
login
+ at 'test01-srv.exoua-int'. The SSO for logout work well also.</para>
+
+ <para>That is all!</para>
+
+ <para>If it works as described above, then configuration right and SSO
+ works.</para>
+ </section>
+ </section>
+</chapter>
Added:
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd-cluster-bench.xml
===================================================================
---
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd-cluster-bench.xml
(rev 0)
+++
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd-cluster-bench.xml 2010-05-28
09:59:52 UTC (rev 2442)
@@ -0,0 +1,186 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>Cometd Cluster Bench</title>
+
+ <section>
+ <title>How we test</title>
+
+ <para>We simple open many connection, all client subscribing to one
+ channel, we don't send any message to client, they reconnect through
+ 120000 ms. Settings for cometd servlet.</para>
+
+ <programlisting><servlet>
+ <servlet-name>cometd</servlet-name>
+
<servlet-class>org.mortbay.cometd.continuation.EXoContinuationCometdServlet</servlet-class>
+ <init-param>
+ <param-name>filters</param-name>
+ <param-value>/WEB-INF/filters.json</param-value>
+ </init-param>
+ <init-param>
+ <param-name>timeout</param-name>
+ <param-value>120000</param-value>
+ </init-param>
+ <init-param>
+ <param-name>interval</param-name>
+ <param-value>0</param-value>
+ </init-param>
+ <init-param>
+ <param-name>multiFrameInterval</param-name>
+ <param-value>1500</param-value>
+ </init-param>
+ <init-param>
+ <param-name>logLevel</param-name>
+ <param-value>0</param-value>
+ </init-param>
+ <init-param>
+ <param-name>JSONCommented</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <init-param>
+ <param-name>alwaysResumePoll</param-name>
+ <param-value>false</param-value> <!-- use true
for x-site cometd -->
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet></programlisting>
+ </section>
+
+ <section>
+ <title>Environment</title>
+
+ <para>Test running on our server for testing (Tornado)</para>
+
+ <para>Processor : Intel(R) Xeon(R) CPU E5345 @ 2.33GHz (8 cores)</para>
+
+ <para>RAM : 16 GB</para>
+
+ <para>java version "1.5.0_15" (64-bit)</para>
+ </section>
+
+ <section>
+ <title>Result</title>
+
+ <table>
+ <title></title>
+
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry align="center">Connection</entry>
+
+ <entry align="center">Heap (JProfiler), mb</entry>
+
+ <entry align="center">Virt (top),gb</entry>
+
+ <entry align="center">res (top), gb</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>1000</entry>
+
+ <entry>239</entry>
+
+ <entry>-</entry>
+
+ <entry>-</entry>
+ </row>
+
+ <row>
+ <entry>2000</entry>
+
+ <entry>318</entry>
+
+ <entry>-</entry>
+
+ <entry>-</entry>
+ </row>
+
+ <row>
+ <entry>3000</entry>
+
+ <entry>450</entry>
+
+ <entry>6</entry>
+
+ <entry>1.36</entry>
+ </row>
+
+ <row>
+ <entry>4000</entry>
+
+ <entry>610</entry>
+
+ <entry>7.2</entry>
+
+ <entry>1.6</entry>
+ </row>
+
+ <row>
+ <entry>5000</entry>
+
+ <entry>767</entry>
+
+ <entry>12.9</entry>
+
+ <entry>1.7</entry>
+ </row>
+
+ <row>
+ <entry>6000</entry>
+
+ <entry>895</entry>
+
+ <entry>14.4</entry>
+
+ <entry>1.8</entry>
+ </row>
+
+ <row>
+ <entry>7000</entry>
+
+ <entry>1004</entry>
+
+ <entry>15.5</entry>
+
+ <entry>2.2</entry>
+ </row>
+
+ <row>
+ <entry>8000</entry>
+
+ <entry>1116</entry>
+
+ <entry>17.3</entry>
+
+ <entry>2.6</entry>
+ </row>
+
+ <row>
+ <entry>9000</entry>
+
+ <entry>1295</entry>
+
+ <entry>29.6</entry>
+
+ <entry>9.8</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/cometd-bench.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>In screenshot red line show thousand of connection. Then count of
+ connection be 9000 the test fail, with exception connection
+ timeout.</para>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd-cluster.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd-cluster.xml
(rev 0)
+++
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd-cluster.xml 2010-05-28
09:59:52 UTC (rev 2442)
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>Cometd cluster</title>
+
+ <section>
+ <title>Motivation</title>
+
+ <para>When we run Stress Testing Cometd (Jetty implementation) <link
+
linkend="???">http://docs.codehaus.org/display/JETTY/Stress+...
+ we see that if we connect many clients, deliver message latency tends to
+ grow up. This situation described in article "20,000 Reasons Why Comet
+ Scales". <link
+
linkend="???">http://cometdaily.com/2008/01/07/20000-reasons...
+ So, in order to support a lot of concurrent cometd connections we need a
+ mean to horizontally scale eXo cometd support.</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/cometd-cluster.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>1- Getting base URL for cometd connection (one of the node in cometd
+ cluster)</para>
+
+ <para>2 - Getting userToken at cometd server (it need for subscribing on
+ channel)</para>
+
+ <para>3 - Sending message from Exo-server</para>
+
+ <para>LoadBalancer - component that give base URL of one of free cometd
+ server.</para>
+
+ <para>ContinuationServiceDelegate - component that send message from
+ Exo-server to client via cometd server there client is registered</para>
+
+ <para>RESTContinuationService - component that receive message from
+ ContinuationServiceDelegate and delegate it to ContinuationServer and send
+ userToken generated by ContinuationServer for user.</para>
+
+ <para>ContinuationService - component that provide cometd
+ connection.</para>
+ </section>
+
+ <section>
+ <title>How it works</title>
+
+ <para>To start work with cometd service the client should send request to
+ Exo-server with the username, receive with response URL one of cometd
+ servers (1 - on the scheme). This URL gives out LoadBalancer using the
+ information set in a configuration</para>
+
+ <programlisting><init-params>
+ <object-param>
+ <name>cometd.lb.configuration</name>
+ <description>cometd lb nodes</description>
+ <object
type="org.exoplatform.ws.frameworks.cometd.loadbalancer.LoadBalancerImpl$LoadBalancerConf">
+ <field name="nodes">
+ <collection type="java.util.ArrayList">
+ <value>
+ <object
type="org.exoplatform.ws.frameworks.cometd.loadbalancer.Node">
+ <field name="id">
+ <string>1</string>
+ </field>
+ <field name="url">
+ <string>http://localhost:8080</string>
+ </field>
+ <field name="maxConnection">
+ <int>10</int>
+ </field>
+ </object>
+ </value>
+ <value>
+ <object
type="org.exoplatform.ws.frameworks.cometd.loadbalancer.Node">
+ <field name="id">
+ <string>2</string>
+ </field>
+ <field name="url">
+ <string>http://localhost:8081</string>
+ </field>
+ <field name="maxConnection">
+ <int>15</int>
+ </field>
+ </object>
+ </value>
+ </collection>
+ </field>
+ </object>
+ </object-param>
+</init-params></programlisting>
+
+ <para>In the above configuration we described two cometd-cluseter nodes
+ of. Let's consider one of them.</para>
+
+ <para>1 - are unique the identifier of node (id)
http://localhost:8080 -
+ base URL 15 - the maximum number of the connected clients. LoadBalancer
+ chooses one of node in cometd cluster (on which connection is possible)
+ and associate with a name of the user! Now the client know on that cometd
+ server connection is possible, for this purpose it is necessary to request
+ userToken on cometd server(2). As for this need do request on other domain
+ client must use framework that allowed cross-domain-ajax. We have
+ framework that can do this task, how use this framework describe in
+ article - Framework for cross-domain AJAX. After client receive userToken
+ the client can do cometd-registration.</para>
+
+ <para>Example: the Client with a name exo1 wishes to be connected to
+ cometd to service. It is necessary to make HTTP request (GET) on
+ Exo-server URL = "http://localhost:8080/rest/cometdurl/exo1" with the
+ answer receives a base URL of cometd server, it can be as a remote server
+ or local. We will assume that we use cluster and receive some thing like
+ this "http://192.168.0.21:8080". Further it is necessary get userToken
+ already from cometd server for this purpose do request (GET) URL
+ ="http://192.168.0.22:8081/rest/gettoken/exo1", after that we do standard
+ procedure for cometd connections.</para>
+
+ <para>Then it is necessary to send the message to client
+ ContinuationServiceDelegate requests at LoadBalancer the cometd server
+ address on which the client is registered sends the message in format JSON
+ on cometd server should be RESTContinuationService which to accept the
+ message and to transfer them to ContinuationService (3)</para>
+
+ <para>Example: we will want to send the message to the client exo1. For
+ this purpose ContinuationServiceDelegate requests to LoadBalancer the
+ information on that to what server the given user is connected, we will
+ receive necessary URL
http://192.168.0.22:8081) and do HTTP request (POST)
+ on comets a server, URL =
+ "http://192.168.0.22:8080/rest/sendprivatemessage/" in a body the message
+ in format JSON is transferred, RESTContinuationService having received the
+ given message transfers it ContinuationService which already in turn
+ delivers it to the client.</para>
+
+ <programlisting><configuration>
+ <component>
+
<type>org.exoplatform.ws.frameworks.cometd.ContinuationService</type>
+ </component>
+ <component>
+ <key>org.mortbay.cometd.continuation.AbstractBayeux</key>
+
<type>org.mortbay.cometd.continuation.EXoContinuationBayeux</type>
+ </component>
+ <component>
+
<key>org.exoplatform.ws.frameworks.cometd.transport.ContinuationServiceDelegate</key>
+
<type>org.exoplatform.ws.frameworks.cometd.transport.ContinuationServiceRemoteDelegate</type>
+ </component>
+ <component>
+
<type>org.exoplatform.ws.frameworks.cometd.transport.RESTContinuationService</type>
+ </component>
+ <component>
+
<type>org.exoplatform.ws.frameworks.cometd.loadbalancer.RESTLoadBalancerService</type>
+ </component>
+ <component>
+
<key>org.exoplatform.ws.frameworks.cometd.loadbalancer.LoadBalancer</key>
+
<type>org.exoplatform.ws.frameworks.cometd.loadbalancer.LoadBalancerImpl</type>
+ <init-params>
+ <object-param>
+ <name>cometd.lb.configuration</name>
+ <description>cometd lb nodes</description>
+ <object
type="org.exoplatform.ws.frameworks.cometd.loadbalancer.LoadBalancerImpl$LoadBalancerConf">
+ <field name="nodes">
+ <collection type="java.util.ArrayList">
+ <value>
+ <object
type="org.exoplatform.ws.frameworks.cometd.loadbalancer.Node">
+ <field name="id">
+ <string>1</string>
+ </field>
+ <field name="url">
+ <string>http://localhost:8080</string>
+ </field>
+ <field name="maxConnection">
+ <int>10</int>
+ </field>
+ </object>
+ </value>
+ <value>
+ <object
type="org.exoplatform.ws.frameworks.cometd.loadbalancer.Node">
+ <field name="id">
+ <string>2</string>
+ </field>
+ <field name="url">
+ <string>http://localhost:8081</string>
+ </field>
+ <field name="maxConnection">
+ <int>15</int>
+ </field>
+ </object>
+ </value>
+ </collection>
+ </field>
+ </object>
+ </object-param>
+</init-params>
+ </component>
+</configuration></programlisting>
+
+ <para>The test: At testing running two servlet-containers Tomcat (in role
+ Exo - server'a) and Jetty (cometd server). A configuration example:</para>
+
+ <programlisting><configuration clients="12"
repeat="1" sleep-connection="500"
sleep-sending="200">
+ <container containerStart="false" port="8080"
home=""/>
+ <messages>
+ <message broadcast="false"
id="1">hello</message>
+ <message broadcast="true"
id="2">hello!!!</message>
+ </messages>
+
<cometd-url>http://localhost:8080/cometd/cometd</cometd-url>
+ <base-url>http://localhost:8080/rest/</base-url>
+ <channels>
+ <channel>/eXo/comedt/test</channel>
+ </channels>
+</configuration></programlisting>
+
+ <para>configuration describe that we create 12 cometd connections with
+ sleep-connection = "500" (мс), will be subscribe on the channel
+ "/eXo/comedt/test". Then it will be sent two message "hello"
"hello!!!"
+ the First individually to each of the clients, the second broadcast on the
+ channel. Messages delivered with an interval sleep-sending = "200".
<link
+ linkend="???">http://localhost:8080/rest/</link> - base URL of Exo
-
+ server. For start test execute a command:</para>
+
+ <programlisting>mvn clean install -f pom-test.xml -Dexo.test.skip=false
-Djetty.home = "./target/jetty"</programlisting>
+ </section>
+
+ <section>
+ <title>Bench</title>
+
+ <para>See Cometd Cluster Bench</para>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd.xml
(rev 0)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd.xml 2010-05-28
09:59:52 UTC (rev 2442)
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>Cometd</title>
+
+ <section>
+ <title>definition</title>
+
+ <para>Comet is a World Wide Web application architecture in which a web
+ server sends data to a client program (normally a web browser)
+ asynchronously without any need for the client to explicitly request it.
+ It allows creation of event-driven web applications, enabling real-time
+ interaction which would otherwise require much more work. Though the term
+ Comet was coined in 2006, the idea is several years older, and has been
+ called various names, including server push, HTTP push, HTTP streaming,
+ Pushlets, Reverse Ajax, and others.</para>
+
+ <para>Cometd on wikipedia <link
+
linkend="???">http://en.wikipedia.org/wiki/Comet_(programmin...
+
+ <para>It's an implementation of the Bayeux protocol.</para>
+ </section>
+
+ <section>
+ <title>Use</title>
+
+ <para>Cometd is deployed by default with the portal (only trunk version).
+ it's composed of a service and a webapp.</para>
+
+ <para>To get access to the cometd, you need to get a key associated with
+ the login used in the portal.</para>
+
+ <programlisting>public String getUserToken(String
eXoId)</programlisting>
+
+ <para>The connection has to be initialized, for doing so you can use the
+ cometd widget available by default in the portal.</para>
+
+ <para>to send a message from the service to a user :</para>
+
+ <programlisting>public void sendMessage(String eXoId, String channel, Object
data)</programlisting>
+ </section>
+
+ <section>
+ <title>Sample</title>
+
+ <para>you can find a sample here <link
+
linkend="???">http://svn.exoplatform.org/svnroot/exoplatform...
+
+ <para><command>To have it working :</command></para>
+
+ <itemizedlist>
+ <listitem>
+ <para>deploy a trunk version of the portal</para>
+ </listitem>
+
+ <listitem>
+ <para>go to ~/java/portal/trunk/sample/application/cometd/ and execute
+ exoproject --deploy=module</para>
+ </listitem>
+
+ <listitem>
+ <para>start the portal</para>
+ </listitem>
+
+ <listitem>
+ <para>load all the widgets and portlets</para>
+ </listitem>
+
+ <listitem>
+ <para>in a page, add the cometd widget and the portlet
+ "CometdDemo"</para>
+ </listitem>
+
+ <listitem>
+ <para>in the widget click on init</para>
+ </listitem>
+
+ <listitem>
+ <para>in the CometdDemo portlet, type a message and click on
"send", a
+ pop up with your message will appear on the top right and disappear
+ after 3 sec</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><command>What happened?</command></para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the portlet (JSR 286) sent an action with the message.</para>
+ </listitem>
+
+ <listitem>
+ <para>the action called the continuation service and sent the message
+ to the user that had sent it</para>
+ </listitem>
+
+ <listitem>
+ <para>the service sent the message to the browser</para>
+ </listitem>
+
+ <listitem>
+ <para>the cometd client side received the message, and sent it to
+ topics</para>
+ </listitem>
+
+ <listitem>
+ <para>in topic, the notification window listened to the topic
+ "/eXo/portal/notification" so the notification window
appeared.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>improvements</title>
+
+ <itemizedlist>
+ <listitem>
+ <para>replace the token system by oAuth would probably be good. not
+ sure of how it is possible.</para>
+ </listitem>
+
+ <listitem>
+ <para>There is no method yet to broadcast a message on a channel to
+ all the subscribers</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/exo-ws-2-0-1.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/exo-ws-2-0-1.xml
(rev 0)
+++
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/exo-ws-2-0-1.xml 2010-05-28
09:59:52 UTC (rev 2442)
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>eXo WS 2.0.1 Release Notes (released on 2009.04.16)</title>
+
+ <section>
+ <title>Notable Changes</title>
+
+ <para>Add supports for javax.ws.rs.core.Application. It is back compatible
+ feature.</para>
+ </section>
+
+ <section>
+ <title>API changes</title>
+
+ <para>None.</para>
+ </section>
+
+ <section>
+ <title>Dependencies changed</title>
+
+ <para>Use eXo Kernel version 2.1.1</para>
+
+ <para>Use eXo Core version 2.2.1</para>
+ </section>
+
+ <section>
+ <title>How to upgrade</title>
+
+ <para>It depends on kernel 2.1.1, core 2.2.1.</para>
+ </section>
+
+ <section>
+ <title>System Requirements</title>
+
+ <para>JVM: version 1.5.x</para>
+
+ <para>Building Tools: Maven 2.0.6 and up</para>
+ </section>
+
+ <section>
+ <title>Detailed Changelog</title>
+
+ <para>Complete list of issues fixed in eXo-Ws Version 2.0.1 . Find details
+ on JIRA <link
+
linkend="???">http://jira.exoplatform.org/secure/ReleaseNote...
+
+ <programlisting>Bug
+* [WS-125] - net.oauth wrong artifact id declared in maven dependencies
+* [WS-137] - Error of processing the request with encoded in UTF-8 content by gadgets.io
+* [WS-146] - In HierarchicalProperty class missing check QName.getPrefix() for length is
0
+* [WS-159] - Need add charSet for Reader and Writer in JSON transformers, problem come in
in Windows OS.
+* [WS-165] - Incorrect maven dependency on net.oauth:net.oauth.core:20080229
+* [WS-166] - Generated files commited in svn
+* [WS-177] - Connection problem with NTLM when trying to connect two users in same time
+* [WS-183] - Use parent pom 1.1.1 in trunk
+
+Improvement
+* [WS-138] - Add supports for javax.ws.rs.core.Application in RESTful framework
+
+New Feature
+* [WS-176] - Create filter for URL rewriting
+* [WS-182] - Create new simple Deploy Service method with JaxWsProxyFactoryBean
+
+Task
+* [WS-168] - Change URL format of groovy services to
"/{command}/{repostory}/{workspace}/{path}"
+* [WS-170] - oAuth in gadgets. Get protected resource from gadgets.
+* [WS-171] - Migrate module configuration to use kernel_1_0.xsd
+* [WS-172] - Remove unnecessary configuration from all the JARs' configuration.xml
+* [WS-184] - Release WS-2.0.1</programlisting>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/exo-ws-2-0.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/exo-ws-2-0.xml
(rev 0)
+++
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/exo-ws-2-0.xml 2010-05-28
09:59:52 UTC (rev 2442)
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>eXo WS 2.0 Release Notes (released on 2009.02.07)</title>
+
+ <section>
+ <title>Notable Changes</title>
+
+ <para>REST framework based on JSR-311 specification including:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Support of JSR-311 annotations</para>
+ </listitem>
+
+ <listitem>
+ <para>Support all media types specified in section 4.2.4 Standard
+ Entity Providers of jaxrs-1.0-final specification. Additional support
+ for 'multipart/*' and 'application/json' media
types.</para>
+ </listitem>
+
+ <listitem>
+ <para>WADL generation on receipt an OPTIONS request</para>
+ </listitem>
+
+ <listitem>
+ <para>Addition feature request and response filters. Filters is
+ similar to servlet filter and gives possibility to modify request and
+ response</para>
+ </listitem>
+
+ <listitem>
+ <para>Support for RESTful services that made in Groovy.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>OAuth implementation able to use persistent storage for
+ 'tickets'</para>
+ </section>
+
+ <section>
+ <title>API changes</title>
+
+ <para>RESTful services MUST use JAX-RS annotations..</para>
+ </section>
+
+ <section>
+ <title>Dependencies changed</title>
+
+ <para>Use eXo Kernel version 2.1</para>
+
+ <para>Use eXo Core version 2.2</para>
+
+ <para>Use maven-ant-run-plugin version 1.3 instead 1.2-SNAPSHOT</para>
+
+ <para>Use jcifs version 1.2.19 instead 1.2.17</para>
+ </section>
+
+ <section>
+ <title>How to upgrade</title>
+
+ <para>See REST Migration to jsr311</para>
+ </section>
+
+ <section>
+ <title>System Requirements</title>
+
+ <para>JVM: version 1.5.x</para>
+
+ <para>Building Tools: Maven 2.0.6 and up</para>
+ </section>
+
+ <section>
+ <title>Detailed Changelog</title>
+
+ <para>Complete list of issues fixed in eXo-Ws Version 2.0. Find details on
+ <link
+
linkend="???">http://jira.exoplatform.org/secure/ReleaseNote...
+
+ <programlisting>Bug
+* [WS-124] - Usage of SNAPSHOT in maven dependencies
+* [WS-126] - jcifs 1.2.17 is not available in public maven repo, but 1.2.19 is.
+* [WS-127] - wrong groupId for catalina dependency declaration
+
+
+Improvement
+* [WS-69] - oAuth should be able to use with annotation JSR250.
+* [WS-74] - Add possibility transfer large data (files) via
org.exoplatform.services.rest.impl.provider.MultipartFormDataEntityProvider
+* [WS-77] - Check if the class org.exoplatform.ws.rest.ejbconnector30.RestEJBConnector
can better handle the Portal Container to be compatible with multiple portal instance
+* [WS-78] - Check if the class
org.exoplatform.ws.rest.ejbconnector21.RestEJBConnectorBean can better handle the Portal
Container to be compatible with multiple portal instance
+* [WS-97] - Add support for X-HTTP-Method-Override header
+* [WS-98] - Use URI pattern for request and response filters.
+
+
+Task
+* [WS-57] - Refactor eXo REST engine to compatibility with JSR-311.
+* [WS-68] - Refactor REST EJB conector according to new implementation of REST engine
(JSR-311). See WS-57.
+* [WS-75] - Add WADL generation for request with OPTIONS HTTP method.
+* [WS-81] - Change cometd service for JSR-311
+* [WS-92] - Pre-release testing plan for QA team
+* [WS-93] - Move webdav methods to the package
org.exoplatform.services.rest.ext.method.webdav
+* [WS-94] - More description of classes' purpose in rest.ext sources
+* [WS-95] - Remove StandaloneContainerInitializedListener from JCR (one from WS has to be
used everywhere), move PortalContainerInitializedFilter from JCR to WS
+* [WS-117] - jsr-311 capability tests
+
+Sub-task
+* [WS-101] - Create service for administration groovy scripts for REST via HTTP.
+* [WS-116] - Merge code to the branches/2.0</programlisting>
+ </section>
+
+ <section>
+ <title>Download</title>
+
+ <para>Sources: <link
+
linkend="???">http://download.forge.objectweb.org/exoplatfor...
+
+ <para>Demo: <link
+
linkend="???">http://download.forge.objectweb.org/exoplatfor...
+ </section>
+</chapter>
Added:
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/framework-for-cross-domain-ajax.xml
===================================================================
---
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/framework-for-cross-domain-ajax.xml
(rev 0)
+++
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/framework-for-cross-domain-ajax.xml 2010-05-28
09:59:52 UTC (rev 2442)
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>Framework for cross-domain AJAX</title>
+
+ <para>(<link
+
linkend="???">http://svn.exoplatform.org/projects/ws/branche...
+
+ <section>
+ <title>Motivation</title>
+
+ <para>XmlHttpRequest objects are bound by the same origin security policy
+ of browsers, which prevents a page from accessing data from another
+ server. This has put a serious limitation on Ajax developers: you can use
+ XmlHttpRequests to make background calls to a server, but it has to be the
+ same server that served up the current page. For detail's you can visit
+ <link
+
linkend="???">http://www.mozilla.org/projects/security/compo...
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/ajax.gif" />
+ </imageobject>
+ </mediaobject>
+
+ <para>But actually writing client web applications that use this object
+ can be tricky given restrictions imposed by web browsers on network
+ connections across domains. So need find way how to bypass this limitation
+ of AJAX.</para>
+ </section>
+
+ <section>
+ <title>Scheme (how it works)</title>
+
+ <para>To describe our method for cross-domain AJAX solution let us
+ consider the following scheme contains of 3 components:</para>
+
+ <para>1). User agent (a browser).</para>
+
+ <para>2). ServerA contains a main page with dedicated client and server
+ IFRAMEs (see below) and an HTML client page (client.html) referenced from
+ the client IFRAME. This client page contains dedicated script to push the
+ data for request into server IFRAME.</para>
+
+ <para>3). ServerB contains remote service that want get access to and an
+ HTML server page (server.html) referenced from the server IFRAME. This
+ server page contains dedicated script to push the requested data into
+ client IFRAME.</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/ajax-how-it-works.png" />
+ </imageobject>
+ </mediaobject>
+ </section>
+
+ <section>
+ <title>A Working Sequence:</title>
+
+ <para>1) A Browser requests the Start page from the ServerA</para>
+
+ <para>2) The Start page is retrieved from the ServerA.</para>
+
+ <para>3) Create in the start page IFRAME (name it - "client iframe")
and
+ insert on it document from ServerA (client.</para>
+
+ <para>4) In "client iframe" create ne IFRAME element ("server
iframe") and
+ insert on it document from ServerB (server.html). Documents (client.html
+ and server.html) contain special script that can transfer data between
+ ifarmes.</para>
+
+ <para>5) "Client iframe" transfer information about HTTP method and
URL
+ that we want do cross-domain request to "server iframe".</para>
+
+ <para>6) "Server iframe" do simple XmlHttpRequest to the service that
we
+ need (it can do that because download from same domain) and get informaton
+ from service.</para>
+
+ <para>7) "Server iframe" transfer data to "client iframe"
and now we get
+ information that we want.</para>
+ </section>
+
+ <section>
+ <title>How to use it</title>
+
+ <para>1). Place the file client.html and xda.js on the serverA.</para>
+
+ <para>2). Place the file server.html on the serverB.</para>
+
+ <para>3). Declare xda.js in the main page.</para>
+
+ <programlisting><script type="text/javascript"
src="xda.js"></script></programlisting>
+
+ <para>4). Create JS function which performing cross domain call as in
+ following example:</para>
+
+ <programlisting><script type="text/javascript">
+ function test(){
+ var facade = xdaInit();
+ facade.clientURI =
"http://localhost/cross-domain-ajax/client/client.html";
+ facade.serverURI =
"http://localhost:8080/cross-domain-ajax/server/server.html";
+ facade.apiURI =
"http://localhost:8080/cross-domain-ajax/server/test.txt";
+ facade.method = "POST";
+ facade.load = function(result) {
+ alert(result.responseText);
+ }
+ facade.setRequestHeader("keep-alive","200");
+ xda.create(facade);
+ }
+</script></programlisting>
+
+ <para>5). Use this function (here it is bound to a button's onclick
+ event).</para>
+
+ <programlisting><button onclick='test()'>test
cross-domain</button></programlisting>
+ </section>
+</chapter>
Added:
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/groovy-scripts-as-rest-services.xml
===================================================================
---
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/groovy-scripts-as-rest-services.xml
(rev 0)
+++
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/groovy-scripts-as-rest-services.xml 2010-05-28
09:59:52 UTC (rev 2442)
@@ -0,0 +1,384 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>Groovy Scripts as REST Services</title>
+
+ <section>
+ <title>Overview</title>
+
+ <para>This article describes how to use Groovy scripts as REST services.
+ We are going to consider these operations:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Load script and save it in JCR.</para>
+ </listitem>
+
+ <listitem>
+ <para>Instantiate script</para>
+ </listitem>
+
+ <listitem>
+ <para>Deploy newly created Class as RESTful service.</para>
+ </listitem>
+
+ <listitem>
+ <para>Script Lifecycle Management.</para>
+ </listitem>
+
+ <listitem>
+ <para>And finally we will discover simple example which can get JCR
+ node UUID</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>In this article we consider RESTful service compatible with JSR-311
+ specification. Currently last feature available in version 1.11-SNAPSHOT
+ of JCR, 2.0-SNAPSHOT of WS and version 2.1.4-SNAPSHOT of core.</para>
+ </section>
+
+ <section>
+ <title>Loading script and save it in JCR</title>
+
+ <para>There are two ways to save a script in JCR. The first way is to save
+ it at server startup time by using configuration.xml and the second way is
+ to upload the script via HTTP.</para>
+
+ <para><command>Load script at startup time</command></para>
+
+ <para>This way can be used for load prepared scripts, for use this way we
+ must configure
+ org.exoplatform.services.jcr.ext.script.groovy.GroovyScript2RestLoaderPlugin.
+ This is simple configuration example.</para>
+
+ <programlisting><external-component-plugins>
+
<target-component>org.exoplatform.services.jcr.ext.script.groovy.GroovyScript2RestLoader</target-component>
+ <component-plugin>
+ <name>test</name>
+ <set-method>addPlugin</set-method>
+
<type>org.exoplatform.services.jcr.ext.script.groovy.GroovyScript2RestLoaderPlugin</type>
+ <init-params>
+ <value-param>
+ <name>repository</name>
+ <value>repository</value>
+ </value-param>
+ <value-param>
+ <name>workspace</name>
+ <value>production</value>
+ </value-param>
+ <value-param>
+ <name>node</name>
+ <value>/script/groovy</value>
+ </value-param>
+ <properties-param>
+ <name>JcrGroovyTest.groovy</name>
+ <property name="autoload" value="true" />
+ <property name="path"
value="file:/home/andrew/JcrGroovyTest.groovy" />
+ </properties-param>
+ </init-params>
+ </component-plugin>
+</external-component-plugins></programlisting>
+
+ <para>First value-param sets JCR repository, second value-param sets
+ workspace and third one sets JCR node where scripts from plugin will be
+ stored. If specified node does not exists then it will be created. List of
+ scripts is set by properties-params. Name of each properties-param will be
+ used as node name for stored script, property autoload says to deploy this
+ script at startup time, property path sets the source of script to be
+ loaded. In this example we try to load single script from local file
+ /home/andrew/JcrGroovyTest.groovy.</para>
+
+ <para><command>Load script via HTTP</command></para>
+
+ <para>This is samples of HTTP requests. In this examples we will upload
+ script from file with name test.groovy.</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X POST \
+-H 'Content-type:script/groovy' \
+--data-binary @test.groovy \
+http://localhost:8080/rest/script/groovy/add/repository/production/script/groovy/test.groovy</programlisting>
+
+ <para>This example imitate sending data with HTML form
+ ('multipart/form-data'). Parameter autoload is optional. If parameter
+ autoload=true then script will be instantiate and deploy script
+ immediately.</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X POST \
+-F "file=(a)test.groovy;name=test" \
+-F "autoload=true" \
+http://localhost:8080/rest/script/groovy/add/repository/production/script/groovy/test1.groovy</programlisting>
+ </section>
+
+ <section>
+ <title>Instantiation</title>
+
+ <para>org.exoplatform.services.script.groovy.GroovyScriptInstantiator is
+ part of project exo.core.component.script.groovy. GroovyScriptInstantiator
+ can load script from specified URL and parse stream that contains Groovy
+ source code. It has possibility inject component from Container in Groovy
+ Class constructor. Configuration example:</para>
+
+ <programlisting><component>
+
<type>org.exoplatform.services.script.groovy.GroovyScriptInstantiator</type>
+</component></programlisting>
+ </section>
+
+ <section>
+ <title>Deploy newly created Class as RESTful service</title>
+
+ <para>For deploy script automatically at server statup time its property
+ exo:autoload must be set as true.
+ org.exoplatform.services.jcr.ext.script.groovy.GroovyScript2RestLoader
+ check JCR workspaces which were specified in configuration and deploy all
+ auto-loadable scripts.</para>
+
+ <para>Example of configuration.</para>
+
+ <programlisting><component>
+
<type>org.exoplatform.services.jcr.ext.script.groovy.GroovyScript2RestLoader</type>
+ <init-params>
+ <object-param>
+ <name>observation.config</name>
+ <object
type="org.exoplatform.services.jcr.ext.script.groovy.ObservationListenerConfiguration">
+ <field name="repository">
+ <string>repository</string>
+ </field>
+ <field name="workspaces">
+ <collection type="java.util.ArrayList">
+ <value>
+ <string>production</string>
+ </value>
+ </collection>
+ </field>
+ </object>
+ </object-param>
+ </init-params>
+ </component></programlisting>
+
+ <para>In example above JCR workspace "production" will be checked
for
+ autoload scripts. At once this workspace will be listened for changes
+ script's source code (property jcr:data).</para>
+ </section>
+
+ <section>
+ <title>Script Lifecycle Management</title>
+
+ <para>If GroovyScript2RestLoader configured as was decribed in previous
+ section then all "autoload" scripts deployed. In first section we added
+ script from file /home/andrew/JcrGroovyTest.groovy to JCR node
+ /script/groovy/JcrGroovyTest.groovy, repository repository, workspace
+ production. In section "Load script via HTTP" it was refered about load
+ scripts via HTTP, there is an opportunity to manage the life cycle of
+ script.</para>
+
+ <para>Undeploy script, which is alredy deployed:</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X GET \
+http://localhost:8080/rest/script/groovy/load/repository/production/script/groovy/JcrGroovyTest.groovy?state=false</programlisting>
+
+ <para>Then deploy it again:</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X GET \
+http://localhost:8080/rest/script/groovy/load/repository/production/script/groovy/JcrGroovyTest.groovy?state=true</programlisting>
+
+ <para>or even more simple:</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X GET \
+http://localhost:8080/rest/script/groovy/load/repository/production/script/groovy/JcrGroovyTest.groovy</programlisting>
+
+ <para>Disable scripts autoloading, NOTE it does not change current
+ state:</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X GET \
+http://localhost:8080/rest/script/groovy/repository/production/script/groovy/JcrGroovyTest.groovy/autoload?state=false</programlisting>
+
+ <para>Enable it again:</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X GET \
+http://localhost:8080/rest/script/groovy/autoload/repository/production/script/groovy/JcrGroovyTest.groovy?state=true</programlisting>
+
+ <para>and again more simpe variant:</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X GET \
+http://localhost:8080/rest/script/groovy/autoload/repository/production/script/groovy/JcrGroovyTest.groovy</programlisting>
+
+ <para>Change script source code:</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X POST \
+-H 'Content-type:script/groovy' \
+--data-binary @JcrGroovyTest.groovy \
+http://localhost:8080/rest/script/groovy/update/repository/production/script/groovy/JcrGroovyTest.groovy</programlisting>
+
+ <para>This example imitate sending data with HTML form
+ ('multipart/form-data').</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X POST \
+-F "file=(a)JcrGroovyTest.groovy;name=test" \
+http://localhost:8080/rest/script/groovy/update/repository/production/script/groovy/JcrGroovyTest.groovy</programlisting>
+
+ <para>Remove script from JCR:</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X GET \
+http://localhost:8080/rest/script/groovy/delete/repository/production/script/groovy/JcrGroovyTest.groovy</programlisting>
+ </section>
+
+ <section>
+ <title>Get node UUID example</title>
+
+ <para>Now we are going to try simple example of Groovy RESTfull service.
+ There is one limitation, even if we use groovy we should use Java style
+ code and decline to use dynamic types, but of course we can use it in
+ private methods and feilds. Create file JcrGroovyTest.groovy, in this
+ example I save it in my home directory /home/andrew/JcrGroovyTest.groovy.
+ Then configure GroovyScript2RestLoaderPlugin as described in section Load
+ script at startup time.</para>
+
+ <programlisting>import javax.jcr.Node
+import javax.jcr.Session
+import javax.ws.rs.GET
+import javax.ws.rs.Path
+import javax.ws.rs.PathParam
+import org.exoplatform.services.jcr.RepositoryService
+import org.exoplatform.services.jcr.ext.app.ThreadLocalSessionProviderService
+
+@Path("groovy/test/{repository}/{workspace}")
+public class JcrGroovyTest {
+ private RepositoryService repositoryService
+ private ThreadLocalSessionProviderService sessionProviderService
+
+ public JcrGroovyTest(RepositoryService repositoryService,
+ ThreadLocalSessionProviderService sessionProviderService) {
+ this.repositoryService = repositoryService
+ this.sessionProviderService = sessionProviderService
+ }
+
+
+ @GET
+ @Path("{path:.*}")
+ public String nodeUUID(@PathParam("repository") String repository,
+ @PathParam("workspace") String workspace,
+ @PathParam("path") String path) {
+ Session ses = null
+ try {
+ ses = sessionProviderService.getSessionProvider(null).getSession(workspace,
repositoryService.getRepository(repository))
+ Node node = (Node) ses.getItem("/" + path)
+ return node.getUUID() + "\n"
+ } finally {
+ if (ses != null)
+ ses.logout()
+ }
+ }</programlisting>
+
+ <para>After configuration is done start server. If configuration is
+ correct and script does not have syntax error you should see next:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/groovy-console1.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>In screenshot we can see service deployed.</para>
+
+ <para>First create folder via WebDAV in repository production, folder name
+ 'test'. Now we can try access this service. Open another console and type
+ command:</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+http://localhost:8080/rest/groovy/test/repository/production/test</programlisting>
+
+ <para>Whe you try to execute this command you should have exception,
+ because JCR node '/test' is not referenceable and has not UUID. We can try
+ add mixin mix:referenceable. To do this add one more method in script.
+ Open script from local source code /home/andrew/JcrGroovyTest.groovy, add
+ following code and save file.</para>
+
+ <programlisting>@POST
+@Path("{path:.*}")
+public void addReferenceableMixin(@PathParam("repository") String repository,
+ @PathParam("workspace") String workspace,
+ @PathParam("path") String path) {
+ Session ses = null
+ try {
+ ses = sessionProviderService.getSessionProvider(null).getSession(workspace,
repositoryService.getRepository(repository))
+ Node node = (Node) ses.getItem("/" + path)
+ node.addMixin("mix:referenceable")
+ ses.save()
+ } finally {
+ if (ses != null)
+ ses.logout()
+ }
+}</programlisting>
+
+ <para>Now we can try to change script deployed on the server without
+ server restart. Type in console next command:</para>
+
+ <programlisting>andrew@ossl:~> curl -i -v -u root:exo \
+-X POST \
+--data-binary @JcrGroovyTest.groovy \
+-H 'Content-type:script/groovy' \
+http://localhost:8080/rest/script/groovy/update/repository/production/script/groovy/JcrGroovyTest.groovy</programlisting>
+
+ <para>Node '/script/groovy/JcrGroovyTest.groovy' has property
+ exo:autoload=true so script will be re-deployed automatically when script
+ source code changed.</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/groovy-console2.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>Script was redeployed, now try access newly created method.</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X POST \
+http://localhost:8080/rest/groovy/test/repository/production/test</programlisting>
+
+ <para>Method excution should be quiet, without output, traces, etc. Then
+ we can try again get node UUID.</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+http://localhost:8080/rest/groovy/test/repository/production/test
+1b8c88d37f0000020084433d3af4941f</programlisting>
+
+ <para>Node UUID: 1b8c88d37f0000020084433d3af4941f</para>
+
+ <para>We don't need this scripts any more, so remove it from
JCR.</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+http://localhost:8080/rest/script/groovy/delete/repository/production/script/groovy/JcrGroovyTest.groovy</programlisting>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/groovy-console3.png" />
+ </imageobject>
+ </mediaobject>
+ </section>
+
+ <section>
+ <title>Groovy script restrictions</title>
+
+ <para>You should keep one class per one groovy file. The same actually for
+ interface and it implementation. It's limitation of groovy parser that
+ does not have type Class[] parseClass(InputStream) or Collection
+ parseClass(InputStream) but only Class parseClass(InputStream)
+ instead.</para>
+
+ <para>That is all.</para>
+ </section>
+</chapter>
Added:
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/introduction-to-rest.xml
===================================================================
---
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/introduction-to-rest.xml
(rev 0)
+++
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/introduction-to-rest.xml 2010-05-28
09:59:52 UTC (rev 2442)
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>Introduction to the Representational State Transfer (REST)</title>
+
+ <section>
+ <title>Introduction</title>
+
+ <para><command>Representational State Transfer (REST)</command> is
a style
+ of software architecture for distributed hypermedia systems such as the
+ World Wide Web. The term was introduced in the doctoral dissertation in
+ 2000 by Roy Fielding, one of the principal authors of the Hypertext
+ Transfer Protocol (HTTP) specification, and has come into widespread use
+ in the networking community.</para>
+
+ <para>REST strictly refers to a collection of network architecture
+ principles that outline how resources are defined and addressed. The term
+ is often used in a looser sense to describe any simple interface that
+ transmits domain-specific data over HTTP without an additional messaging
+ layer such as SOAP or session tracking via HTTP cookies.</para>
+
+ <para>The key abstraction of information in REST is a
+ <command>resource</command>. Any information that can be named can be a
+ resource: a document or image, a temporal service (e.g. "today's weather
+ in Los Angeles"), a collection of other resources, a non-virtual object
+ (e.g. a person), and so on. In other words, any concept that might be the
+ target of an author's hypertext reference must fit within the definition
+ of a resource. A resource is a conceptual mapping to a set of entities,
+ not the entity that corresponds to the mapping at any particular point in
+ time.</para>
+
+ <para>REST uses a <command>resource identifier </command>to
identify the
+ particular resource involved in an interaction between components. REST
+ connectors provide a generic interface for accessing and manipulating the
+ value set of a resource, regardless of how the membership function is
+ defined or the type of software that is handling the request. URL or URN
+ are the examples of a resource identifier.</para>
+
+ <para>REST components perform actions with a resource by using a
+ <command>representation</command> to capture the current or intended
state
+ of that resource and transferring that representation between components.
+ A representation is a sequence of bytes, plus <command>representation
+ metadata </command>to describe those bytes. Other commonly used but less
+ precise names for a representation include: <command>document, file, and
+ HTTP message entity, instance, or variant</command>. A representation
+ consists of data, metadata describing the data, and, on occasion, metadata
+ to describe the metadata (usually for the purpose of verifying message
+ integrity). Metadata are in the form of name-value pairs, where the name
+ corresponds to a standard that defines the value's structure and
+ semantics. The data format of a representation is known as a media
+ type.</para>
+
+ <table>
+ <title>REST Data Elements</title>
+
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry align="center">Data Element</entry>
+
+ <entry align="center">Modern Web Examples</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>resource</entry>
+
+ <entry>the intended conceptual target of a hypertext
+ reference</entry>
+ </row>
+
+ <row>
+ <entry>resource identifier</entry>
+
+ <entry>URL, URN</entry>
+ </row>
+
+ <row>
+ <entry>representation</entry>
+
+ <entry>HTML document, JPEG image</entry>
+ </row>
+
+ <row>
+ <entry>representation metadata</entry>
+
+ <entry>media type, last-modified time</entry>
+ </row>
+
+ <row>
+ <entry>resource metadata</entry>
+
+ <entry>source link, alternates, vary</entry>
+ </row>
+
+ <row>
+ <entry>control data</entry>
+
+ <entry>if-modified-since, cache-control</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>REST uses various <command>connector</command> types to
encapsulate
+ the activities of accessing resources and transferring resource
+ representations. The connectors present an abstract interface for
+ component communication, enhancing simplicity by providing a complete
+ separation of concepts and hiding the underlying implementation of
+ resources and communication mechanisms.</para>
+
+ <table>
+ <title>REST Connectors</title>
+
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry align="center">Connector</entry>
+
+ <entry align="center">Modern Web Examples</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>client</entry>
+
+ <entry>libwww, libwww-perl</entry>
+ </row>
+
+ <row>
+ <entry>server</entry>
+
+ <entry>libwww, Apache API, NSAPI</entry>
+ </row>
+
+ <row>
+ <entry>cache</entry>
+
+ <entry>browser cache, Akamai cache network</entry>
+ </row>
+
+ <row>
+ <entry>resolver</entry>
+
+ <entry>bind (DNS lookup library)</entry>
+ </row>
+
+ <row>
+ <entry>tunnel</entry>
+
+ <entry><para></para>SOCKS, SSL after HTTP
CONNECT</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>The primary connector types are client and server. The essential
+ difference between the two is that a client initiates communication by
+ making a request, whereas a server listens for connections and responds to
+ requests in order to supply access to its services. A component may
+ include both client and server connectors.</para>
+
+ <para>An important part of RESTful architecture is a well-defined
+ interface to communicate, in particular it is a set of HTTP methods such
+ as POST, GET, PUT and DELETE. These methods are often compared with the
+ CREATE, READ, UPDATE, DELETE (CRUD) operations associated with database
+ technologies. An analogy can also be made:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>PUT is analogous to CREATE or PASTE OVER,</para>
+ </listitem>
+
+ <listitem>
+ <para>GET to READ or COPY,</para>
+ </listitem>
+
+ <listitem>
+ <para>POST to UPDATE or PASTE AFTER, and</para>
+ </listitem>
+
+ <listitem>
+ <para>DELETE to DELETE or CUT.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><command>Note</command>: RESTful architecture is not limited
to
+ those methods, one of good examples of extension is the WebDAV
+ protocol.</para>
+
+ <para>The <command>CRUD</command> (Create, Read, Update and Delete)
verbs
+ are designed to operate with atomic data within the context of a database
+ transaction. REST is designed around the atomic transfer of a more complex
+ state and can be viewed as a mechanism for transferring structured
+ information from one application to another.</para>
+
+ <para>HTTP separates the notions of a web server and a web browser. This
+ allows the implementation of each to vary from the other based on the
+ client/server principle. When used RESTfully, HTTP is
+ <command>stateless</command>. Each message contains all the information
+ necessary to understand the request.</para>
+
+ <para>As a result, neither the client nor the server needs to remember any
+ communication-state between messages. Any state retained by the server
+ must be modeled as a resource..</para>
+ </section>
+</chapter>
Added:
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/javascript-webdav-library.xml
===================================================================
---
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/javascript-webdav-library.xml
(rev 0)
+++
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/javascript-webdav-library.xml 2010-05-28
09:59:52 UTC (rev 2442)
@@ -0,0 +1,358 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>JavaScript WebDAV Library</title>
+
+ <section>
+ <title>Introduction to the JavaScript WebDAV library</title>
+
+ <para>I am proud to introduce JavaScript WebDAV library webdav.js which
+ based on AJAX. This library consists the special class webdav which is
+ aimed to make all requests supported by eXo Platform WebDAV-server with
+ supported parameters.</para>
+
+ <para>Proposed library supports asynchronous (on default) and synchronous
+ mode of AJAX request processing. To set one of some of this mode you
+ should call webdav.setAsynchronous() or webdav.setSynchronous()
+ method.</para>
+
+ <para>Also this library can fulfill BASIC HTTP authentication using value
+ of preset webdav.username and webdav.password properties.</para>
+
+ <para>Scheme of WebDAV data exchange:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/javascript-webdav.png" />
+ </imageobject>
+ </mediaobject>
+ </section>
+
+ <section>
+ <title>Content of JavaScript WebDAV Library:</title>
+
+ <para>There is a list of realized methods:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>ExtensionMethod(handler, path, options) method - a simple
+ constructor of the user-defined WebDAV request.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>1. WebDAV Modifications to HTTP Operations:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>GET(handler, path, options) method - retrieves the content of a
+ resource.</para>
+ </listitem>
+
+ <listitem>
+ <para>PUT(handler, path, options) method - saves the content of a
+ resource to the server.</para>
+ </listitem>
+
+ <listitem>
+ <para>DELETE(handler, path, options) method - removes a resource or
+ collection.</para>
+ </listitem>
+
+ <listitem>
+ <para>OPTIONS(handler, path, options) method - returns the HTTP
+ methods that the server supports for specified URL.</para>
+ </listitem>
+
+ <listitem>
+ <para>MKCOL(handler, path, options) method - creates a
+ collection.</para>
+ </listitem>
+
+ <listitem>
+ <para>COPY(handler, path, options) method - copies a resource from one
+ URI to another.</para>
+ </listitem>
+
+ <listitem>
+ <para>MOVE(handler, path, options) method - moves a resource from one
+ URI to another.</para>
+ </listitem>
+
+ <listitem>
+ <para>HEAD(handler, path, options) method - asks for the response
+ identical to the one that would correspond to a HEAD request, but
+ without the response body. This is useful for retrieving
+ meta-information written in response headers, without having to
+ transport the entire content.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>2. WebDAV Property Operations:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>PROPFIND(handler, path, options) method - retrieves properties,
+ stored as XML, from a resource. It is also overloaded to allow one to
+ retrieve the collection structure (a.k.a. directory hierarchy) of a
+ remote system.</para>
+ </listitem>
+
+ <listitem>
+ <para>PROPPATCH(handler, path, options) method - changes and deletes
+ multiple properties on a resource in a single atomic act.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>3. WebDAV Lock Operations:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>LOCK(handler, path, options) method - puts a lock on a
+ resource.</para>
+ </listitem>
+
+ <listitem>
+ <para>UNLOCK(handler, path, options) method - removes a lock from a
+ resource.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>4. WebDAV Versioning Extension Operations:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>VERSIONCONTROL(handler, path, options) method - is used to
+ create a new version-controlled resource for an existing version
+ history. This allows the creation of version-controlled resources for
+ the same version history in multiple workspaces.</para>
+ </listitem>
+
+ <listitem>
+ <para>CHECKOUT(handler, path, options) method - can be applied to a
+ checked-in version-controlled resource to allow modifications to the
+ content and dead properties of that version-controlled
+ resource.</para>
+ </listitem>
+
+ <listitem>
+ <para>CHECKIN(handler, path, options) method - can be applied to a
+ checked-out version-controlled resource to produce a new version whose
+ content and dead properties are copied from the checked-out
+ resource.</para>
+ </listitem>
+
+ <listitem>
+ <para>UNCHECKOUT(handler, path, options) method - can be applied to a
+ checked-out version-controlled resource to cancel the CHECKOUT and
+ restore the pre-CHECKOUT state of the version-controlled
+ resource.</para>
+ </listitem>
+
+ <listitem>
+ <para>REPORT(handler, path, options) method - an extensible mechanism
+ for obtaining information about a resource.</para>
+ </listitem>
+
+ <listitem>
+ <para>ORDERPATCH(handler, path, options) method - is used to change
+ the ordering semantics of a collection, to change the order of the
+ collection's members in the ordering, or both.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>5. WebDAV SEARCH Operation:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>SEARCH(handler, path, options) method - a lightweight search
+ method to transport queries and result sets that allows clients to
+ make use of server-side search facilities retrieve properties, stored
+ as XML, from a resource.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>If there is no interested WebDAV method in the list above, you can
+ use ExtensionMethod(handler, path, options) to construct WebDAV request
+ you like with your own:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>name of method (passing throw parameter options.method)</para>
+ </listitem>
+
+ <listitem>
+ <para>request headers (passing throw parameter options.headers)
+ and</para>
+ </listitem>
+
+ <listitem>
+ <para>request body (passing throw parameter options.body).</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>First parameter of each method - hanlder - is an object {onSuccess ,
+ onError, onComplete}, which describes three functions to call when the
+ request either succeeds or fails, and completes:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>handler.onSuccess - will call if the request succeeds,</para>
+ </listitem>
+
+ <listitem>
+ <para>handler.onError - will call if the request fails,</para>
+ </listitem>
+
+ <listitem>
+ <para>handler.onComplete - will call if the request
completes.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Additionally you can add your own headers to the request by using
+ the special parameter options.</para>
+
+ <para>Each method returns object result which consists next
+ properties:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>result.status - status of XMLHttp response,</para>
+ </listitem>
+
+ <listitem>
+ <para>result.statusstring - an explanation of status,</para>
+ </listitem>
+
+ <listitem>
+ <para>result.headers - object with hash of XMLHttpRequest
+ response.getAllResponseHeaders() (e.g. if this the response header is
+ "Content-Type: test/plain" then result.headers['Content-Type']
=
+ 'test/plain'),</para>
+ </listitem>
+
+ <listitem>
+ <para>result.content = XMLHttprequest response.responseXML if
+ response.header['Content-Type'] consists 'xml', or =
XMLHttpRequest
+ response.responseText otherwise.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Example of using of JavaScript WebDAV library</title>
+
+ <para>An example of using WebDAV library for the eXo Platform
+ WebDAV-server:</para>
+
+ <programlisting><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML
4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html;
charset=UTF-8" />
+ <title>Demonstration of the eXo Platform Client Library of
WebDAV</title>
+ <script type="text/javascript"
src="js/webdav.js"></script>
+ <script>
+
+// Example of using of eXo Platform Client Library of WebDAV
+/**
+ * Serialize an XML Document or Element and return it as a string.
+ */
+function XMLtoString(node) {
+ if (typeof node != 'object') return node;
+ if (typeof XMLSerializer != "undefined")
+ return (new XMLSerializer( )).serializeToString(node);
+ else if (node.xml) return node.xml;
+ else throw "XML.serialize is not supported or can't serialize " +
node;
+};
+
+// get and setup webdav object
+ var webdav = new Webdav('localhost', '8080');
+
+ webdav.username = 'root';
+ webdav.password = 'exo';
+
+// define webdav methods handlers
+ function handler_onSuccess(result) {
+ alert('Request SUCCEEDED with status = ' + result.status + ':
' + result.statusstring);
+ };
+
+ function handler_onError(result) {
+ alert('Request FAILED with status = ' + result.status + ': '
+ result.statusstring);
+ };
+
+var handler = {
+ onSuccess: handler_onSuccess,
+ onError: handler_onError,
+ onComplete: MKCOL_handler_onComplete
+}
+
+// for eXoPlatform webdav
+var default_webdav_path = '/rest/jcr/repository/collaboration';
+
+// create a collection 'test'
+webdav.MKCOL(handler, default_webdav_path + '/test1');
+
+// create a resource 'example.txt' with content 'an example'
+ function MKCOL_handler_onComplete(result) {
+ // create a resource 'example.txt' with content 'an example'
+ var options = {
+content: 'an example',
+content_type: 'text/plain; charset=UTF-8'
+ }
+ handler.onComplete = PUT_handler_onComplete;
+ webdav.PUT(handler, default_webdav_path + '/test1/example.txt', options);
+ };
+
+// put resource example.txt under version control
+ function PUT_handler_onComplete(result) {
+ // put resource example.txt under version control
+ handler.onComplete = VERSIONCONROL_handler_onComplete;
+ webdav.VERSIONCONTROL(handler, default_webdav_path +
'/test1/example.txt');
+ };
+
+// obtain the 'version-tree' WebDAV report about 'example.txt'
+ function VERSIONCONROL_handler_onComplete(result) {
+ // obtain the 'version-tree' WebDAV report about 'example.txt'
+ var options = {
+ depth: '0',
+ type: 'version-tree'
+ };
+ handler.onComplete = REPORT_handler_onComplete;
+ webdav.REPORT(handler, default_webdav_path + '/test1/example.txt', options);
+ };
+
+ // delete the collection 'test'
+ function REPORT_handler_onComplete(result) {
+ if ( result.content )
+alert( 'Response of server: ' + XMLtoString(result.content) );
+
+ // delete the collection 'test'
+ handler.onComplete = 'function() {}';
+ webdav.DELETE(handler, default_webdav_path + '/test1/');
+ };
+ </script>
+</head>
+<body>
+ <h2>Demonstration of the eXo Platform Client Library of
WebDAV</h2>
+</body>
+</html></programlisting>
+ </section>
+
+ <section>
+ <title>How to get JavaScript WebDAV library</title>
+
+ <para>You can get this library at the <link
+
linkend="???">http://svn.exoplatform.org/svnroot/exoplatform...
+
+ <para>Demonstration page was placed as <link
+
linkend="???">http://svn.exoplatform.org/svnroot/exoplatform...
+
+ <para>JSDoc is available at the <link
+
linkend="???">http://svn.exoplatform.org/svnroot/exoplatform...
+
+ <para>Another place of Javadoc will be at the <link
+ linkend="???">http://docs.exoplatform.com.ua site
soon</link>.</para>
+ </section>
+</chapter>
Added:
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/kerberos-sso-on-active-directory.xml
===================================================================
---
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/kerberos-sso-on-active-directory.xml
(rev 0)
+++
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/kerberos-sso-on-active-directory.xml 2010-05-28
09:59:52 UTC (rev 2442)
@@ -0,0 +1,305 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>Kerberos SSO on Active Directory</title>
+
+ <section>
+ <title>Overview</title>
+
+ <para>ExoPortal allows to use SSO (Single Sign On) with Kerberos
+ authentication on a Microsoft Active Directory. To install this
+ functionality, some configuration is needed, on the Active Directory
+ server and on the application server.</para>
+
+ <para>In this example, we suppose that the complete name of the machine on
+ which Tomcat server runs is ubu.exoua-int, and that it runs on the Linux
+ host (Ubuntu 7.04). This machine must be in Windows domain. How to do it
+ read in Samba documentation.</para>
+
+ <para>Our implementation makes it possible to use SPNEGO or NTLM
+ (sometimes this two terms can be mixed, but here we will try to separate
+ it). The client will get two authentication headers 'Negotiate' and
'NTLM'
+ and will use supported by client (browser). In Firefox it is possible to
+ manage authentication types, in IE this is not possible. This HOWTO will
+ describe how to make configuration to support both authentication types.
+ In fact for IE SPNEGO will work.</para>
+ </section>
+
+ <section>
+ <title>Active Directory configuration</title>
+
+ <para>On the AD server, we need to create a Kerberos identification for
+ Tomcat Server :</para>
+
+ <para>1. Create a user account for the host computer on which Tomcat
+ Server runs in the Active Directory server. (Select New > User, not New
+ > Machine.)</para>
+
+ <para>When creating the two user accounts, use the simple name of the
+ computer, and I recommend give names as next pattern host_host-name and
+ http_host-name. First account will be used for LDAP connection, second one
+ will be used for authentication service via HTTP. For example, if the host
+ name is ubu.exoua-int, create a users in Active Directory called host_ubu
+ and http_ubu.</para>
+
+ <para>Note the password you defined when creating the user account. You
+ will need it in step 3. Do not select the "User must change password at
+ next login" option, or any other password options.</para>
+
+ <para>2. Configure the new user account to comply with the Kerberos
+ protocol.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Right-click the name of the user account in the Users tree in
+ the left pane and select Properties.</para>
+ </listitem>
+ </itemizedlist>
+
+ <itemizedlist>
+ <listitem>
+ <para>NOTE Make sure the box "Use DES encryption types for this
+ account" is unchecked. Also make sure no other boxes are checked,
+ particularly the box "Do not require Kerberos
+ pre-authentication."</para>
+ </listitem>
+
+ <listitem>
+ <para>Setting the encryption type may corrupt the password. Therefore,
+ you should reset the user password by right-clicking the name of the
+ user account, selecting Reset Password, and re-entering the same
+ password specified earlier.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>3. Generate keys for service.</para>
+
+ <programlisting>C:\> ktpass -princ host/ubu.exoua-int@EXOUA-INT -mapuser
host_ubu@EXOUA-INT -crypto RC4-HMAC-NT \
+-ptype KRB5_NT_PRINCIPAL -mapop set -pass 123456 -out c:\host_ubu.keytab
+
+
+C:\> ktpass -princ HTTP/ubu.exoua-int@EXOUA-INT -mapuser http_ubu@EXOUA-INT
-crypto RC4-HMAC-NT \
+-ptype KRB5_NT_PRINCIPAL -mapop set -pass 123456 -out
c:\http_ubu.keytab</programlisting>
+
+ <para>4. Use the setspn utility to create the Service Principal Names
+ (SPNs) for the user account created in step 1. Enter the following
+ commands:</para>
+
+ <programlisting>C:\> setspn -A host/ubu.exoua-int host_ubu
+C:\> setspn -A HTTP/ubu.exoua-int http_ubu</programlisting>
+
+ <para>5. Check which SPNs are associated with your user account, using the
+ following command:</para>
+
+ <programlisting>C:\> setspn -L host_ubu</programlisting>
+
+ <para>NOTE This is an important step. If the same service is linked to a
+ different account in the Active Directory server, the client will not send
+ a Kerberos ticket to the server. If filter will be used secure-constraint
+ must be removed from web.xml</para>
+
+ <para>6. Configuration on Linux host. This is example of file
+ /etc/krb5.conf</para>
+
+ <programlisting>[logging]
+ default = FILE:/var/log/krb5libs.log
+ kdc = FILE:/var/log/krb5kdc.log
+ admin_server = FILE:/var/log/kadmind.log
+
+[libdefaults]
+ ticket_lifetime = 24000
+ default_realm = EXOUA-INT
+ default_tkt_enctypes = rc4-hmac
+ default_tgs_enctypes = rc4-hmac
+
+[realms]
+ EXOUA-INT = {
+ kdc = test01-srv.exoua-int:88
+ admin_server = test01-srv.exoua-int:749
+ default_domain = EXOUA-INT
+ }
+
+[domain_real]
+ .exoua-int = EXOUA-INT
+ exoua-int = EXOUA-INT
+
+[kdc]
+ profile = /etc/kdc.conf
+
+[pam]
+ debug = false
+ ticket_lifetime = 36000
+ renew_lifetime = 36000
+ forwardable = true
+ krb4_convert = false</programlisting>
+
+ <para>7. Copy key generated on step 3 to the Linux machine where tomcat
+ server runs.</para>
+
+ <para>8. Run the ktutil utility on the Linux machine and import
+ keys.</para>
+
+ <programlisting>andrew@ubu:~$ ktutil
+ktutil: rkt host_ubu.keytab
+ktutil: wkt host.keytab
+ktutil: rkt http_ubu.keytab
+ktutil: wkt http.keytab</programlisting>
+
+ <para>You must get to new files with tickets.</para>
+ </section>
+
+ <section>
+ <title>Setup webserver</title>
+
+ <para>1. Deploy an exo-tomcat, and copy the jar for SSO in lib folder and
+ change configuration.xml file to your network settings :</para>
+
+ <programlisting><configuration>
+ <component>
+
<key>org.exoplatform.services.security.sso.config.SSOConfigurator</key>
+
<type>org.exoplatform.services.security.sso.config.SSOConfigurator</type>
+ <init-params>
+ <properties-param>
+ <name>sso-properties</name>
+ <property name="charset" value="UnicodeLittleUnmarked"
/>
+ <property name="domain" value="EXOUA-INT" />
+ <property name="jaas-context" value="krb5.ldap-action"
/>
+ <property name="ldap-server"
value="ldap://test01-srv.exoua-int:389/" />
+ <!--
+ **********************************************************
+ Default cross domain authentication is disabled.
+ NOTE: This is actual for NTLM only.
+ For SPNEGO cross domain authentication is disabled by default.
+ There is some more work to enable it for SPNEGO.
+ **********************************************************
+ -->
+ <!--
+ <property name="cross-domain" value="true" />
+ -->
+ <!--
+ <property name="redirect-on-error"
value="http://google.com" />
+ -->
+ </properties-param>
+ </init-params>
+ </component></programlisting>
+
+ <para>2. In exo-tomcat/conf/Catalina/localhost/, change a file portal.xml
+ :</para>
+
+ <programlisting><Context path='/portal' docBase='portal'
debug='0' reloadable='true' crossContext='true'>
+ <Logger className='org.apache.catalina.logger.SystemOutLogger'
+ prefix='localhost_portal_log.' suffix='.txt'
timestamp='true'/>
+ <Manager className='org.apache.catalina.session.PersistentManager'
saveOnRestart='false'/>
+ <!--
+ <Realm className='org.apache.catalina.realm.JAASRealm'
+ appName='exo-domain'
+ userClassNames='org.exoplatform.services.security.jaas.UserPrincipal'
+ roleClassNames='org.exoplatform.services.security.jaas.RolePrincipal'
+ debug='0' cache='false'/>
+ <Valve
className='org.apache.catalina.authenticator.FormAuthenticator'
characterEncoding='UTF-8'/>
+ -->
+ <Valve
className="org.exoplatform.services.security.sso.tomcat.SSOAuthenticatorValve"/>
+</Context></programlisting>
+
+ <para>Secure configuration in web.xml must be changed to next:</para>
+
+ <programlisting><security-role>
+ <description>a simple user role</description>
+ <role-name>users</role-name>
+ </security-role>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>portal</web-resource-name>
+ <url-pattern>/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>users</role-name>
+ </auth-constraint>
+
+ <user-data-constraint>
+ <transport-guarantee>NONE</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint></programlisting>
+
+ <para>NOTE At list one roles in web.xml must be corresponding to user
+ group in AD. </para>
+
+ <para>3. Download in lib folder jcif-1.2.17.jar . We need this for support
+ NTLM authentication. </para>
+
+ <para>4. In exo-tomcat/conf/jaas.conf, add :</para>
+
+ <programlisting>com.sun.security.jgss.accept {
+ com.sun.security.auth.module.Krb5LoginModule required
+ keyTab = "/home/andrew/http.keytab"
+ useKeyTab = true
+ storeKey = true
+ principal = "HTTP/ubu.exoua-int@EXOUA-INT"
+ doNotPrompt = true
+ realm = "EXOUA-INT"
+ refreshKrb5Config = true
+ debug = false
+ ;
+};
+
+krb5.ldap-action {
+ com.sun.security.auth.module.Krb5LoginModule required
+ keyTab = "/home/andrew/host.keytab"
+ useKeyTab = true
+ storeKey = true
+ principal = "host/ubu.exoua-int@EXOUA-INT"
+ doNotPrompt = true
+ realm = "EXOUA-INT"
+ refreshKrb5Config = true
+ debug = false
+ ;
+};</programlisting>
+
+ <para>5. Add next system properties in file bin/eXo.sh</para>
+
+ <programlisting>KERBEROS="-Djavax.security.auth.useSubjectCredsOnly=false
\
+-Djava.security.krb5.kdc=test01-srv.exoua-int \
+-Djava.security.krb5.realm=EXOUA-INT"
+
+JAVA_OPTS="$YOURKIT_PROFILE_OPTION $JAVA_OPTS $LOG_OPTS $SECURITY_OPTS $EXO_OPTS
$EXO_CONFIG_OPTS $KERBEROS"</programlisting>
+
+ <para>6. For portal add one more filter for initialize Identity for user
+ org.exoplatform.services.security.sso.http.JndiIdentityInitalizerFilter
+ this filter must be mapped before
+ org.exoplatform.services.security.web.SetCurrentIdentityFilter on private
+ area.</para>
+
+ <para>7. For Firefox, there is an additionnal configuration to do to use
+ AD authentication : in adress bar, go to about:config. Filter on ntlm and
+ choose "network.automatic-ntlm-auth.trusted-uris". Set string to the name
+ of the machine where webserver run (in this exemple : set "ubu"). For IE,
+ there is no additional configuration.</para>
+
+ <para>8. Go to <link
+
linkend="???">http://ubu.exoua-int:8080/portal/private/classic</link>
If
+ use was login windows (domain authentication) then, Active directory
+ authentication will be used.</para>
+
+ <para>Instead tomcat valve
+ org.exoplatform.services.security.sso.tomcat.SSOAuthenticatorValve can be
+ used filter
+ org.exoplatform.services.security.sso.http.SSOAuthenticationFilter</para>
+
+ <para>9. Important about using NTLM. JCIF may use MAC for signature
+ connection to DC. In this case when one user logined, then next user may
+ be not able login during time specified in property
+ jcifs.smb.client.soTimeout (in ms), default 15000. This time JCIF keeps
+ previous connection opened and may not create new one to authenticate
+ other user. Must be set next properties to fix this
+ jcifs.smb.client.domain, jcifs.smb.client.username,
+ jcifs.smb.client.password. For example</para>
+
+ <programlisting>-Djcifs.smb.client.domain=EXOUA-INT
-Djcifs.smb.client.username=Admin
-Djcifs.smb.client.password=secret"</programlisting>
+
+ <para>In this case SMB connection will be signed for user.</para>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/oauth.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/oauth.xml
(rev 0)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/oauth.xml 2010-05-28
09:59:52 UTC (rev 2442)
@@ -0,0 +1,285 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>oAuth</title>
+
+ <section>
+ <title>Overview</title>
+
+ <para>OAuth allows to grant access to private resources on one site (which
+ is called the Service Provider), to another site (called Consumer). OAuth
+ is giving access to a resource without sharing your identity at all. More
+ about oAuth at the site <link
linkend="???">http://oauth.net/</link>.
+ (OAuth protocol: <link
+
linkend="???">http://oauth.net/core/1.0/</link>).</...
+
+ <para>This article describes how to configure our implementation of oAuth
+ service and client part. Both parts, service (Provider) and client
+ (Consumer) are based on oAuth core, this code can be found here <link
+
linkend="???">http://oauth.googlecode.com/svn/code/java/core...
+
+ <para>Our implementation can be found here <link
+
linkend="???">http://svn.exoplatform.org/svnroot/exoplatform...
+ </section>
+
+ <section>
+ <title>Provider</title>
+
+ <para>The provider consists of two parts oauthprovider.war and
+ exo.ws.security.oauth.provider.service-trunk.jar. The main part of the
+ provider is OAuthProviderService, currently there is one implementation of
+ this interface
+ org.exoplatform.ws.security.oauth.impl.OAuthProviderServiceMD5Impl; this
+ component has few required configuration parameters.</para>
+
+ <section>
+ <title>Configuration</title>
+
+ <para>The configuration is defined in the file
configuration.xml.</para>
+
+ <programlisting><component>
+
<type>org.exoplatform.ws.security.oauth.impl.OAuthProviderServiceMD5Impl</type>
+ <init-params>
+ <properties-param>
+ <name>exo1</name>
+ <property name="secret" value="81d1b5d080d1" />
+ <property name="description" value="description"
/>
+ <property name="callbackURL"
value="http://localhost:8080/ws-examples/callback" />
+ </properties-param>
+ </init-params>
+</component></programlisting>
+
+ <para>Properties:</para>
+
+ <para>1. <command>name</command>: the name of provider, the
client will
+ send the name of provider that it wants to use.</para>
+
+ <para>2. <command>secret</command>: this property is used for
subscribe
+ requests, this property must be known to the provider and the
+ consumer.</para>
+
+ <para>3. <command>description</command>: any description of the
+ provider. Optional.</para>
+
+ <para>4. <command>callbackURL</command>: this is URL where the
client
+ will be redirected after successful authentication by the
+ provider.</para>
+
+ <para>That is all what is needed for the configuration of the provider
+ service. The next part of configuration is about web, such as
+ servlets.</para>
+ </section>
+
+ <section>
+ <title>Servlets</title>
+
+ <para>The web part of the provider consists of 3 servlets:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>OAuthRequestTokenServlet,</para>
+ </listitem>
+
+ <listitem>
+ <para>OAuthAccessTokenServlet, and</para>
+ </listitem>
+
+ <listitem>
+ <para>OAuthAuthorizationServlet</para>
+ </listitem>
+ </itemizedlist>
+
+ <programlisting><?xml version="1.0"
encoding="UTF-8"?>
+<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
+
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+ <display-name>oAuth provider</display-name>
+ <context-param>
+ <description>Login page name</description>
+ <param-name>login-page</param-name>
+ <param-value>login/jsp/login.jsp</param-value>
+ </context-param>
+ <servlet>
+ <servlet-name>OAuthAuthenticationServlet</servlet-name>
+
<servlet-class>org.exoplatform.ws.security.oauth.http.OAuthAuthenticationServlet</servlet-class>
+ </servlet>
+ <servlet>
+ <servlet-name>OAuthRequestTokenServlet</servlet-name>
+
<servlet-class>org.exoplatform.ws.security.oauth.http.OAuthRequestTokenServlet</servlet-class>
+ </servlet>
+ <servlet>
+ <servlet-name>OAuthAccessTokenServlet</servlet-name>
+
<servlet-class>org.exoplatform.ws.security.oauth.http.OAuthAccessTokenServlet</servlet-class>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>OAuthAuthenticationServlet</servlet-name>
+ <url-pattern>/authorize/*</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>OAuthRequestTokenServlet</servlet-name>
+ <url-pattern>/request_token/*</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>OAuthAccessTokenServlet</servlet-name>
+ <url-pattern>/access_token/*</url-pattern>
+ </servlet-mapping>
+</web-app></programlisting>
+ </section>
+ </section>
+
+ <section>
+ <title>Consumer</title>
+
+ <para>The consumer consists of OAuthConsumerService and web part (servlets
+ and filters).</para>
+
+ <section>
+ <title>How it works</title>
+
+ <para>OAuthConsumerFilter checks cookies in client's request. The cookie
+ must have the name _consumer_name_.oauth_token and
+ _consumer_name_.oauth_token_secret. Then this filter try to find the
+ request/access token this at OAuthConsumerService. If the token from the
+ request is an access token then the client is already authenticated and
+ gets access to requested resource.</para>
+
+ <para>Otherwise the client will be redirected to the provider for
+ authentication (see below, property "provider.authorizationURL"). This
+ is the part of configuration.xml for the consumer:</para>
+
+ <programlisting><component>
+
<type>org.exoplatform.ws.security.oauth.impl.OAuthConsumerServiceImpl</type>
+ <init-params>
+ <value-param>
+ <!-- this parameter MUST be set in minutes -->
+ <name>tokenAliveTime</name>
+ <value>300</value>
+ </value-param>
+ <properties-param>
+ <name>exo1</name>
+ <property name="secret" value="81d1b5d080d1" />
+ <property name="description" value="description"
/>
+ <property name="provider.tokenRequestURL"
value="http://localhost:8080/oauthprovider/request_token" />
+ <property name="provider.authorizationURL"
value="http://localhost:8080/oauthprovider/authorize" />
+ <property name="provider.accessTokenURL"
value="http://localhost:8080/oauthprovider/access_token" />
+ </properties-param>
+ </init-params>
+</component>
+<component>
+
<type>org.exoplatform.ws.security.oauth.impl.OAuthClientHttpImpl</type>
+</component>
+<component>
+
<type>org.exoplatform.ws.security.oauth.impl.OAuthTokenCleanerImpl</type>
+ <init-params>
+ <value-param>
+ <!-- this parameter MUST be set in minutes -->
+ <name>tokenCleanerTimeout</name>
+ <value>3</value>
+ </value-param>
+ </init-params>
+</component></programlisting>
+
+ <para>The client is redirected for authentication to the provider with
+ the required parameters (request and secret token), before this token
+ OAuthClient got from the provider (see configuration, property
+ "provider.tokenRequestURL"). On the provider side, the user (if the
+ authentication is successful and has valid request parameters) will be
+ redirected to the consumer again (see property "callbackURL" in the
+ provider configuration). Then the consumer (this is, the same as
+ receiving request token, invisible for the client) receives the access
+ token, and redirects the client to the original URL. Then the filter
+ checks the token from the request and gives access to the requested
+ resource.</para>
+ </section>
+
+ <section>
+ <title>web.xml</title>
+
+ <para>This is the file web.xml for consumer application, in this example
+ the resource
http://localhost:8080/ws-examples/oauth/protected/ is under
+ oAuth protect :</para>
+
+ <programlisting><filter>
+<filter-name>OAuthConsumerFilter</filter-name>
+
<filter-class>org.exoplatform.ws.security.oauth.http.OAuthConsumerFilter</filter-class>
+ <init-param>
+ <param-name>consumer</param-name>
+ <param-value>exo1</param-value>
+</init-param> </filter>
<filter>
+<filter-name>OAuthRequestWrapperFilter</filter-name>
+<filter-class>org.exoplatform.ws.security.oauth.http.OAuthRequestWrapperFilter</filter-class>
</filter>
+
<filter-mapping>
+<filter-name>OAuthConsumerFilter</filter-name>
+<url-pattern>/oauth/protected/*</url-pattern>
+</filter-mapping>
+<filter-mapping>
+<filter-name>OAuthRequestWrapperFilter</filter-name>
+<url-pattern>/oauth/protected/*</url-pattern>
+</filter-mapping></programlisting>
+
+ <para>Any resource can be protected by this mechanism under the
+ condition that web.xml is configured to use OAuthConsumerFilter. Client
+ must save the given access and the secret token in a cookie.</para>
+ </section>
+
+ <section>
+ <title>Stages</title>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/oauth-scheme.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>1. continuous line - client's redirections</para>
+
+ <para>2. fine dashed line - internal oAuth schema requests and
+ responses.</para>
+
+ <para>Stages:</para>
+
+ <para>1. green - stage 1 (receiving request token)</para>
+
+ <para>2. yellow - stage 2 (authentication)</para>
+
+ <para>3. blue - stage 3 (receiving access token)</para>
+
+ <para>4. red - stage 4 (get protected resource)</para>
+ </section>
+
+ <section>
+ <title>Token Alive Time</title>
+
+ <para>Alive time for tokens can be set using the parameter
+ tokenAliveTime.</para>
+
+ <programlisting><value-param>
+ <!-- this parameter MUST be set in minutes -->
+ <name>tokenAliveTime</name>
+ <value>300</value>
+</value-param></programlisting>
+ </section>
+
+ <section>
+ <title>Token Cleaner Timeout</title>
+
+ <para>There is special component cleaner on consumer side, it starts, by
+ default, every 5 minutes and checks all tokens. If it finds token with
+ expired time it removes it from the storage. Token cleaner timeout (how
+ often it must run) can be also set in the configuration:</para>
+
+ <programlisting><component>
+
<type>org.exoplatform.ws.security.oauth.impl.OAuthTokenCleanerImpl</type>
+ <init-params>
+ <value-param>
+ <!-- this parameter MUST be set in minutes -->
+ <name>tokenCleanerTimeout</name>
+ <value&#623;</value>
+ </value-param>
+ </init-params>
+ </component></programlisting>
+ </section>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-framework.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-framework.xml
(rev 0)
+++
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-framework.xml 2010-05-28
09:59:52 UTC (rev 2442)
@@ -0,0 +1,472 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>REST Framework</title>
+
+ <important>
+ <para>This describes REST framework before version exo-ws-2.0</para>
+ </important>
+
+ <section>
+ <title>Requirements</title>
+
+ <para>The purpose of eXo REST framework is to make eXo services (i.e. the
+ components deployed inside eXo Container) simple and transparently
+ accessible via HTTP in RESTful manner. In other words those services
+ should be viewed as a set of REST Resources - endpoints of the HTTP
+ request-response chain, we call those services ResourceContainers.</para>
+
+ <para>image: Simplified working model</para>
+
+ <para>Taking into account HTTP/REST constraints, it is considered that
+ Resources (naturally mapped as Java methods) contained in
+ ResourceContainer conform with the following conditions:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>they are uniquely identifiable in the same way as it is
+ specified for HTTP i.e. using URI</para>
+ </listitem>
+
+ <listitem>
+ <para>they can accept data from an HTTP request using all possible
+ mechanisms, i.e. as a part of an URL, as URI parameters, as HTTP
+ headers and body</para>
+ </listitem>
+
+ <listitem>
+ <para>they can return data to an HTTP response using all possible
+ mechanisms, i.e. as HTTP status, headers and body</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>From the implementation point of view:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the framework should be as much JSR-311 compatible as possible
+ for the time the Specification is in draft and fully compatible after
+ the standard's release</para>
+ </listitem>
+
+ <listitem>
+ <para>the ResourceContainer components should be deployable and
+ accessible in the same way as an ordinary service</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Implementation</title>
+
+ <para>In our REST architecture implementation, an HTTPServlet is the
+ front-end for the REST engine. In this RESTful framework, endpoints for
+ HTTP request are represented by java classes (ResourceContainers). All
+ ResourceContainers are run as components of an ExoContainer, so they are
+ configured within the same configuration file.</para>
+
+ <para>ResourceBinder and ResourceDispatcher are two other important
+ components of the REST engine. ResourceBinder deals with binding and
+ unbinding ResourceContainer. ResourceDispatcher dispatches REST requests
+ to ResourceContainer. ResourceBinder and ResourceDispatcher are also
+ components of the ExoContainer</para>
+
+ <section>
+ <title>ResourceContainer</title>
+
+ <para>A ResourceContainer is an annotated java class. Annotations must
+ at least describe URLs and HTTP methods to be served by this container.
+ But they may also describe other parameters, like produced content type
+ or transformers. Transformers are special Java classes, used to
+ serialize and deserialize Java objects.</para>
+
+ <para>A very simple ResourceContainer may look like this:</para>
+
+ <programlisting>@HTTPMethod("GET")
+@URITemplate("/test1/{param}/test2/")
+public Response method1(@URIParam("param") String param) {
+//...
+//...
+ Response resp = Response.Builder.ok().build();
+ return resp;
+}</programlisting>
+
+ <para>The ResourceContainer described above is very simple, it can serve
+ the GET HTTP method for the relative URL /test1/{param}/test2/ where
+ {param} can be any string value. Additionally, {param} can be used as a
+ method parameter of the container by annotating it as :
+ @URIParam("param") String param. For example, in URL /test1/myID/test2
+ the method parameter "param" has the value
"myID".</para>
+
+ <para>@URITemplate may be used for annotating classes or methods. If the
+ TYPE scope annotation is for example @URITemplate("/testservices/") and
+ a METHOD scope annotation is @URITemplate("/service1/") then that method
+ can be called with the path /testservices/service1/. All
+ ResourceContainer methods return Response objects. A Response includes
+ HTTP status, an entity (the requested resource), HTTP headers and
+ OutputEntityTransformer.</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/rest-scheme.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>A client sends a request, after some operations, the HTTP request
+ is parsed into three parts: the HTTP request stream, which consists of
+ the body of the request, HTTP headers and query parameters. Then
+ ResourceDispatcher gets this request. During the start of ExoContainers
+ ResourceBinder collects all available ResourceContainers and after the
+ start passes the list of ResourceContainers to the ResourceDispatcher.
+ When ResourceDispatcher gets the request from a client it tries to
+ search for a valid ResourceContainer. For this search ResourceDispatcher
+ uses @HTTPMethod, @URITemplate and @ProducedMimeType annotations. The
+ last one is not always necessary, if it is not specified this is set in
+ / (all mime types). When ResourceDispatcher found the "right"
+ ResourceContainer it tries to call a method with some parameters.
+ ResourceDispatcher will send only parameters which ResourceContainer
+ requests. In the code example above the parameter is a part of the
+ requested URL between "/test1/" and "/test2/".
ResourceContainer methods
+ can consist only of some well-defined parameters. See the next
+ rules:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Only one parameter of a method can be not annotated. This
+ parameter represents the body of the HTTP request.</para>
+ </listitem>
+
+ <listitem>
+ <para>All other parameters should be of java.lang.String types or
+ must have a constructor with the java.lang.String parameter and must
+ have annotation.</para>
+ </listitem>
+
+ <listitem>
+ <para>If the parameter which represents the HTTP request body is
+ present, then in the annotation @InputTransformer a java class must
+ be defined that can build the requested parameter from
+ java.io.InputStream. About transformation see below. After request
+ processing ResourceContainer creates Request. Request is a special
+ Java object which consists of HTTP status, a response header, an
+ entity, a transformer. The entity is a representation of the
+ requested resource. If Response has an entity it also must have
+ OutputEntityTransformer. OutputEntityTransformer can be set in a few
+ different ways.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Response</title>
+
+ <para>Response is created by Builder. Builder is an inner static Java
+ class within Response. Builder has some preset ways to build Response,
+ for example (see code example above). The method ok() creates Builder
+ with status 200 (OK HTTP status) and ok() returns again a Builder
+ object. In this way a developer can again call other Builder methods.
+ For example:</para>
+
+ <programlisting>//...
+Document doc = ....
+Response response = Response.Builder.ok().entity(doc,
"text/xml").transformer(new
XMLOutputTransformer()).build();</programlisting>
+
+ <para>In the code example above Response has HTTP status 200, an XML
+ document like entity, a Content-Type header "text/xml" and
+ OutputEntityTransformer of type XMLOutputTransformer. The method build()
+ should be called at the end of process. In the same way a developer can
+ build some other prepared Responses, like CREATED, NO CONTENT,
+ FORBIDDEN, INTERNAL ERROR and other. In this example we set
+ OutputEntityTransformer directly. Another mechanism to do this is the
+ same like in the case with InputEntityTransformer.</para>
+
+ <programlisting>//...
+@HTTPMethod("GET")
+@URITemplate("/test/resource1/")
+(a)InputTransformer(XMLInputTransformer.class)
+(a)OutputTransformer(XMLOutputTransformer.class)
+public Response method1(Document inputDoc) {
+//...
+ Document doc = ....
+ Response response = Response.Builder.ok(doc, "text/xml").build();
+ return response;
+}</programlisting>
+
+ <para>InputEntityTransformer is described in the annotation to the
+ method "method1". OutputEntityTransformer is described in the annotation
+ to the method "method1".</para>
+ </section>
+
+ <section>
+ <title>Transformer</title>
+
+ <para>All transformers can be created by EntityTransformerFactory.
+ Transformers can be divided in two groups. Transformers from the first
+ one extend the abstract class InputEntityTransformer.
+ InputEntityTransformer implements the interface
+ GenericInputEntityTransformer, and GenericInputEntityTransformer extends
+ the interface GenericEntityTransformer. This architecture gives the
+ possibility to use one class EntityTransformerFactory for creating both
+ types of transformers (input and output). At first we will speak about
+ InputEntityTransformer.</para>
+
+ <para><command>InputEntityTransformer</command></para>
+
+ <para>All classes which extend the abstract class InputEntitytransformer
+ must override the method ObjectreadFrom(InputStream entityDataStream).
+ This method must return an object with the same type as
+ ResourceContainer requires in method parameters (one not annotated
+ parameter). This mechanism works in the following way. For example, a
+ class which extends InputEntityTransformer will be called
+ SimpleInputTransformer. So, SimpleInputTransformer must have a simple
+ constructor (without any parameters). SimpleInputTransformer also has
+ two methods void setType(Class entityType) and Class getType(). Those
+ methods are described in InputEntityTransformer. And, as we said above,
+ SimpleInputTransformer must override the abstract method Object
+ readFrom(InputStream entityDataStream). So, a developer needs to create
+ a class which can build a Java Object from InputStream and then create
+ annotation to ResourceContainer or some method in ResourceContainer.
+ This annotation must define the type of InputEntityTransformer. Here is
+ the code of the annotation InputTransformer.</para>
+
+ <programlisting>//...
+@Retention(RUNTIME)
+@Target({TYPE, METHOD})
+public @interface InputTransformer {
+ Class<? extends InputEntityTransformer> value();
+}</programlisting>
+
+ <para>Then ResourceDispatcher gets InputTransformer from the factory
+ during runtime then builds an Object from stream and adds it to the
+ parameter array. See the code below.</para>
+
+ <programlisting>//...
+ InputEntityTransformer transformer = (InputEntityTransformer)
factory_.newTransformer(resource.getInputTransformerType());
+ transformer.setType(methodParameters[i]);
+ params[i] = transformer.readFrom(request.getEntityStream());
+//...
+ Response response = (Response)
resource.getServer().invoke(resource.getResourceContainer(),
params);</programlisting>
+
+ <para>A developer can find some prepared transformers in the package
+ "org.exoplatform.services.rest.transformer".</para>
+
+ <para><command>OutputEntityTransformer</command></para>
+
+ <para>OutputEntityTransformer can be used to serialize the Object which
+ represents the requested resource to OutputStream.
+ OutputEntityTransformer, in future we will call it
+ SimpleOutputTransformer, can be defined in a few ways.</para>
+
+ <para>Now some more words about transformation. The RESTful framework
+ has two multi-purpose input/output transformers. One of them is
+ JAXB(Input/Output)Transformer, and another one is
+ Serializable(Input/Output)Transformer. The first one uses JAXB API for
+ serializing and deserializing an object. Serializable
+ (Input/Output)Transformer uses the own methods of an entity for
+ serialization and deserialization. Here is an example:</para>
+
+ <programlisting>/...
+public class SimpleSerializableEntity implements SerializableEntity {
+
+ String data;
+
+ public SimpleSerializableEntity() {
+ }
+
+ public void readObject(InputStream in) throws IOException {
+ StringBuffer sb = new StringBuffer();
+ int rd = -1;
+ while((rd = in.read()) != -1)
+ sb.append((char)rd);
+ data = sb.toString();
+ }
+
+ public void writeObject(OutputStream out) throws IOException {
+ out.write(data.getBytes());
+ }
+}</programlisting>
+
+ <para>SerializableInputTransformer will try to use the method void
+ readObject(InputStream in) and SerializableOutputTransformer will try to
+ use the method void writeObject(OutputStream in).</para>
+ </section>
+
+ <section>
+ <title>Binding and unbinding components (ResourceContainers)</title>
+
+ <para>ResourceBinder takes care of binding and unbinding components
+ which represent ResourceContainer. All ResourceContainers must be
+ defined as ExoContainer components in configuration files, for
+ example:</para>
+
+ <programlisting><component>
+
<type>org.exoplatform.services.rest.samples.RESTSampleService</type>
+</component></programlisting>
+
+ <para>ResourceBinder is an ExoContainer component and implements the
+ interface org.picocontainer.Startable (see the picocontainer
+ documentation). So at the start of ExoContainer ResourceBinder collects
+ all available ResourceContainers. ResourceBinder makes validation for
+ all ResourceContainers. At least each ResourceContainer must have the
+ @HTTPMethod annotation and @URITemplate annotation. Other annotations
+ are not obligatory. It's not allowed to have few ResourceContainers or
+ methods with the same @HTTPMethod and @URITemplate annotation value. For
+ example, if one container/method has the following code:</para>
+
+ <programlisting>public class SimpleResourceContainer implements
ResourceContainer {
+ @HTTPMethod("GET")
+ @URITemplate("/services/{id}/service1/")
+ @InputTransformer(StringInputTransformer.class)
+ @OutputTransformer(StringOutputTransformer.class)
+ public Response method1(String data, @URIParam("id") String param) {
+ // ...
+ }
+}</programlisting>
+
+ <para>than another component with @HTTPMethod("GET") and
+ @URITemplate("/services/service1/{id}/") can't be bound. And now
we'll
+ try to explain this situation. On the one hand URITemplate is defined by
+ value /services/{id}/service1/, instead of {id} there can be any other
+ string value, so the combination /services/service1/service1/ is
+ possible and valid. On the other hand another URITemplate
+ /services/service1/{id}/ can have the string service1 instead of {id},
+ so for this resource the combination /services/service1/service1/ is
+ possible and valid. And now we have two resources with the same
+ URITemplate and the same HTTPMethod. This situation is not obligatory,
+ we can't say what method we must call! In this case ResourceBinder
+ generates InvalidResourceDescriptorException. Binder also checks the
+ method parameters. In parameters only one parameter without annotation
+ and of free type is allowed. All other parameters must have String type
+ (or have a constructor with String) and be annotated. In other cases
+ InvalidResourceDescriptorException* is generated. If all components have
+ the "right" @HTTPMethod and @URITemplate annotations they should be
+ bound without any problems. ResourceDispather gets a collection of
+ ResourceContainers during the start and everything is ready to serve a
+ request.</para>
+
+ <para>Note: within the scope of one component (one class) validation for
+ URI templates is not implemented, so a developer must take care of
+ @URITemplate and @HTTPMethod. Both of them must not be the same for
+ different methods. Except if @QueryTemplate or/and @ProducedMimeTypes
+ annotation is used.</para>
+ </section>
+
+ <section>
+ <title>ResourceDispatcher</title>
+
+ <para>Now let's talk about the features of ResourceDispatcher.
+ ResourceDispatcher is the main part of the RESTful engine. Above we said
+ some words about transformation and the role of ResourceDispatcher in
+ this process. Now we are ready to talk about annotated method
+ parameters. In one of the code examples above you could see the next
+ construction</para>
+
+ <programlisting>public Response method1(String data,
@URIParam("id") String param) {</programlisting>
+
+ <para>The method method1 is described with two parameters. The first
+ parameter String data is built from the entity body (InputStream). The
+ second one - String param is annotated by a special type Annotation.
+ This Annotation has the following code:</para>
+
+ <programlisting>@Target(value={PARAMETER})
+@Retention(RUNTIME)
+public @interface URIParam {
+ String value();
+}</programlisting>
+
+ <para>How does it work? After having found the right method
+ ResourceDispatcher gets the list of method parameters and starts
+ handling them. Dispatcher tries to find the not annotated parameter
+ (this entity body) and addresses InputEntityTransformer in order to
+ build the required Object from InputStream. When dispatcher finds an
+ annotated parameter it checks the type of annotation. It is possible to
+ have four types of annotation: @URIParam, @HeaderParam, @QueryParam and
+ @ContextParameter. If dispatcher has found the annotation
+ @URIParam("id") then it takes the parameter with the key "id"
from
+ ResourceDescription and adds it into the parameter array. The same
+ situation is with header, context and query parameters. So within the
+ method a developer gets only the necessary parameters from header, query
+ and uri. Some more information about @ContextParameters.
+ @ContextParameters can be set in the configuration file of a
+ component:</para>
+
+ <programlisting><component>
+<type>org.exoplatform.services.rest.ResourceDispatcher</type>
+ <init-params>
+ <properties-param>
+ <name>context-params</name>
+ <property name="test" value="test_1"/>
+ </properties-param>
+ </init-params>
+</component></programlisting>
+
+ <para>In this case any service can use this parameter, for
+ example:</para>
+
+ <programlisting>...method(@ContextParam("test") String p) {
+ System.out.println(p);
+}</programlisting>
+
+ <para>After its execution you should see "test_1" in
console.</para>
+
+ <para>And in each service the next context parameters can be used. The
+ name of these parameters are described in ResourceDispatcher:</para>
+
+ <programlisting>public static final String CONTEXT_PARAM_HOST =
"host";
+public static final String CONTEXT_PARAM_BASE_URI = "baseURI";
+public static final String CONTEXT_PARAM_REL_URI = "relURI";
+public static final String CONTEXT_PARAM_ABSLOCATION =
"absLocation";</programlisting>
+
+ <para>After that dispatcher finishes collecting parameters that the
+ method requires, invokes this method and passes the result to the client
+ as it is described above.</para>
+
+ <para>This part of code can explain how this mechanism works:</para>
+
+ <programlisting>//...
+ for (int i = 0; i < methodParametersAnnotations.length; i++) {
+ if (methodParametersAnnotations[i] == null) {
+ InputEntityTransformer transformer = (InputEntityTransformer) factory
+ .newTransformer(resource.getInputTransformerType());
+ transformer.setType(methodParameters[i]);
+ params[i] = transformer.readFrom(request.getEntityStream());
+ } else {
+ Constructor<?> constructor =
methodParameters[i].getConstructor(String.class);
+ String constructorParam = null;
+ Annotation a = methodParametersAnnotations[i];
+ if (a.annotationType().isAssignableFrom(URIParam.class)) {
+ URIParam u = (URIParam) a;
+ constructorParam =
request.getResourceIdentifier().getParameters().get(u.value());
+ } else if (a.annotationType().isAssignableFrom(HeaderParam.class)) {
+ HeaderParam h = (HeaderParam) a;
+ constructorParam = request.getHeaderParams().get(h.value());
+ } else if (a.annotationType().isAssignableFrom(QueryParam.class)) {
+ QueryParam q = (QueryParam) a;
+ constructorParam = request.getQueryParams().get(q.value());
+ } else if (a.annotationType().isAssignableFrom(ContextParam.class)) {
+ ContextParam c = (ContextParam) a;
+ constructorParam = contextHolder_.get().get(c.value());
+ }
+ if (methodParameters[i].isAssignableFrom(String.class)) {
+ params[i] = constructorParam;
+ } else {
+ params[i] = (constructorParam != null) ?
constructor.newInstance(constructorParam) : null;
+ }
+ }
+ }
+ Response resp = (Response)
resource.getServer().invoke(resource.getResourceContainer(), params);
+//...</programlisting>
+
+ <para>The more detailed schema looks like this:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/rest-scheme-detailed.png" />
+ </imageobject>
+ </mediaobject>
+ </section>
+ </section>
+</chapter>
Added:
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-migration-to-jsr311.xml
===================================================================
---
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-migration-to-jsr311.xml
(rev 0)
+++
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-migration-to-jsr311.xml 2010-05-28
09:59:52 UTC (rev 2442)
@@ -0,0 +1,327 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>REST Migration to jsr311</title>
+
+ <important>
+ <para>The new implementation of the REST engine respects the jsr311
+ specification.</para>
+ </important>
+
+ <section>
+ <title>REST service structure:</title>
+
+ <itemizedlist>
+ <listitem>
+ <para>REST service must be represented by Java class that has @Path
+ annotation, it calls <command>root resource</command>. In some cases
+ class may have not @Path, about this classes see in Sub-Resource
+ Locators section. Root resource class may contain <command>Resource
+ Methods</command>, <command>Sub-Resource Methods</command> and
+ <command>Sub-Resource Locators</command>. Root resource MUST contain
+ at least one of it. </para>
+
+ <para>1. <command>Resource Method</command> it is method that
contains
+ HTTP method annotation, e.g. @GET, @POST, etc. and it does not contain
+ @Path annotation. </para>
+
+ <para>2. <command>Sub-Resource Method</command> it is method
that
+ contains HTTP method annotation and @Path annotation. Sub-Resource
+ Locator it is method that does not contain HTTP method annotation but
+ contains @Path annotation. </para>
+
+ <para>3. <command>Sub-Resource Locator </command>can't
process request
+ directly but it can produce Object (Resource) and that object can
+ process request or has <command>Sub-Resource Locator</command> that
+ can produce other Resource.Other important part @Consumes and
+ @Produces annotations. These annotations can be used at classes and
+ methods. Annotation on method override annotation on class.</para>
+ </listitem>
+
+ <listitem>
+ <para>Annotated method parameters @PathParam, @QueryParam, @FormParam,
+ @HeaderParam, @Matrix, @CookieParam, @Context annotation must be
+ (Description of this annotation in jsr311 specification or jsr311-api
+ javadoc): </para>
+
+ <para>1. String </para>
+
+ <para>2. Primitive type, except char </para>
+
+ <para>3. Has constructor with single string arguments </para>
+
+ <para>4. Has static valueOf method with single string argument
</para>
+
+ <para>5. Be List, Set or SortedSet with items described in first four
+ points</para>
+ </listitem>
+
+ <listitem>
+ <para>Not annotated method parameter or <command>Entity
+ Parameter</command>. </para>
+
+ <para>1. Must be not more then one </para>
+
+ <para>2. <command>Sub-Resource Locator</command> MUST NOT have
+ <command>Entity Parameter</command>. </para>
+
+ <para>3. If <command>Resource Method</command> or
+ <command>Sub-Resource Method</command> contains at least one
parameter
+ with @FormParam annotation then <command>Entity Parameter</command>
+ MUST be MultivaluedMap<String, String> only.</para>
+ </listitem>
+
+ <listitem>
+ <para>Method return type. Resource method (<command>Resource
+ Method</command> or <command>Sub-Resource Method</command>) may
return
+ void,javax.ws.rs.core.Response,javax.ws.rs.core.GenericEntity or other
+ Java type. If void type returned ot returned object is null then 204
+ HTTP status will be set for response otherwise 200 status will be
+ used. With javax.ws.rs.core.Response response can be set by service
+ developer.</para>
+ </listitem>
+
+ <listitem>
+ <para>Reading/Writing Entity done via
+ <command>EntityProvider</command>. Each
+ <command>EntityProvider</command> can require precise preset media
+ type of entity, for example JsonEntityProvider require 'Content-Type'
+ and/or 'Accept' header set as application/json. REST engine supports
+ next entity provider:</para>
+
+ <table>
+ <title></title>
+
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry align="center">Provider class</entry>
+
+ <entry align="center">Media Type</entry>
+
+ <entry align="center">Java Type</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>ByteEntityProvider</entry>
+
+ <entry>*/*</entry>
+
+ <entry>byte[]</entry>
+ </row>
+
+ <row>
+ <entry>DataSourceEntityProvider</entry>
+
+ <entry>*/*</entry>
+
+ <entry>javax.activation.DataSource</entry>
+ </row>
+
+ <row>
+ <entry>DOMSourceEntityProvider</entry>
+
+
<entry>application/xml,application/xhtml+xml,text/xml</entry>
+
+ <entry>javax.xml.transform.dom.DOMSource</entry>
+ </row>
+
+ <row>
+ <entry>FileEntityProvider</entry>
+
+ <entry>*/*</entry>
+
+ <entry>java.io.File</entry>
+ </row>
+
+ <row>
+ <entry>MultivaluedMapEntityProvider</entry>
+
+ <entry>application/x-www-form-urlencoded</entry>
+
+ <entry>MultivaluedMap<String, String></entry>
+ </row>
+
+ <row>
+ <entry>MultipartFormDataEntityProvider</entry>
+
+ <entry>multipart/*</entry>
+
+
<entry>java.util.Iterator<org.apache.commons.fileupload.FileItem></entry>
+ </row>
+
+ <row>
+ <entry>InputStreamEntityProvider</entry>
+
+ <entry>*/*</entry>
+
+ <entry>java.io.InputStream</entry>
+ </row>
+
+ <row>
+ <entry>ReaderEntityProvider</entry>
+
+ <entry>*/*</entry>
+
+ <entry>java.io.Reader</entry>
+ </row>
+
+ <row>
+ <entry>SAXSourceEntityProvider</entry>
+
+
<entry>application/xml,application/xhtml+xml,text/xml</entry>
+
+ <entry>javax.xml.transform.sax.SAXSource</entry>
+ </row>
+
+ <row>
+ <entry>StreamSourceEntityProvider</entry>
+
+
<entry>application/xml,application/xhtml+xml,text/xml</entry>
+
+ <entry>javax.xml.transform.stream.StreamSource</entry>
+ </row>
+
+ <row>
+ <entry>StringEntityProvider</entry>
+
+ <entry>*/*</entry>
+
+ <entry>java.lang.String</entry>
+ </row>
+
+ <row>
+ <entry>StreamOutputEntityProvider</entry>
+
+ <entry>*/*</entry>
+
+ <entry>NOTE for writing data only</entry>
+ </row>
+
+ <row>
+ <entry>JsonEntityProvider</entry>
+
+ <entry>application/json</entry>
+
+ <entry>Object (simple constructor, get/set methods)</entry>
+ </row>
+
+ <row>
+ <entry>JAXBElementEntityProvider</entry>
+
+
<entry>application/xml,application/xhtml+xml,text/xml</entry>
+
+ <entry>javax.xml.bind.JAXBElement</entry>
+ </row>
+
+ <row>
+ <entry>JAXBObjectEntityProvider</entry>
+
+
<entry>application/xml,application/xhtml+xml,text/xml</entry>
+
+ <entry>Object (simple constructor, get/set methods)</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Migration Examples</title>
+
+ <para>EXAMPLE #1</para>
+
+ <para><command>Old code</command></para>
+
+ <programlisting>package org.exoplatform.services.rest.example;
+
+import org.exoplatform.services.rest.HTTPMethod;
+import org.exoplatform.services.rest.URITemplate;
+import org.exoplatform.services.rest.URIParam;
+import org.exoplatform.services.rest.container.ResourceContainer;
+import org.exoplatform.services.rest.transformer.StringOutputTransformer;
+import org.exoplatform.services.rest.OutputTransformer;
+import org.exoplatform.services.rest.Response;
+
+@URITemplate("/a/{1}/b")
+public class Resource implements ResourceContainer {
+
+ @HTTPMethod("GET")
+ @URITemplate("{2}")
+ @OutputTransformer(StringOutputTransformer.class)
+ public Response m0(@URIParam("1") String param1, @URIParam("2")
String param2) {
+ Response resp = Response.Builder.ok(param1+param2, "text/plain").build();
+ return resp;
+ }
+}</programlisting>
+
+ <para><command>New code</command></para>
+
+ <programlisting>import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam
+
+@Path("/a/{1}/b")
+public class Resource implements ResourceContainer {
+ @GET
+ @Path("{2}")
+ @Produces("text/plain")
+ public String m0(@PathParam("1") String param1, @PathParam("2")
String param2) {
+ return path1+path2;
+ }
+}</programlisting>
+
+ <para>EXAMPLE #2</para>
+
+ <para><command>Old code</command></para>
+
+ <programlisting>import org.exoplatform.services.rest.HTTPMethod;
+import org.exoplatform.services.rest.InputTransformer;
+import org.exoplatform.services.rest.Response;
+import org.exoplatform.services.rest.URITemplate;
+import org.exoplatform.services.rest.container.ResourceContainer;
+import org.exoplatform.ws.frameworks.json.transformer.Json2BeanInputTransformer;
+
+public class Resource implements ResourceContainer {
+ @HTTPMethod("POST")
+ @URITemplate("/")
+ @InputTransformer(Json2BeanInputTransformer.class)
+ public Response m0(Book book) {
+ // do something with bean
+ return Response.Builder.noContent().build();
+ }
+}</programlisting>
+
+ <para><command>New code</command></para>
+
+ <programlisting>import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Consumes;
+
+@Path("/")
+public class Resource implements ResourceContainer {
+ @POST
+ @Consumes("application/json")
+ public void m0(Book book) {
+ // do something with bean
+ }
+}</programlisting>
+ </section>
+
+ <section>
+ <title>Support for javax.ws.rs.core.Application</title>
+
+ <para>Since version exo-ws-2.0.1 add support for class
+ javax.ws.rs.core.Application. It gives possibility to setup services and
+ provider life-cycle to singleton or per-request mode. For details see
+ JAX-RS specification, chapter 2. Subclass of Application should be
+ configured as component of exo-container.</para>
+ </section>
+</chapter>
Added:
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-service-tutorial.xml
===================================================================
---
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-service-tutorial.xml
(rev 0)
+++
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-service-tutorial.xml 2010-05-28
09:59:52 UTC (rev 2442)
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>REST Service Tutorial</title>
+
+ <important>
+ <para>This article describes REST framework before version
+ exo-ws-2.0.</para>
+ </important>
+
+ <section>
+ <title>Introduction</title>
+
+ <para>This HOW-TO explains how to create your own REST based services. In
+ this HOW-TO we will create a simple calculator, which can do basic
+ operations with integers.</para>
+ </section>
+
+ <section>
+ <title>Source code</title>
+
+ <programlisting>// ...
+@URITemplate("/calculator/{item1}/{item2}/")
+public class Calculator implements ResourceContainer {
+}</programlisting>
+
+ <para>Writing <command>@URITemplate</command> before the class
definition
+ gives you the possibility not to set it for each method. Furthermore the
+ class must implement the interface <command>ResourceContainer</command>.
+ This interface doesn't have any methods, it is just an indication for the
+ <command>ResourceBinder</command>. Add the code for adding two
+ integers.</para>
+
+ <programlisting>// ...
+@URITemplate("/calculator/{item1}/{item2}/")
+public class Calculator implements ResourceContainer {
+ @QueryTemplate("operation=add")
+ @OutputTransformer(StringOutputTransformer.class)
+ @HTTPMethod("GET")
+ public Response add(@URIParam("item1") Integer item1,
+ @URIParam("item2") Integer item2) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(item1).append(" + ").append(item2).append(" =
").append(item1 + item2);
+ return Response.Builder.ok(sb.toString(), "text/plain").build();
+ }
+}</programlisting>
+
+ <para>@QueryTemplate("operation=add") - only requests with query
+ parameters "operation=add" can reach this method;
+ @OutputTransformer(StringOutputTransformer.class) - the output
+ transformer; @HTTPMethod("GET") - the HTTP method
"GET".</para>
+
+ <para>Write the code for other operations in the same way. Then the result
+ should look like:</para>
+
+ <programlisting>package org.exoplatform.services.rest.example;
+
+import org.exoplatform.services.rest.HTTPMethod;
+import org.exoplatform.services.rest.OutputTransformer;
+import org.exoplatform.services.rest.QueryTemplate;
+import org.exoplatform.services.rest.Response;
+import org.exoplatform.services.rest.URIParam;
+import org.exoplatform.services.rest.URITemplate;
+import org.exoplatform.services.rest.container.ResourceContainer;
+import org.exoplatform.services.rest.transformer.StringOutputTransformer;
+
+@URITemplate("/calculator/{item1}/{item2}/")
+(a)OutputTransformer(StringOutputTransformer.class)
+public class Calculator implements ResourceContainer {
+
+ @QueryTemplate("operation=add")
+ @HTTPMethod("GET")
+ public Response add(@URIParam("item1") Integer item1,
@URIParam("item2") Integer item2) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(item1).append(" + ").append(item2).append(" =
").append(item1 + item2);
+ return Response.Builder.ok(sb.toString(), "text/plain").build();
+ }
+
+ @QueryTemplate("operation=subtract")
+ @HTTPMethod("GET")
+ public Response subtract(@URIParam("item1") Integer item1,
@URIParam("item2") Integer item2) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(item1).append(" - ").append(item2).append(" =
").append(item1 - item2);
+ return Response.Builder.ok(sb.toString(), "text/plain").build();
+ }
+
+ @QueryTemplate("operation=multiply")
+ @HTTPMethod("GET")
+ public Response multiply(@URIParam("item1") Integer item1,
@URIParam("item2") Integer item2) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(item1).append(" * ").append(item2).append(" =
").append(item1 * item2);
+ return Response.Builder.ok(sb.toString(), "text/plain").build();
+ }
+
+ @QueryTemplate("operation=divide")
+ @HTTPMethod("GET")
+ public Response divide(@URIParam("item1") Integer item1,
@URIParam("item2") Integer item2) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(item1).append(" / ").append(item2).append(" =
").append(item1 / item2);
+ return Response.Builder.ok(sb.toString(), "text/plain").build();
+ }
+}</programlisting>
+
+ <para>So we are done with the source code.</para>
+ </section>
+
+ <section>
+ <title>Configuration</title>
+
+ <para>Create the directory conf/portal and create the file
+ configuration.xml in it. Add the following code to this file:</para>
+
+ <programlisting><?xml version="1.0"
encoding="ISO-8859-1"?>
+<configuration>
+ <component>
+
<type>org.exoplatform.services.rest.example.Calculator</type>
+ </component>
+</configuration></programlisting>
+ </section>
+
+ <section>
+ <title>Build</title>
+
+ <para>Now we must create the following directory structure to get the
+ possibility to build the source code using maven.</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/rest-build-process.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>Then create the file pom.xml using the following:</para>
+
+ <programlisting><project>
+ <parent>
+ <groupId>org.exoplatform.ws</groupId>
+ <artifactId>config</artifactId>
+ <version>trunk</version>
+ </parent>
+
+ <modelVersion&#624;.0.0</modelVersion>
+ <groupId>org.exoplatform.ws.rest</groupId>
+ <artifactId>simple.calculator</artifactId>
+ <packaging>jar</packaging>
+ <version>trunk</version>
+ <description>Simple REST service</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.exoplatform.ws.rest</groupId>
+ <artifactId>exo.rest.core</artifactId>
+ <version>trunk</version>
+ </dependency>
+ </dependencies>
+</project></programlisting>
+
+ <para>Build this by executing the command:</para>
+
+ <programlisting>andrew@ubu:~/workspace/calculator$ mvn clean
install</programlisting>
+ </section>
+
+ <section>
+ <title>Deploy</title>
+
+ <para>We have done all now. Then copy the jar file from the target
+ directory of project exo-tomcat into the server with all prepared stuff
+ for REST services. (You can download it here: <link
+
linkend="???">http://forge.objectweb.org/project/download.ph...
+
+ <para>So just put the jar file into the lib directory of the tomcat and
+ restart it. In the console you should see this message:</para>
+
+ <programlisting>[INFO] ResourceBinder - Bind new ResourceContainer:
org.exoplatform.services.rest.example.Calculator@19846fd</programlisting>
+
+ <para>This message indicates that our service was found, bound and is
+ ready to work</para>
+ </section>
+
+ <section>
+ <title>Usage</title>
+
+ <para>Open your browser and type the following URL: <link
+
linkend="???">http://localhost:8080/rest/calculator/12/5/?operation=add</link>
+ and you should see the next page:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/rest-run-process.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>The service is working. This is a very simple example, but it should
+ help developers use the REST framework.</para>
+
+ <para>Try to check other URLs.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><link
+
linkend="???">http://localhost:8080/rest/calculator/12/5/?operation=subtract</link>
+ - must give "12 - 5 = 7";</para>
+ </listitem>
+
+ <listitem>
+ <para><link
+
linkend="???">http://localhost:8080/rest/calculator/12/5/?operation=multiply</link>
+ - must give "12 * 5 = 60";</para>
+ </listitem>
+
+ <listitem>
+ <para><link
+
linkend="???">http://localhost:8080/rest/calculator/12/5/?operation=divide</link>-
+ must give "12 / 5 = 2" (we are working with integers!);</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+</chapter>
Added:
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/soap-service-tutorial.xml
===================================================================
---
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/soap-service-tutorial.xml
(rev 0)
+++
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/soap-service-tutorial.xml 2010-05-28
09:59:52 UTC (rev 2442)
@@ -0,0 +1,248 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>SOAP Service Tutorial</title>
+
+ <section>
+ <title>Introduction</title>
+
+ <para>In this tutorial you will learn how you can use JSR 181 to expose
+ your Exo Container components as web services.</para>
+
+ <para>The steps given below have been tested with eXo WS samples 2.0.2
+ under Tomcat 6.0.16. It uses the WS tomcat bundle.</para>
+
+ <para>You can use maven build within "ws/tags/2.0.2/application" to
deploy
+ this sample application configuration:</para>
+
+ <programlisting>mvn clean install -f product-exo-ws-as-tomcat6.xml
antrun:run</programlisting>
+ </section>
+
+ <section>
+ <title>Add JSR 181 support to the deployed application</title>
+
+ <para>The JSR181 support does not come by default in portal.</para>
+
+ <para>The WS example tomcat bundle, which you can deploy with provided
+ command above, has already all necessary libraries and SOAP servlet
+ declarations.</para>
+
+ <para>For any other bundles you have to done the two steps below.</para>
+
+ <section>
+ <title>Add dependencies</title>
+
+ <para>First you need to add the necessary dependencies inside
+ exo-tomcat/lib</para>
+
+ <para>The required artifacts are :</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>exo.ws.soap.cxf.jsr181-2.0.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>exo.ws.application.soap.cxf.samples-2.0.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-rt-transports-http-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-api-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-rt-core-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-common-utilities-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>wsdl4j-1.6.1.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>geronimo-jaxws_2.1_spec-1.0.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>geronimo-ws-metadata_2.0_spec-1.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-rt-frontend-jaxws-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-rt-frontend-simple-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-rt-bindings-soap-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>XmlSchema-1.4.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-rt-databinding-jaxb-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>jaxb-impl-2.1.7.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-tools-common-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-rt-ws-addr-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>saaj-api-1.3.jar</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Configure CXF servlet</title>
+
+ <para>Edit YOUR_APPLICATION.war/WEB-INF/web.xml and add the CXF servlet
+ :</para>
+
+ <programlisting><servlet>
+ <servlet-name>SOAPServlet</servlet-name>
+ <display-name>SOAP Servlet</display-name>
+
<servlet-class>org.exoplatform.services.ws.impl.cxf.transport.http.SOAPServlet</servlet-class>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>SOAPServlet</servlet-name>
+ <url-pattern>/soap/services/*</url-pattern>
+ </servlet-mapping></programlisting>
+
+ <important>
+ <para>alternatively, you could bundle cxf in a separate app, but make
+ sure ws-examples.war starts before it</para>
+ </important>
+ </section>
+ </section>
+
+ <section>
+ <title>Write the Web Service class</title>
+
+ <para>We have a tiny sample to demonstrate called :
+ TicketOrderService.</para>
+
+ <para>Following JSR 181, it is now just a matter of annotating a class to
+ create a Web Service. The main idea is the your interface has to extends
+ extends AbstractSingletonWebService.</para>
+
+ <programlisting>@WebService
+public interface TicketOrderService extends AbstractSingletonWebService {
+
+ /**
+ * @param departing departing place.
+ * @param arriving arriving place.
+ * @param departureDate departure date.
+ * @param passenger passenger.
+ * @return ticket order.
+ */
+ public String getTicket(String departing, String arriving, Date departureDate, String
passenger);
+
+ /**
+ * @param confirmation confirm or not.
+ */
+ public void confirmation(boolean confirmation);
+
+}</programlisting>
+
+ <programlisting>@WebService(serviceName = "TicketOrderService",
+ portName = "TicketOrderServicePort",
+ targetNamespace = "http://exoplatform.org/soap/cxf")
+public class TicketOrderServiceImpl implements TicketOrderService {
+
+ /**
+ * Logger.
+ */
+ private static final Log LOG = ExoLogger.getLogger(TicketOrderServiceImpl.class);
+
+ /**
+ * Ticket.
+ */
+ private Ticket ticket;
+
+ /**
+ * @param departing departing place.
+ * @param arriving arriving place.
+ * @param departureDate departure date.
+ * @param passenger passenger.
+ * @return ticket order.
+ */
+ public String getTicket(String departing, String arriving, Date departureDate, String
passenger) {
+ ticket = new Ticket(passenger, departing, arriving, departureDate);
+ LOG.info(ticket);
+ return String.valueOf(ticket.getOrder());
+ }
+
+ /**
+ * @param confirmation confirm or not.
+ */
+ public void confirmation(boolean confirmation) {
+ LOG.info("Confirmation : " + confirmation + " for order '" +
ticket.getOrder() + "'.");
+ }
+
+}</programlisting>
+
+ <para>To test quickly, you can simply grab the jar on eXo repository and
+ deploy within your application.</para>
+ </section>
+
+ <section>
+ <title>Configure the component</title>
+
+ <programlisting><configuration
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://www.exoplatform.org/xml/ns/kernel_1_0.xsd
http://www.exoplatform.org/xml/ns/kernel_1_0.xsd"
+
xmlns="http://www.exoplatform.org/xml/ns/kernel_1_0.xsd">
+ <component>
+
<type>org.exoplatform.services.ws.soap.jsr181.TicketOrderServiceImpl</type>
+ </component>
+</configuration></programlisting>
+ </section>
+
+ <section>
+ <title>Verify it works.</title>
+
+ <para>Start server.</para>
+
+ <para>Execute script at
+ ws/tags/2.0.2/application/java/services/samples/soap/client to test
+ service</para>
+
+ <programlisting>run.sh</programlisting>
+
+ <para>and watch for this in the logs:</para>
+
+ <programlisting>Sep 3, 2009 5:21:13 PM org.apache.cxf.endpoint.ServerImpl
initDestination
+INFO: Setting the server's publish address to be
/TicketOrderService/TicketOrderServicePort
+03.09.2009 17:21:13 *INFO * [http-8080-1] ExoDeployCXFUtils: The webservice
'/TicketOrderService/TicketOrderServicePort' has been published SUCCESSFUL!
(ExoDeployCXFUtils.java, line 190)
+03.09.2009 17:21:13 *INFO * [http-8080-1] WebServiceLoader: New singleton WebService
'/TicketOrderService/TicketOrderServicePort' registered. (WebServiceLoader.java,
line 95)
+03.09.2009 17:21:27 *INFO * [http-8080-1] TicketOrderServiceImpl: Ticket {, , , null,
1251991287079} (TicketOrderServiceImpl.java, line 57)
+03.09.2009 17:21:27 *INFO * [http-8080-1] TicketOrderServiceImpl: Confirmation : false
for order '1251991287079'. (TicketOrderServiceImpl.java, line
65)</programlisting>
+
+ <para>Now, your service is started and you can retrieve the WSDL at :
+ <link
+
linkend="???">http://localhost:8080/ws-examples/soap/services/TicketOrderService/TicketOrderServicePort?wsdl</link></para>
+ </section>
+</chapter>
Modified: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws.xml 2010-05-28 09:56:00
UTC (rev 2441)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws.xml 2010-05-28 09:59:52
UTC (rev 2442)
@@ -8,4 +8,53 @@
<xi:include href="ws/ws.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/introduction-to-rest.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/rest-service-tutorial.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/rest-migration-to-jsr311.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/groovy-scripts-as-rest-services.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/rest-framework.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/soap-service-tutorial.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/central-authentication-service-configuration.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/kerberos-sso-on-active-directory.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/oauth.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/cometd.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/cometd-cluster.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/framework-for-cross-domain-ajax.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/cometd-cluster-bench.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/javascript-webdav-library.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/exo-ws-2-0.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/exo-ws-2-0-1.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
</part>
Added: jcr/trunk/docs/reference/en/src/main/resources/images/ajax-how-it-works.png
===================================================================
(Binary files differ)
Property changes on:
jcr/trunk/docs/reference/en/src/main/resources/images/ajax-how-it-works.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/ajax.gif
===================================================================
(Binary files differ)
Property changes on: jcr/trunk/docs/reference/en/src/main/resources/images/ajax.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/cometd-bench.png
===================================================================
(Binary files differ)
Property changes on:
jcr/trunk/docs/reference/en/src/main/resources/images/cometd-bench.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/cometd-cluster.png
===================================================================
(Binary files differ)
Property changes on:
jcr/trunk/docs/reference/en/src/main/resources/images/cometd-cluster.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/groovy-console1.png
===================================================================
(Binary files differ)
Property changes on:
jcr/trunk/docs/reference/en/src/main/resources/images/groovy-console1.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/groovy-console2.png
===================================================================
(Binary files differ)
Property changes on:
jcr/trunk/docs/reference/en/src/main/resources/images/groovy-console2.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/groovy-console3.png
===================================================================
(Binary files differ)
Property changes on:
jcr/trunk/docs/reference/en/src/main/resources/images/groovy-console3.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/javascript-webdav.png
===================================================================
(Binary files differ)
Property changes on:
jcr/trunk/docs/reference/en/src/main/resources/images/javascript-webdav.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/oauth-scheme.png
===================================================================
(Binary files differ)
Property changes on:
jcr/trunk/docs/reference/en/src/main/resources/images/oauth-scheme.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/rest-build-process.png
===================================================================
(Binary files differ)
Property changes on:
jcr/trunk/docs/reference/en/src/main/resources/images/rest-build-process.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/rest-run-process.png
===================================================================
(Binary files differ)
Property changes on:
jcr/trunk/docs/reference/en/src/main/resources/images/rest-run-process.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/rest-scheme-detailed.png
===================================================================
(Binary files differ)
Property changes on:
jcr/trunk/docs/reference/en/src/main/resources/images/rest-scheme-detailed.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/rest-scheme.png
===================================================================
(Binary files differ)
Property changes on:
jcr/trunk/docs/reference/en/src/main/resources/images/rest-scheme.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream