cancel
Showing results for 
Search instead for 
Did you mean: 

Howto create a JavaBacked Web_Script using FLT templates

mastro
Champ in-the-making
Champ in-the-making
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 Smiley Happy


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!
9 REPLIES 9

openpj
Elite Collaborator
Elite Collaborator
I'll try to spend some time on the Alfresco Wiki (that is a better place for how-to guides Smiley Wink ) to add a generic example of DeclarativeWebScript in the following wiki page:
http://wiki.alfresco.com/wiki/Java-backed_Web_Scripts_Samples

Hope this helps  :wink:

mastro
Champ in-the-making
Champ in-the-making
I've written the previous example, without the maven part and trying to stick with the other sections structure

https://wiki.alfresco.com/wiki/Java-backed_Web_Scripts_Samples#DeclarativeWebScript.java


I can say your wiki is the worst I ever tried!!!! I'm gonna open another post about this, here in the forum

openpj
Elite Collaborator
Elite Collaborator
Again and again, the wiki is written by contributors of the Alfresco community as you have done now.
The Alfresco wiki is not the official Alfresco documentation.

Thank you for your contribution during these days I'll review the page to test all the implementations with Alfresco 4.

Hope that this could help you to understand the goal of each tool that Alfresco provides to the community  :wink:

m_scapoli
Champ in-the-making
Champ in-the-making
Again and again, the wiki is written by contributors of the Alfresco community as you have done now.
The Alfresco wiki is not the official Alfresco documentation.

ok, if the official Alfresco documentetion it's this -> http://docs.alfresco.com/4.0/index.jsp then it's useful but as mastro says
the official alfresco documentation is outdated and wrong
and i agree with mastro

Thank you for your contribution during these days I'll review the page to test all the implementations with Alfresco 4.

Hope that this could help you to understand the goal of each tool that Alfresco provides to the community  :wink:

I found your wiki very helpful too and a great help for understending Java-backed web scripting in Alfresco, but without a clear explanation of where the things and files have to be located; an updated explanation of AMPs packaging classpath, all the documentation and wiki are of little help..

For example one of my question is: have I to deploy every time my modifications with merging my AMP file in the .war for testing the code or can I package all java backed logic and file in a structured JAR and test through putting them in TOMCAT_HOME/webapps/alfresco/WEB-INF/lib only for the tests?

Thank you for your effort to update the wiki page, we really need this!  :wink:

namil
Champ in-the-making
Champ in-the-making
hi

I have imilar probem

My problem is how deploy a javaBacked Web script in JBOSS 5.1. I am using ALFRESCO 4.0
where I put exactely  the 3  files :      JavaBackedWebScriptExample.class
                                                        JavaBackedWebScriptExample.get.desc
                                                        JavaBackedWebScriptExample.get.html.ftl

Voila le code de ma class  JavaBackedWebScriptExample.class

package org.kugelmass.alfresco.webscripts;

import java.util.HashMap;
import java.util.Map;

import org.alfresco.service.cmr.repository.NodeService;
import org.apache.log4j.Logger;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptRequest;

public class JavaBackedWebScriptExample extends DeclarativeWebScript {
   
   // Get the log4j instance
   private final Logger logger = Logger.getLogger(this.getClass().getName());
   // NodeService bean, injected by spring using the public setter
   private NodeService nodeService;
   
   @Override
   protected Map<String, Object> executeImpl(WebScriptRequest req, Status status) {
      logger.debug("Hello!");
      // This method must return a map like this, from which you can fetch the values later
      // within the template
      Map<String, Object> model = new HashMap<String, Object>();
      model.put("test", "Hello!");
      return model;
   }

   public void setNodeService(NodeService nodeService) {
      this.nodeService = nodeService;
   }

   public NodeService getNodeService() {
      return nodeService;
   }

}

