In this recipe, we will describe how you can implement standard portlets using Spring WebScripts when you are using an Alfresco repository instance that is running in the same application server of the GateIn portal.
Alfresco is an open source ECM system that allows you to implement specific ECM architectures and build your own domain model for any type of contents, workflows, rules, security constraints, and collaboration tools.
For more information about Alfresco, please visit http://www.alfresco.com.
Spring WebScripts is a framework, initially contributed by Alfresco, which allows you to implement your own RESTful API. This framework supports scripting languages such as JavaScript and FreeMarker.
More details about Spring WebScripts can be found at the following URL:
http://www.springsurf.org/sites/1.0.0.M3/spring-webscripts/spring-webscripts-documentation/
The main components that you can use to implement a WebScript are as follows:
FreeMarker is a template engine used to build custom views. For more information about FreeMarker, see the following URL:
The template could be optional because in the case of a
Java-Backed WebScript implementation, you can only use a descriptor and a Java class to implement your WebScript in the same way you implement a custom
action with any other MVC framework. This is because AbstractWebScript
allows you to directly control of the HTTP request and response.
For more information about Java-Backed WebScripts, you can visit http://wiki.alfresco.com/wiki/Java-backed_Web_Scripts_Samples.
We will demonstrate how to implement two services exposed by WebScripts for providing an advanced search portlet in the portal:
The following are required for this recipe:
We are assuming that the Alfresco repository (alfresco.war
) is correctly deployed in the same application server of GateIn. This scenario
allows us to simplify examples without implementing custom and remote authenticators for the WebScripts framework.
We will start implementing the first WebScript dedicated to render the search form inside the portlet. We want a WebScript configured to be invoked only using the GET
method of the HTTP protocol:
extensionRoot
of Alfresco the following path: /alfresco/extension/templates/webscripts
.fulltextsearch.get.desc.xml
that describes the service with this content:<webscript> <shortname>Full Text Search Form</shortname> <description>Show the keyword search form</description> <url>/gatein/search</url> <url>/gatein/search.portlet</url> <authentication>guest</authentication> <format default="html" /> <transaction allow="readonly">required</transaction> <family>GateIn - ECM - Portlets</family> </webscript>
fulltextsearch.get.html.ftl
and enter a similar snippet:<div class="portlet-section-header">Alfresco - Full Text Search</div> <br/> <div class="portlet-section-body"> <div id="alfrescoSearch"> <form name="alfrescoSearchForm" onSubmit="return submitAlfrescoSearch();"> <table> <tr> <td<span class="portlet-form-label">Keyword:</span></td> <td> <input class="portlet-form-input-field" type="text" name="keyword" /> </td> <td> <input class="portlet-form-button" type="submit" value="Search"/> </td> </tr> </table> </form> <br /> <table id="results"> <tr> <td></td> </tr> </table> </div>
alfresco.war/WEB-INF/portlet.xml
:<portlet> <description>GateIn - ECM - Full Text Search</description> <portlet-name>FullTextSearch</portlet-name> <portlet-class> org.springframework.extensions.webscripts.portlet.WebScriptPortlet</portlet-class> <init-param> <name>authenticator</name> <value>webscripts.authenticator.jsr168</value> </init-param> <init-param> <name>scriptUrl</name> <value>/alfresco/168s/gatein/search</value> </init-param> <supports> <mime-type>text/html</mime-type> <portlet-mode>VIEW</portlet-mode> </supports> <portlet-info> <title>Alfresco Full Text Search</title> <short-title>Alfresco Search</short-title> </portlet-info> </portlet>
The important parameters of portlet.xml
that must be described are as follows:
portlet-class
: This is the implementation class of the portletauthenticator
: This is the authenticator class used to authenticate user sessions scriptUrl
: Consists of the context root that starts with alfresco/168s with a suffix based on the WebScript URL available in AlfrescoThe wrapper class that is responsible for exposing WebScript as portlets is provided by the Spring WebScripts framework. This class is WebScriptPortlet
, and it allows declaring inside the
portlet-class
element in the portlet.xml
of any web application deployed in the same application server of GateIn.
In this way, a portlet can be available in the portal and it is backed by a WebScript implementation.
You can set two different types for the authenticator
parameter:
webscripts.authenticator.jsr168
: This uses the same user session taken from the portal (this is the default authenticator, which is used when you don't specify the authenticator parameter)webscripts.authenticator.jsr168.webclient
: This uses the same user session taken from the portal, but synchronizes the session with the Alfresco Explorer applicationIf you need a different type of authenticator, you can implement your own and then declare it using the identifier of the Spring bean as the value of the authenticator
parameter.
In this way, you can implement your own Spring WebScripts for any type of operations and then you can declare them as portlets.
We will show another example of processing a WebScript using the JavaScript controller to execute a query against the Alfresco repository and return the results using a FreeMarker template.
Let's start to implement the complementary WebScript for finishing the advanced search portlet that we started in the previous section. This new WebScript
service must be exposed by the HTTP POST
method, and it will need a keyword
parameter for executing the full text search:
fulltextsearch.post.desc.xml
because we want to expose this result service via HTTP POST method. We are also declaring this WebScript with an output format portlet
, because there are some Ajax calls to refresh the view context of the previous WebScript:<webscript> <shortname>Full Text Search Results</shortname> <description>Show the results of the keyword search</description> <url>/gatein/search?keyword={keyword}</url> <authentication>guest</authentication> <format default="portlet" /> <transaction allow="readonly">required</transaction> <family>GateIn - ECM - Portlets</family> </webscript>
SearchService
of Alfresco with a JavaScript file fulltextsearch.post.js
:var keyword = ""; keyword = args.keyword; var searchResults = null; if(keyword != undefined && keyword!=""){ var luceneQuery = "TEXT:""+keyword+"""; searchResults = search.luceneSearch(luceneQuery); } else { status.code = 400; status.message = "Keyword not provided."; status.redirect = true; } model.keyword = keyword; model.searchResults = searchResults;
searchResults
to show a portlet section inside the FreeMarker file named fulltextsearch.post.portlet.ftl
:<p>Results for the keyword: <strong>${keyword}</strong></p> <p>Click on an item to download the document</p> <#if searchResults?exists> <table id="results"> <#list searchResults as hit> <tr> <td><a style="text-decoration: underline;" href="/alfresco${hit.url}" target="_blank">${hit.properties.name}</a></td> </tr> </#list> </table> <#else> <p>No results found.</p> </#if> <br /> <a href="#" onClick="viewSearchForm();">Return to the search form</a> <br />
3.15.168.214