WHAT'S IN THIS CHAPTER?
In this chapter, you will discover how to develop Java-backed Web scripts, which are Web scripts whose controller implementation is written in Java, rather than JavaScript. You might be wondering why you would need to dive into Java, when JavaScript Web scripts seem to cater to most requirements. Although rare, Java-backed Web scripts are useful when:
Accessing Alfresco Content Application Services not available via the JavaScript API
Interacting with systems whose only API is exposed via Java
Overriding how responses are rendered, such as to stream large content
Performance is absolutely critical
Unlike scripted Web scripts, Java-backed Web scripts require more tooling for their development. The Java source code has to be compiled, then packaged, and finally deployed to the Alfresco Content Application Server. This means deeper knowledge of the Alfresco architecture is required, such as knowing how Alfresco employs the Spring Framework for registering and binding together Java components.
Although this seems daunting, it's not that different from developing a scripted Web script, especially if you're already familiar with Java. A Java-backed Web script (as shown in Figure 11-1) has a very similar construction to that of a scripted Web script.
The primary difference is that a Java class replaces the controller script. It still has the same intent of encapsulating the behavior of the Web script and producing a model for subsequent rendering by a response template. Alfresco is aware of the Java class through Spring Framework configuration, which identifies the Java class as being the behavior for the Web script. All other components are exactly the same as those for scripted Web scripts.
The Spring Framework is an open source application framework for the Java platform best known for providing an Inversion of Control container, Aspect-Oriented Programming, and abstractions for data access and transaction management. Led and sustained by SpringSource, full details of the Spring Framework can be found at www.springsource.org
.
Java-backed Web scripts are best illustrated by developing an example. In this case, you are going to build the equivalent of the Folder ListingWeb script that was introduced in Chapter 9. This Web script mimics the behavior of the 'dir' command in Microsoft Windows, or 'ls' in Linux and Mac OS X.
Although the implementation introduced in this chapter replaces the controller script with Java, the behavior will not change: users will perceive no difference. In fact, it doesn't matter how theWeb script is implemented, as the client only interacts with it through HTTP requests and responses. This is very useful as it is sometimes convenient and efficient to build a library of scripted Web scripts exposing a well-defined interface and then, over time, replace their implementation with Java, if requirements such as performance become critical. As long as the interface does not change, the user will not notice.
Get started by first creating the scripted components of your Folder Listing Web script.
You first need to log in to Alfresco Explorer.
Type the following in your Web browser, and log in with the user name admin
and password admin
if requested:
http://localhost:8080/alfresco
Navigate to Company Home > Data Dictionary > Web Scripts Extensions.
Create a folder to represent the top-level package structure. You may skip this step if the org
space already exists.
In the Create menu, click Create Space.
Enter the name for the folder in the Name field, such as:
org
Click Create Space.
Next, create a sub-package. You may skip this step if the example
space already exists.
Navigate to Company Home > Data Dictionary > Web Scripts Extensions > org.
In the Create menu, click Create Space.
Enter the name for the folder in the Name field, such as:
example
Navigate to Company Home > Data Dictionary > Web Scripts Extensions > org > example.
Now create a Web script description document for your Java Folder Listing example.
In the Create menu, click Create Content.
Enter the name for the Web script in the Name field, such as:
javadir.get.desc.xml
In the Content Type list, select XML.
Click Next.
Type the following in the Enter Content box:
<webscript> <shortname>Folder Listing Utility</shortname> <description>Java-backed implementation of listing folder contents </description> <url>/javadir/{folderpath}?verbose={verbose?}</url> <authentication>user</authentication> </webscript>
Code snippet javadir.get.desc.xml
Click Next.
Click Finish.
Click OK.
Create a Web script response template for your Java Folder Listing example.
In the Create menu, click Create Content.
Enter the name for the Web script in the Name field as follows:
javadir.get.html.ftl
In the Content Type list, select Plain Text.
Click Next.
Type the following in the Enter Content box:
<html> <head> <title>Folder ${folder.displayPath}/${folder.name}</title> </head> <body> Alfresco ${server.edition} Edition v${server.version} : dir <p> Contents of folder ${folder.displayPath}/${folder.name} <p> <table> <#list folder.children as child> <tr> <td><#if child.isContainer>d</#if></td> <#if verbose> <td>${child.properties.modifier}</td> <td><#if child.isDocument> ${child.properties.content.size}</#if></td> <td>${child.properties.modified?date}</td> </#if> <td>${child.name}</td> </tr> </#list> </table> </body> </html>
Code snippet javadir.get.html.ftl
Click Next.
Click Finish.
Click OK.
The Web script description specifies a URI template containing the tokens {folderpath}
and {verbose?}
. The folderpath
token represents the folder to list and the verbose
URI argument specifies whether a verbose listing is required or not.
The HTML response template renders the contents of the specified folder, taking into account the verbose
flag. It does this by accessing the Web script model values named folder
and verbose
.
You haven't yet completed your Web script, which is still missing its controller. In this case, the controller needs to parse the URI to extract the token values, interact with the Alfresco content repository to locate the specified folder, and populate the model for subsequent rendering by the HTML response template.
It's now time to switch to Java for developing your controller.
First, create the Java class for your Folder Listing Web script.
Launch your Java IDE.
Create a Java package whose name is:
org.example
Create a Java class whose name is:
JavaDir
Implement the Java class as follows:
package org.example; import java.util.HashMap; import java.util.Map; import org.alfresco.repo.model.Repository; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.web.scripts.Cache; import org.alfresco.web.scripts.DeclarativeWebScript; import org.alfresco.web.scripts.Status; import org.alfresco.web.scripts.WebScriptException; import org.alfresco.web.scripts.WebScriptRequest; public class JavaDir extends DeclarativeWebScript { private Repository repository; public void setRepository(Repository repository) { this.repository = repository; } protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache) { // extract folder listing arguments from URI String verboseArg = req.getParameter("verbose"); Boolean verbose = Boolean.parseBoolean(verboseArg); Map<String, String> templateArgs = req.getServiceMatch().getTemplateVars(); String folderPath = templateArgs.get("folderpath");
// search for folder within Alfresco content repository String nodePath = "workspace/SpacesStore/" + folderPath; NodeRef folder = repository.findNodeRef("path", nodePath.split("/")); // validate that folder has been found if (folder == null) { throw new WebScriptException(Status.STATUS_NOT_FOUND, "Folder " + folderPath + " not found"); } // construct model for response template to render Map<String, Object> model = new HashMap<String, Object>(); model.put("verbose", verbose); model.put("folder", folder); return model; } }
Code snippet JavaDir.java
Compile the Java class.
Place the compiled Java class into the folder org/example
within the Web application classpath of the Alfresco Content Application Server.
Next, create the Spring Framework configuration for registering your Web script Java class.
Create an XML file whose name is:
javadir-context.xml
Register the Java class as follows:
<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN 2.0//EN' 'http://www.springframework.org/dtd/spring-beans-2.0.dtd'> <beans> <bean id="webscript.org.example.javadir.get" class="org.example.JavaDir" parent="webscript"> <property name="repository" ref="repositoryHelper"/> </bean> </beans>
Code snippet javadir-context.xml
Place the Spring Framework configuration file into the extension classpath of the Alfresco Content Application Server.
The Java samples in this chapter depend on the following libraries: alfresco-core, alfresco-repository, alfresco-webscript-framework, and dom4j.
For a default installation of Alfresco, the web application classpath is located at installLocation/tomcat/webapps/alfresco/WEB-INF/classes and the extension classpath is located at installLocation/tomcat/shared/classes/alfresco/extension.
When deploying a Java-backed Web script to the Alfresco Content Application Server, the server must be restarted for it to be fully registered.
You can now test your Java-backed Web script. In your Web browser, type the following:
http://localhost:8080/alfresco/service/javadir/Company%20Home?verbose=true
If successful, you will see a verbose listing of the contents of the Company Home folder. Externally, this Folder Listing Web script looks and behaves the same as its scripted Web script implementation.
The Java class for a Java-backed Web script only has to follow one rule, which is that it implements the Java interface:
org.alfresco.web.scripts.WebScript
This interface defines the following two methods, which must be implemented:
/** * Gets the Web script Description * * @return the Web script description */ public WebScriptDescription getDescription(); /** * Execute the Web script * * @param req the Web script request * @param res the Web script response */ public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException;
The first method, getDescription()
, returns a WebScriptDescription
object, which is a Java representation of the Web script description XML document. The second method, execute()
, is invoked by the Web Script Framework to initiate the Web script.
Thankfully, the Web Script Framework also provides two Java classes that implement the difficult parts of this interface, which you can extend as a starting point. The simplest helper Java class is named as follows:
org.alfresco.web.scripts.AbstractWebScript
This helper provides an implementation of getDescription()
but does not provide any execution assistance, which it delegates to its derived class. This allows a Java-backed Web script to take full control of the execution process, including how output is rendered to the response.
The other helper Java class is named as follows:
org.alfresco.web.scripts.DeclarativeWebScript
This helper provides an implementation of getDescription()
and execute()
. Interestingly, it encapsulates the execution of a scripted Web script, which is:
Locate an associated controller script written in JavaScript and, if found, execute it.
Locate an associated response template for the requested format and execute it, passing the model populated by the controller script.
By default, all Web scripts implemented through scripting alone are actually backed by the DeclarativeWebScript
Java class. There is one special hook point, though, that makes this a very useful class for your own Java-backed Web scripts to extend. Just prior to controller script execution, DeclarativeWebScript
invokes the template method executeImpl()
, which it expects derived Java classes to implement.
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache)
This is where the behavior of a custom Java-backed Web script is encapsulated, including the population of the Web script model, which is returned from this method.
Your Java Folder Listing Web script uses DeclarativeWebScript
for its starting point.
... public class JavaDir extendsDeclarativeWebScript
{ ... protected Map<String, Object>executeImpl
(WebScriptRequest req, Status status, Cache cache) { ... returnmodel
; } ... }
Code snippet JavaDir.java
The model returned from executeImpl()
is passed to the response template for subsequent rendering. Prior to template rendering, the model may also be accessed and further refined by a controller script, if one happens to be provided for the Web script.
Apart from implementing the WebScript
interface, there are no other Web script demands on the Java class. You are free to give the Java class any name and place it in any Java package.
Your Folder Listing Web script defines the following URI template with one URI-path token and one query parameter token:
<uri>/javadir/{folderpath}?verbose={verbose?}</uri>
To extract the values provided for the {folderpath}
and {verbose}
tokens, the following Java code is used:
... String verboseArg =req
.getParameter("verbose"); Boolean verbose = Boolean.parseBoolean(verboseArg); Map<String, String> templateArgs =req
.getServiceMatch().getTemplateVars(); String folderPath = templateArgs.get("folderpath"); ...
Code snippet JavaDir.java
Access to the request that invoked the Web script is through the req
parameter of the executeImpl()
method. This parameter encapsulates everything about the request, including its URI, query parameters, and header values. In particular, the getParameter()
method of the request provides access to query parameters, which your Web script uses to retrieve the value of the verbose
flag. If the query parameter is not specified on the URI, the returned value is null.
Access to tokens specified in the URI path is also through the req
parameter. A map of all URI-path token values indexed by token name is provided by req.getServiceMatch().getTemplateVars()
. Your Web script uses this map to retrieve the value of the folderpath
token. URI-path token values are never null.
Imagine a client has made the following URI request:
/javadir/Company%20Home?verbose=true
The resulting value of verbose
is true
and the value of folderpath
is Company Home
.
As a Java-backed Web script, all services provided by the Alfresco Content Application Server are available for use. In fact, any Java API within the server process, subject to security controls, is accessible.
Access to services is provided through a mechanism known as Dependency Injection (DI). Instead of the Java-backed Web script locating its dependent services, the dependent services are handed to the Web script.
Dependency Injection is a technique for supplying an external dependency to a software component. A full description of this technique can be found at http://en.wikipedia.org/wiki/Dependency_injection
.
Alfresco employs the Spring Framework for its Dependency Injection capabilities. This means that dependencies are specified in a separate XML configuration file as part of the Java-backed Web script registration. This XML configuration will be covered in more detail later in this chapter.
How are dependent services actually injected? For each dependency, the Java-backed Web script provides a setter method for accepting a reference to the dependent service. The Spring Framework invokes each of the setter methods with the appropriate configured dependency during the initialization of the Java-backed Web script. By the time the Web script is executed, all dependent services are available within the executeImpl()
method.
Your Folder Listing Web script needs to locate the folder within the Alfresco content repository that is identified by the folderpath
token. To accomplish this, the Web script injects a Repository
service that provides some simple content repository access capabilities.
... public class JavaDir extends DeclarativeWebScript { private Repositoryrepository
; public voidsetRepository
(Repository repository) { this.repository = repository; } protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache) { ... String nodePath = "workspace/SpacesStore/" + folderPath; NodeRef folder =repository
.findNodeRef("path", nodePath.split("/")); ... } }
Code snippet JavaDir.java
The setRepository
method represents the setter method that is called by the Spring Framework. Its implementation simply stores the Repository
service reference in a member variable of the Java-backed Web script for subsequent access in the executeImpl()
method.
A Web script uses a response status code to inform the calling client of its execution outcome. In Java, exceptions are often used for this and Java-backed Web scripts may follow suit.
Your Folder Listing Web script validates that the provided folder path actually exists in the Alfresco content repository using the following code pattern:
... if (folder == null) { throw new WebScriptException(Status.STATUS_NOT_FOUND, "Folder " + folderPath + " not found"); } ...
Code snippet JavaDir.java
The WebScriptException
class is a special kind of exception supported by the Web Script Framework, which carries a status code and message. Whenever a Web script throws this kind of exception, the Web Script Framework translates it into the equivalent status on the HTTP response.
All other exceptions are caught by the Web Script Framework and translated into the 500 status code, which means an internal error occurred. In all cases, the status response template has access to details such as the status code, status message, and exception call stack.
Throwing an exception is not always ideal, so the Web Script Framework provides another approach to setting the response status code. The executeImpl()
method is passed a Status
object, which allows the Web script to set the status explicitly.
Your Folder Listing Web script can implement folder validation using the following alternate code:
... if (folder == null) { status.setCode(Status.SC_NOT_FOUND); status.setMessage("Folder " + folderPath + " not found"); status.setRedirect(true); return; } ...
One advantage of setting the status explicitly is that the Web script may control whether a status response template is used to render the status through the setRedirect()
method.
Exceptions may be handled in a similar manner:
...
catch(ConstraintException e)
{
status.setCode(Status.SC_FORBIDDEN);
status.setMessage("Cannot create folder");
status.setException
(e);
status.setRedirect(true);
}
...
The setException()
method allows the Web script to associate the status with the caught exception.
One of the responsibilities of the controller is to create a model for subsequent rendering by a response template. A model is a map of values indexed by name. In Java, the model is simply returned from the executeImpl()
method as a Map
.
Your Folder Listing Web script constructs a HashMap
and places the verbose
flag and located folder
into it.
... Map<String, Object> model = new HashMap<String, Object>(); model.put("verbose
", verbose); model.put("folder
", folder); return model; ...
Code snippet JavaDir.java
The model is then subsequently available to response templates, which can use the values to render the output. An important point is that values placed into the map by Java are converted to values that are accessible to the FreeMarker template language.
For example, your Java Folder Listing Web script places a NodeRef
into the model under the name folder
, which it received from the Repository
service. A NodeRef
represents a reference to an object residing in the content repository. The Web Script Framework converts NodeRef
s into full objects so that FreeMarker templates can easily reference their object properties and methods as demonstrated by your Folder Listing response template:
Contents of folder ${folder.
displayPath}/${folder
.name}
Code snippet javadir.get.html.ftl
A Java-backed Web script does not have to create a model. In this case, the executeImpl()
method can simply return null.
A Java-backed Web script must be registered with the Web Script Framework. This is done through Spring Framework configuration, which supports the notion of a bean: a declaration of a Java class instance.
Each Java-backed Web script is defined by its own bean declaration. For example, your Java Folder Listing Web script is declared as follows:
... <beans> ... <bean id="webscript.org.example.javadir.get
" class="org.example.JavaDir
" parent="webscript
"> ... </bean> ... </beans>
Code snippet javadir-context.xml
Spring beans are given a unique identifier through their id
attribute and construct an instance of the Java class as named through their class
attribute.
The Web Script Framework uses the following bean id
naming convention for locating Java-backed Web scripts:
webscript.<web script package>.<web script id>.<http method>
The <web script package>, <web script id>
, and <http method>
are used to bind the Java class to the associated Web script. The class
attribute simply refers to the Java class implementing the Java-backed Web script.
Finally, all Web script bean declarations must have the parent 'webscript'
.
The Spring bean is also the place where service dependencies are declared. Your Folder Listing Web script declares a single dependency on the Repository
service as follows:
...
<bean id="webscript.org.example.javadir.get"
class="org.example.JavaDir" parent="webscript">
<property name="repository" ref="repositoryHelper"/>
</bean>
...
Code snippet javadir-context.xml
Each dependency is represented by a <property>
element whose name
attribute identifies the setter method to call and whose ref
attribute identifies the service to depend on. The ref
value is actually an ID of another bean. All Alfresco services are declared as beans, so can be injected in this way.
In the example, repository
maps to the setRepository()
method and repositoryHelper
maps to the bean representing the Repository
service.
...
public class JavaDir extends DeclarativeWebScript
{
...
public void setRepository
(Repository repository)
{
...
}
}
Code snippet JavaDir.java
Although your example only declares a single dependency, multiple dependencies may be declared. The Spring Framework calls setter methods during the initialization of the Java-backed Web script, so all dependencies are resolved by the time the executeImpl()
is invoked.
On some occasions it is useful to extend the capabilities of the Web Script Framework by introducing a new kind of Web script. This is useful for encapsulating behavior that you wish to reuse across many scripted Web scripts.
This is best demonstrated by developing a new kind of Web script. Your example will encapsulate the logic for finding a node in the content repository given a node path and placing that node into the Web script model. Web scripts of this kind only have to declaratively specify the node path in their Web script description for the model to be automatically populated with the associated node.
Behavior for a new kind of Web script is encapsulated in Java; therefore, you can follow the same steps as for developing a Java-backed Web script.
Time to get started.
First, create the Java class for your new kind of Web script.
Launch your Java IDE.
Create a Java package whose name is:
org.example
Create a Java class whose name is:
NodeWebScript
Implement the Java class as follows:
package org.example; import java.io.Serializable; import java.util.HashMap; import java.util.Map;
import org.alfresco.repo.model.Repository; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.web.scripts.Cache; import org.alfresco.web.scripts.DeclarativeWebScript; import org.alfresco.web.scripts.Status; import org.alfresco.web.scripts.WebScriptException; import org.alfresco.web.scripts.WebScriptRequest; public class NodeWebScript extends DeclarativeWebScript { private Repository repository; public void setRepository(Repository repository) { this.repository = repository; } protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache) { // extract node path from description extensions Map<String, Serializable> extensions = getDescription().getExtensions(); String path = (String)extensions.get("path"); // search for folder within Alfresco content repository String nodePath = "workspace/SpacesStore/" + path; NodeRef node = repository.findNodeRef("path", nodePath.split("/")); // validate that node has been found if (node == null) { throw new WebScriptException(Status.STATUS_NOT_FOUND, "Path " + path + " not found"); } // construct model for response template to render Map<String, Object> model = new HashMap<String, Object>(); model.put("node", node); return model; } }
Code snippet NodeWebScript.java
Compile the Java class.
Place the compiled Java class into the folder org/example
within the Web application classpath of the Alfresco Content Application Server.
Next, create a Java class for extracting the node path configuration for your new kind of Web script.
Create a Java class in the package org.example
whose name is:
NodeWebScriptExtension
Implement the Java class as follows:
package org.example; import java.io.InputStream; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import org.alfresco.web.scripts.DescriptionExtension; import org.alfresco.web.scripts.WebScriptException; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class NodeWebScriptExtension implements DescriptionExtension { public Map<String, Serializable> parseExtensions(String serviceDescPath, InputStream servicedesc) { Map<String, Serializable> extensions = new HashMap<String, Serializable>(); SAXReader reader = new SAXReader(); try { // extract path value from description document Document document = reader.read(servicedesc); Element rootElement = document.getRootElement(); Element pathElement = rootElement.element("path"); String path = pathElement.getTextTrim(); extensions.put("path", path); } catch (DocumentException e) { throw new WebScriptException("Failed to parse", e); } return extensions; } }
Code snippet NodeWebScriptExtension.java
Compile the Java class.
Place the compiled Java class into the folder org/example
within the Web application classpath of the Alfresco Content Application Server.
Now create the Spring Framework configuration file for registering your new kind of Web script.
Create an XML file whose name is:
nodewebscript-context.xml
Register the Java classes as follows:
<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN 2.0//EN' 'http://www.springframework.org/dtd/spring-beans-2.0.dtd'> <beans> <bean id="webscript.org.example.nodewebscript" class="org.example.NodeWebScript" parent="webscript" scope="prototype"> <property name="repository" ref="repositoryHelper"/> </bean> <bean id="webscriptdesc.org.example.nodewebscript" class="org.example.NodeWebScriptExtension"/> </beans>
Code snippet nodewebscript-context.xml
Place the Spring Framework configuration into the extension classpath of the Alfresco Content Application Server.
Your example Java class extends DeclarativeWebScript
just like other Java-backed Web scripts. Its primary purpose is to locate a node in the Alfresco content repository given a node path, which it does using the Repository
service. The NodeRef
returned from the Repository
service is placed into the Web script model under the name node
.
How does the implementation get hold of the node path? Instead of parsing the URI, the example uses a Web script description extension, which allows custom information to be placed into the Web script description. In this case, the path is to be extracted from a <path>
element as follows:
<webscript> ... <path>Company Home/Data Dictionary</path> ... </webscript>
Extensions to the Web script description are accessed through the getDescription().getExtensions()
method, which returns a map of extension values indexed by name. Your example extracts the path as follows:
... Map<String, Serializable> extensions = getDescription().getExtensions(); String path = (String)extensions.get("path"); ...
Code snippet NodeWebScript.java
The extension map still needs to be created from the Web script description XML document. This requires the development of another Java class that implements the following interface:
org.alfresco.web.scripts.DescriptionExtension
This interface defines the following single method, which must be implemented:
/** * Parse Web script description extensions * * @param serviceDescPath path to service document * @param serviceDesc service document input stream * @return extensions mapped by name */ public Map<String, Serializable> parseExtensions(String serviceDescPath, InputStream servicedesc);
An implementation of this interface parses the Web script description document to extract the custom extensions and returns a map of those extensions indexed by name. This is the same map that is returned by getDescription().getExtensions()
.
Your example extracts the value of the <path>
element from the Web script description document and places it into the extension map under the name path
.
... // extract path value from description document Document document = reader.read(servicedesc); Element rootElement = document.getRootElement(); Element pathElement = rootElement.element("path"); String path = pathElement.getTextTrim(); extensions.put("path", path); ...
Code snippet NodeWebScriptExtension.java
Finally, both Java classes are registered as Spring beans whose identifiers follow the naming convention defined by the Web Script Framework.
... <bean id="webscript.org.example.nodewebscript
" class="org.example.NodeWebScript" parent="webscript" scope="prototype"> ... </bean> <bean id="webscriptdesc.org.example.nodewebscript
" class="org.example.NodeWebScriptExtension"/> ...
Code snippet nodewebscript-context.xml
The Web script Java class identifier is structured as follows:
webscript.<web script kind id>
whereas the Web script description extension Java class identifier is structured as follows:
webscriptdesc.<web script kind id>
The <web script kind id>
can be any unique value but both IDs must match each other to be tied together.
When developing a scripted Web script, it is possible to specify its kind through its Web script description document. If the new kind of Web script supports extensions to the Web script description document, then those must be provided as well. Otherwise, development of the Web script is the same as any other Web script.
You will implement a simple Web script based on the example NodeWebScript
kind, which simply renders information about the Data Dictionary folder held in the Alfresco content repository.
You first need to log in to Alfresco Explorer.
Type the following in your Web browser, and log in with the user name admin
and password admin
if requested:
http://localhost:8080/alfresco
Navigate to Company Home > Data Dictionary > Web Scripts Extensions.
Create a folder to represent the top-level package structure. You may skip this step if the org space already exists.
In the Create menu, click Create Space.
Enter the name for the folder in the Name field, such as:
org
Click Create Space.
Next, create a sub-package. You may skip this step if the example space already exists.
Navigate to Company Home > Data Dictionary > Web Scripts Extensions > org.
In the Create menu, click Create Space.
Enter the name for the folder in the Name field, such as:
example
Navigate to Company Home > Data Dictionary > Web Scripts Extensions > org > example.
You now create a Web script description document for your Data Dictionary information sample.
In the Create menu, click Create Content.
Enter the name for the Web script in the Name field, as follows:
info.get.desc.xml
In the Content Type list, select XML.
Click Next.
Type the following in the Enter Content box:
<webscript kind="org.example.nodewebscript"> <shortname>Node Info</shortname> <description>Demonstration of Web script Kind</description> <url>/info</url> <authentication>user</authentication> <path>Company Home/Data Dictionary</path> </webscript>
Code snippet info.get.desc.xml
Click Next.
Click Finish.
Click OK.
Create a response template for your Data Dictionary information sample.
In the Create menu, click Create Content.
Enter the name in the Name field, such as:
info.get.html.ftl
In the Content Type list, select Plain Text.
Click Next.
Type the following in the Enter Content box:
${node.name} created on ${node.properties.created?date}
Code snippet info.get.html.ftl
Click Next.
Click Finish.
Click OK.
Now register the Data Dictionary Information Web script with Alfresco.
Type the following in your Web browser, and log in with the user name admin
and password admin
if requested:
http://localhost:8080/alfresco/service/index
Click Refresh Web Scripts. You'll see a message indicating there is one additional Web script.
Finally, it's time to test.
Type the following in your Web browser, and log in with the user name admin
and password admin
if requested:
http://localhost:8080/alfresco/service/info
If you see a message similar to Data Dictionary created on Jan 12, 2010, your Web script is working.
The Web script kind is specified through the kind
attribute of the <webscript>
element contained within the Web script description document. Its value is the <web script kind id>
as defined in the Spring configuration for the new kind of Web script.
In your example, the NodeWebScript
kind is selected by specifying its identifier of org.example.nodewebscript
:
<webscriptkind="org.example.nodewebscript"
> ...<path>
Company Home/Data Dictionary</path>
... </webscript>
Code snippet info.get.desc.xml
As expected by the NodeWebScript
, the description document also specifies a path to a node in the Alfresco content repository. In the example, you specify the Data Dictionary folder through the custom <path>
element.
Your example does not provide a controller script, as the NodeWebScript
Java class already encapsulates the behavior of locating a node given a path and populating the Web script model. In this case, the located node is placed into the Web script model under the name node
.
${node.
name} created on ${node
.properties.created?date}
Code snippet info.get.html.ftl
This means the response template can simply refer to node
to render the output.
3.144.18.198