the content of the file  JavaBackedWebScriptExample.get.desc
<webscript>
   <shortname>Java baked web script template</shortname>
   <description>Java baked web script template</description>
   <url>/kugelmass/sample</url>
   <authentication>none</authentication>
   <format default="html">argument</format>
</webscript>

and the file JavaBackedWebScriptExample.get.json.ftl
{
   "message":   "${test}"
}


Calling WebScript : http://localhost:8080/alfresco/service/kugelmass/sample?alf_ticket=TICKET_dedf85a143868a5f4ac3903704...
respose satatus : HTTP/1.1 500 Erreur Interne de Servlet
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
   <head>
      <title>Web Script Status 500 - Internal Error</title>
      <link rel="stylesheet" href="/alfresco/css/webscripts.css" type="text/css" />
   </head>
   <body>
      <div>
         <table>
            <tr>
               <td><img src="/alfresco/images/logo/AlfrescoLogo32.png" alt="Alfresco" /></td>
               <td><span class="title">Web Script Status 500 - Internal Error</span></td>
            </tr>
         </table>
         <br/>
         <table>
            <tr><td>The Web Script <a href="%2Falfresco%2Fservice%2Fkugelmass%2Fsample%3Falf_ticket%3DTICKET_dedf85a143868a5f4ac3903704149103649c9209">/alfresco/service/kugelmass/sample</a> has responded with a status of 500 - Internal Error.</td></tr>
         </table>
         <br/>
         <table>
            <tr><td><b>500 Description:</b></td><td> An error inside the HTTP server which prevented it from fulfilling the request.</td></tr>
            <tr><td> </td></tr>
            <tr><td><b>Message:</b></td><td>05050005 Wrapped Exception (with status template): 05050204 Erreur lors du traitement du modèle 'Expression test is undefined on line 1, column 7 in org/kugelmass/alfresco/webscript/JavaBackedWebScriptExample.get.html.ftl.'. Veuillez contacter votre administrateur système.</td></tr>
            <tr><td></td><td> </td></tr>
   <tr><td><b>Exception:</b></td><td>freemarker.core.InvalidReferenceException - Expression test is undefined on line 1, column 7 in org/kugelmass/alfresco/webscript/JavaBackedWebScriptExample.get.html.ftl.</td></tr>
   <tr><td></td><td> </td></tr>
         <tr><td></td><td>freemarker.core.TemplateObject.assertNonNull(TemplateObject.java:125)</td></tr>
         <tr><td></td><td>freemarker.core.Expression.getStringValue(Expression.java:118)</td></tr>
         <tr><td></td><td>freemarker.core.Expression.getStringValue(Expression.java:93)</td></tr>
         <tr><td></td><td>freemarker.core.DollarVariable.accept(DollarVariable.java:76)</td></tr>
         <tr><td></td><td>freemarker.core.Environment.visit(Environment.java:221)</td></tr>
         <tr><td></td><td>freemarker.core.MixedContent.accept(MixedContent.java:92)</td></tr>
         <tr><td></td><td>freemarker.core.Environment.visit(Environment.java:221)</td></tr>
         <tr><td></td><td>freemarker.core.Environment.process(Environment.java:199)</td></tr>
         <tr><td></td><td>org.alfresco.repo.template.FreeMarkerProcessor.process(FreeMarkerProcessor.java:202)</td></tr>
         <tr><td></td><td>org.springframework.extensions.webscripts.AbstractWebScript.renderTemplate(AbstractWebScript.java:800)</td></tr>
         <tr><td></td><td>org.springframework.extensions.webscripts.DeclarativeWebScript.renderFormatTemplate(DeclarativeWebScript.java:267)</td></tr>
         <tr><td></td><td>org.springframework.extensions.webscripts.DeclarativeWebScript.execute(DeclarativeWebScript.java:147)</td></tr>
         <tr><td></td><td>org.alfresco.repo.web.scripts.RepositoryContainer.transactionedExecute(RepositoryContainer.java:348)</td></tr>
         <tr><td></td><td>org.alfresco.repo.web.scripts.RepositoryContainer.transactionedExecuteAs(RepositoryContainer.java:500)</td></tr>
         <tr><td></td><td>org.alfresco.repo.web.scripts.RepositoryContainer.executeScript(RepositoryContainer.java:275)</td></tr>
         <tr><td></td><td>org.springframework.extensions.webscripts.AbstractRuntime.executeScript(AbstractRuntime.java:372)</td></tr>
         <tr><td></td><td>org.springframework.extensions.webscripts.AbstractRuntime.executeScript(AbstractRuntime.java:209)</td></tr>
         <tr><td></td><td>org.springframework.extensions.webscripts.servlet.WebScriptServlet.service(WebScriptServlet.java:118)</td></tr>
         <tr><td></td><td>javax.servlet.http.HttpServlet.service(HttpServlet.java:717)</td></tr>
         <tr><td></td><td>org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)</td></tr>
         <tr><td></td><td>org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)</td></tr>
         <tr><td></td><td>org.alfresco.web.app.servlet.GlobalLocalizationFilter.doFilter(GlobalLocalizationFilter.java:58)</td></tr>
         <tr><td></td><td>org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)</td></tr>
         <tr><td></td><td>org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)</td></tr>
         <tr><td></td><td>org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)</td></tr>
         <tr><td></td><td>org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)</td></tr>
         <tr><td></td><td>org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)</td></tr>
         <tr><td></td><td>org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)</td></tr>
         <tr><td></td><td>org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)</td></tr>
         <tr><td></td><td>org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)</td></tr>
         <tr><td></td><td>org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433)</td></tr>
         <tr><td></td><td>org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)</td></tr>
         <tr><td></td><td>org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)</td></tr>
         <tr><td></td><td>org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)</td></tr>
         <tr><td></td><td>org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)</td></tr>
         <tr><td></td><td>org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)</td></tr>
         <tr><td></td><td>org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)</td></tr>
         <tr><td></td><td>org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)</td></tr>
         <tr><td></td><td>org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)</td></tr>
         <tr><td></td><td>org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)</td></tr>
         <tr><td></td><td>org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:598)</td></tr>
         <tr><td></td><td>org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)</td></tr>
         <tr><td></td><td>java.lang.Thread.run(Thread.java:662)</td></tr>
   <tr><td></td><td> </td></tr>
   <tr><td><b>Exception:</b></td><td>org.alfresco.service.cmr.repository.TemplateException - 05050204 Erreur lors du traitement du modèle 'Expression test is undefined on line 1, column 7 in org/kugelmass/alfresco/webscript/JavaBackedWebScriptExample.get.html.ftl.'. Veuillez contacter votre administrateur système.</td></tr>
   <tr><td></td><td> </td></tr>
      <tr><td></td><td>org.alfresco.repo.template.FreeMarkerProcessor.process(FreeMarkerProcessor.java:206)</td></tr>
   <tr><td></td><td> </td></tr>
   <tr><td><b>Exception:</b></td><td>org.springframework.extensions.webscripts.WebScriptException - 05050005 Wrapped Exception (with status template): 05050204 Erreur lors du traitement du modèle 'Expression test is undefined on line 1, column 7 in org/kugelmass/alfresco/webscript/JavaBackedWebScriptExample.get.html.ftl.'. Veuillez contacter votre administrateur système.</td></tr>
   <tr><td></td><td> </td></tr>
      <tr><td></td><td>org.springframework.extensions.webscripts.AbstractWebScript.createStatusException(AbstractWebScript.java:970)</td></tr>
   <tr><td></td><td> </td></tr>
            <tr><td><b>Server</b>:</td><td>Community v4.0.0 (4003) schema 5 025</td></tr>
            <tr><td><b>Time</b>:</td><td>5 juin 2012 17:02:40</td></tr>
            <tr><td></td><td> </td></tr>
            <tr><td><b>Diagnostics</b>:</td><td><a href="/alfresco/service/script/org/kugelmass/alfresco/webscript/JavaBackedWebScriptExample.get">Inspect Web Script (org/kugelmass/alfresco/webscript/JavaBackedWebScriptExample.get)</a></td></tr>
         </table>
      </div>
   </body>
