Blogroll

The New Domino Admin

A great source of information for Lotus Domino administrators

ecmarchitect.com

Jeff Potts' excellent ECM/Portal blog

Jared Ottley

Lots of very useful Alfresco articles

Looking for web hosting?  I have been using DreamHost for years and have found them to be reliable, inexpensive and very good at what they do!  Click below to sign up, use promo code 'unorganized' to get a free domain registration and 10 bucks off your first year of hosting!

 

dreamhostBadge

Home Software and Tech Software Development Calling Web Services from the Alfresco Javascript API
Calling Web Services from the Alfresco Javascript API PDF Print E-mail
Written by Nathan McMinn   
Thursday, 12 August 2010 19:10

One of my favorite features of Alfresco is the Javascript API.  The Javascript API allows a developer to interact with the repostitory via server-side scripts.  These scripts can be mapped to a URL and tied to a Freemarker Template to form a Web Script, or can be developed as repository scripts that can be run on a schedule or in response to a repository action via a content rule.  It's powerful stuff, but not without limitations.  The API uses the Rhino Javascript engine for Java, but has a few restrictions imposed.  Normally, Rhino allows you to script just about any Java object on the classpath, including the entire Java Core API.  In Alfresco this is disabled for security purposes.  Instead, a pre-defined set of repository objects is made available.  While this set of objects can handle just about anything you might want to do with the repository, it lacks facilities for interacting with external resources such as JDBC connections or external web services.  Thankfully the API is extensible and allows you to add your own custom script APIs via Spring.

 

I am currently working on a project that requires a few web service calls to be made in response to repository actions.  In particular, I want to use Tropo.com's web API to create SMS and voice notifications about some actions on specific documents (for example when a new PDF is added to a space).  I've already created my Tropo scripts and mapped them to a URL, so all I need to do now is execute a simple GET request and pass a variable or two when a document is modified.  Unfortunately for me, Alfresco's Javascript API doesn't include any type of HTTP request object, and the core Java API is inaccessible.  When I was researching the best way to hit a URL from Javascript in Rhino, I came across this article on IBM's DeveloperWorks site in which the authors discuss a Java implementation of the XMLHttpRequest object that works with Rhino.  With a little work, I was able to modify their XMLHttpRequest object to work with Alfresco's Javascript API.  You can download the .jar file here (source included, of course).  There are two classes worth noting.  The first, from the IBM article, is xmlhttp.XMLHttpRequest.  It supports both GET and POST operations, and aims to be complete implementation of the same XMLHttpRequest object available to the browser.  It supports asynchronous calls, but I don't think this will work properly in Rhino.  The second class, org.um.alfresco.SimpleHttpConnection is a dead simple little wrapper around java.net.HttpURLConnection.  It only supports GET operations, with a single method, getContent(String URL), that returns the content of the URL as a String.

 

To use either class, you first have to configure Alfresco to make use of it.  Take the downloaded .jar and put it on your classpath.  I dropped it in <alfresco_home>/tomcat/webapps/alfresco/WEB-INF/lib.  Next, open <alfresco_home/tomcat/webapps/alfresco/WEB-INF/classes/alfresco/script-services-context.xml and add the following bean entries:

 

1
2
3
4
5
6
7
8
9
10
    <bean id="httpUtilsScript" parent="baseJavaScriptExtension" 
class
="org.um.alfresco.SimpleHttpConnection">
<property name="extensionName"> <value>SimpleHttpConnection</value> </property> </bean> <bean id="e4xutilsScript" parent="baseJavaScriptExtension"
class
="xmlhttp.XMLHttpRequest">
<property name="extensionName"> <value>XMLHttpRequest</value> </property> </bean>

 

This snippet of XML creates two new beans and makes them available to the Alfresco Javascript API.  Notice that each bean inherits from baseJavaScriptExtension.  This allows each one to automatically register with the Alfresco ScriptService framework.  Each bean is also given an extensionName value, which is the name by which the object will be referenced in your scripts.  Much like you can call people.createPerson to use the built-in "people" object in the Alfresco Javascript API, you can now call any of the methods of the XMLHttpRequest or SimpleHttpConnection objects.  The object is instantiated when the server starts, so there is no need to create a new instance.  Here's a quickie script that shows how to use both objects:

 

wstest.js (wstest.get.js if used in the Web Script example)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var simplehttpresult = "no result";
var xmlhttpresult = "no result";
var error = "no error";
 
