Since I lost hours to figure it out and since the official alfresco documentation is outdated and wrong about it I'd like to share how to do this.I'm using Alfresco 4.0.b, developing with maven-alfresco.The documentation is not clear at all on how to write a webscript using the FreeMarker templates as you would do with a javascript controller.So here's how to write a Java Backed controller src/main/java/my/experiment/webscript/MyExperimentWebscriptController.java:
package my.experiment.webscript;
import java.util.HashMap;
import java.util.Map;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptRequest;
public class MyExperimentWebscriptController extends DeclarativeWebScript {
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache) {
Map<String, Object> model = new HashMap<String, Object>();
model.put("mykey", "Happy coding! :D");
return model;
}
}
Declare the bean in src/main/config/context/service-context.xml:
<bean id="webscript.my.experiment.happycoding.get"
class="my.experiment.webscript.MyExperimentWebscriptController"
parent="webscript">
</bean>
Webscript description XML in src/main/resources/alfresco/extension/templates/webscripts/my/experiment/happycoding.get.desc.xml:
<?xml version="1.0" encoding="UTF-8"?>
<webscript>
<shortname>My Happy coding Experiment</shortname>
<description>Demo on how to use a java backed declarative webscript</description>
<url>/my/experiment/happycoding</url>
<format default="xml">argument</format>
<authentication runas="admin">none</authentication>
<negotiate accept="text/xml">xml</negotiate>
<negotiate accept="application/json">json</negotiate>
</webscript>
Note: I used authentication none and runas admin to show it is possible to run a public webscript as another user, even admin (careful on what you do! of course).Define the two FTL happycoding.get.xml.ftl and happycoding.get.json.ftl in the same folder of the description XML above:
<root>
<msg><![CDATA[Hello ${person.properties.userName}! ${mykey}]]></msg>
</root>
and the json template:
{
msg: "Hello ${person.properties.userName}! ${mykey}"
}
compile the amp:
mvn clean package
and apply it to the alfresco war with the apply_amps.sh script.I couldn't compile with maven, just add this to the pom.xml dependencies:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.extensions.surf</groupId>
<artifactId>spring-surf</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.extensions.surf</groupId>
<artifactId>spring-webscripts</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
not sure if they are all needed, I've done other stuffs and I don't know yet which one contained what I need.It's also possible that it will be fixed in maven-alfresco in the future
Test your webscript from an Unix machine with:
# xml
wget -O- –header='Accept: text/xml' 'http://localhost:8080/alfresco/service/my/experiment/happycoding' 2> /dev/null
<root>
<msg><![CDATA[Hello admin! Happy coding! :D]]></msg>
</root>
# json
wget -O- –header='Accept: application/json' 'http://localhost:8080/alfresco/service/my/experiment/happycoding' 2> /dev/null
{
msg: "Hello admin! Happy coding! :D"
}
If you are not using maven all of the above apply, you just have to adjust paths so that src/main/resources/alfresco/extension/templates/webscripts/my/experiment/happycoding.get.desc.xml will end up in WEB-INF/classes/alfresco/extension/templates/webscripts/my/experiment/happycoding.get.desc.xml.Since alfresco 3.3 you have to extend org.springframework.extensions.webscripts.DeclarativeWebScript instead of the removed alfresco class org.alfresco.web.scripts.DeclarativeWebScript.Since your Controller is effectively a spring bean you can inject alfresco services and use them from within your java controller.Note that:- The request contains all the methods to access paths, url arguments, headers
- You can change the output status using the "status" argument
- you can manage cache, it's been given to you
- finally, if you want you can override the executeFinallyImpl method to do some cleanup (you may need it I think), see below
the final cleanup method you may want to override, this is executed before failing with an exception so if you have some resource opened you can do it here
@Override
protected void executeFinallyImpl(WebScriptRequest req, Status status, Cache cache, Map<String, Object> model) {
// cleanup here
}
The other option is to extend org.springframework.extensions.webscripts.AbstractWebScript which give you complete control over the response, that means you don't use FreeMarker templates, you directly write the response as you would do in a servlet.Hope this help someone else.to Alfresco guys: please, really, put your effort on the documentation! Developers need it and you need developers!