</html>



When I call the web script the requeste do not reach the controler  JavaBackedWebScriptExample.class
When Iconnecte to http://localhost:8080/alfresco/service/ My webscript is avaible in the list off webscripts

/index/family/{family}
/index/lifecycle/{lifecycle}
/index/package/{package}
/index/package/{package}/doc
/index/uri/{uri}
/installer
[b]/kugelmass/sample[/b]
/mimetypes
/modules/deploy
/office/callexternal
/office/docActions
/office/documentDetails
/office/getUsers
/office/myAlfresco

namil
Champ in-the-making
Champ in-the-making
I think that when I call the web scripts Iget the respense without passing by the controller ( the javabacked webscripts)

namil
Champ in-the-making
Champ in-the-making
Can you help me

isastre
Champ in-the-making
Champ in-the-making
I have the same problem. I don't know why but my java class is not being executed and I don't know why.

I have tried:

Troubleshooting

I am getting: Cannot locate template processor for template …

If you are extending the AbstractWebScript class then it is most likely that your bean definition file is either in the wrong place, or has the wrong content. Double check this by visiting the following link http://localhost:8080/share/page/script/org/alfresco/module/demoscripts/simple.get (for the first example) and look at the Implementation line. If the implementation is not the class you created, but is the default class (DeclaritiveWebScript), then your class is not being loaded properly. Stop Tomcat and remove your class. Then start tomcat again. If you do not see any class loading errors then that means your bean definition file is not correct. Move it to the correct location and restart tomcat until you are getting a class loading error. Then move your java class file (or jar) into the correct place and restart tomcat again. Visit the page above to make sure the implementation is correct.