// try calling the web script a couple different ways
try {
 
	//call the web service using SimpleHttpConnection
	simplehttpresult = SimpleHttpConnection
.getContentAsString("http://your.server.com/path/to/service");
  //call the web service synchronously via XMLHttpRequest XMLHttpRequest
.open("GET", "http://your.server.com/path/to/service",
 false, "user", "pass");
XMLHttpRequest.send(""); xmlhttpresult = XMLHttpRequest.getResponseText(); XMLHttpRequest.close();   }catch(ex){error = String(ex)}   //uncomment to add to Freemarker model (if run as Web Script) //model.simplehttpresult = simplehttpresult; //model.xmlhttpresult = xmlhttpresult //model.error = error;

 

If all you want to do is hit a URL in a content rule, just create a script in /Company Home/Data Dictionary/Scripts and call whatever RESTful web service you need as shown above.  Then, go to your space and create a content rule which executes the script.  Pretty easy, right?  You can also use the same technique to create a Web Script that invokes web services.  Just create the appropriate descriptor and Freemarker template and drop them in /Company Home/Data Dictionary/Web Scripts Extensions along with your script.  Here is a simple example that works with the script above to hit a URL:

 

wstest.get.desc.xml

1
2
3
4
5
6
<webscript>
	<shortname>wstest</shortname>
	<description>web service call test</description>
	<url>/org/um/wstest</url>
	<authentication>user</authentication>
</webscript>

 

wstest.html.ftl

1
2
3
4
5
SimpleHttpConnection web service call result: ${simplehttpresult}
<br/><br/>
XMLHttpRequest web service call result: ${xmlhttpresult}
<br/><br/>
errors: ${error}

 

This example will create a web script that is accessible at http://<server>:<port>/alfresco/service/org/um/wstest.  The example script will retrieve content from the URL provided in the script and display the results in the browser.  Hopefully others will find this useful, the ability to call a web service from Alfresco's Javascript API was a missing piece of my particular puzzle.

 

Happy coding!

http://your.server.com/path/to/script
Last Updated on Friday, 13 August 2010 12:13
 

Comments  

 
#27 matthew 2012-03-21 15:37
Nvm - resolved it - needed to restart browser for some reason.
 
 
#26 matthew 2012-03-21 15:18
XMLHttpRequest is throwing the error:
'JavaException: java.lang.IllegalStateExc eption: already open' any ideas?
 
 
#25 matthew 2012-03-21 14:36
THANK YOU - 2 days of working with alfresco webscripts to make a silly external request. Alfresco is silly when it comes to easy tasks.
 
 
#24 NazarKalp 2012-02-27 14:26
I'd like to give thanks to you for your website. You have got a whole lot of interesting stuff for that reason the site is worth your time. I'm a college student in Cali and I have got an vital school assignment scheduled this week. I'm just tangled as well as currently have writers-block currently as I am studying. Would just like someone to guide
me revise the cost-free article I stumbled upon on-line the origin and cause of aids essay. That report fits my personal prerequisites yet is composed in an unsatisfactory fashion and there are sentence structure mistakes. Do you consider I ought to proceed? I am simply just in need of aid, and so any idea could be good.
 
 
#23 Joe Donnelly 2012-01-30 11:54
Hi,

This is just want I am looking to do and thank you for posting it. I do have have a question, how do you either access java script API on the share side or how do you add the similar setup on the alfresco share side?
 
 
#22 tee 2011-11-18 09:12
Thanks a lot!! This is what I've been looking for a long time.
 
 
#21 2011-10-07 05:49
Thank for the explanation, It's good to have people like you.
 
 
#20 2011-08-25 09:18
Thanks Nathan.

Nice howto. Was banging my head thinking how to post a simple message to my http listener. Your article solved my problem.
Thanks
Venkat
 
 
#19 2011-07-05 02:20
Hi Nathan,

let me say thank you for saving my week. This functionality was exactly what I needed and after a bit of fiddling 'round it work perfectly.

Thanks a lot for this great resource.

Best regards,

ThaGoob
 
 
#18 2011-07-01 10:21
Hi Andrew,

Did you add the bean definitions to script-services-context.xml? That's the most likely cause.
 
RSS Feed Icon

About Me

 

My profile picture

 

My name is Nathan McMinn.  I'm a software engineer, beer geek, wannabe adventurer and genuinely curious guy.  Find me on Facebook, Linkedin or Twitter

Latest Comments