I get the class loading error, so I have put my .jar file in the /alfresco/tomcat/webapps/alfresco/WEB-INF/lib folder and I have restarted tomcat.

I still get: "org.springframework.extensions.webscripts.DeclarativeWebScript" in Implementation instead of the SimpleWebScript class.
Script Properties
Id:   org/springframework/extensions/webscripts/org/alfresco/demo/simple.get
Short Name:   The World's Simplest Webscript
Description:   Hands back a little bit of JSON
Authentication:   none
Transaction:   none
Method:   GET
URL Template:   /demo/simple
Format Style:   argument
Default Format:   [undefined]
Negotiated Formats:   [undefined]
Implementation:   class org.springframework.extensions.webscripts.DeclarativeWebScript
Extensions:   [undefined]

Store: classpath:alfresco/site-webscripts

[No implementation files]

Store: classpath:surf/webscripts

[No implementation files]

Store: classpath:webscripts

File: org/springframework/extensions/webscripts/org/alfresco/demo/simple.get.desc.xml

<webscript>
  <shortname>The World's Simplest Webscript</shortname>
  <description>Hands back a little bit of JSON</description>
  <url>/demo/simple</url>
  <authentication>none</authentication>
  <format default="">argument</format>
  <family>Alfresco Java-Backed WebScripts Demo</family>
</webscript>

Can somebody help?

abarisone
Star Contributor
Star Contributor
Hi isastre,
I thinl you're missing to register your webscript to Spring configuration.
In the same way you can register new models, you have to add a bean definition to the Alfresco context:

<bean id="webscript.getTypes.get" (you can change this as you like)
          class="org.kugelmass.alfresco.webscripts.JavaBackedWebScriptExample"
          parent="webscript">
          <property name="dictionaryService" ref="DictionaryService"/> (if needed)
</bean>
In this way your code will be correctly loaded by Spring.

Hope this helps.
Regards,
Andrea
Getting started

Tags


Find what you came for

We want to make your experience in Hyland Connect as valuable as possible, so we put together some helpful links.