Tuesday, January 27, 2009

Groovy Scripting for Alfresco - Alf Hack # 1

This is the first post of my Alfresco Hacks series, showing some very useful tricks for the development with Alfresco. After working with Alfresco since beginning of 2007 with Version 1.4, I feel now well prepared for sharing some code. I do appreciate any feedback, feel free to comment and add suggestions. I'm tired of doing the somewhat lengthy process of editing java source, compiling, alfresco.war building, deploying to tomcat and finally starting tomcat. Just to try something out, this is too tedious. Therefore I gave the Groovy Server from http://iterative.com/GroovyServer.tar.gz a try. It will give you access to a Groovy shell using:
telnet localhost 6789
The simple steps I did:
  • build the groovyserver.jar
  • copy groovyserver.jar, groovy-all*.jar, jline*.jar to WEB-INF/lib/
  • add this to a spring context file grooyserver-context.xml in the extensions directory:
<bean id="groovyService" abstract="true" method="initialize" method="destroy">
<property name="bindings">
<map>
<entry key="ServiceRegistry" ref="ServiceRegistry">
</map>
</property>
</bean>

<bean id="groovyShellService" class="com.iterative.groovy.service.GroovyShellService" parent="groovyService">
<property name="socket" value="6789">
<property name="launchAtStart" value="true">
</bean>
After starting Alfresco up, the Groovy shell can be access with a telnet client connection to port 6789 on the Alfresco server:
lothar@lothar-laptop:~$ telnet localhost 6789
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Groovy Shell (1.6-RC-2, JVM: 1.6.0_11)
Type 'go' to execute statements; Type 'help' for more information.
groovy>
As an example, searching for the term "alfresco":
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
workspaceStoreRef = new StoreRef("workspace://SpacesStore");
ServiceRegistry.getAuthenticationService().authenticate("admin", "admin".toCharArray());
retryTXService = ServiceRegistry.getRetryingTransactionHelper();
def doWork() {
results = ServiceRegistry.getSearchService().query(workspaceStoreRef, "lucene", "alfresco");
for(r in results) { out.println(r.document); }
}
def sow = [ execute: { doWork() } ] as RetryingTransactionCallback<Void>;
retryTXService.doInTransaction(sow);
go
Looks simple? Not at the first glance, but it is easy. The real work has to be put into the doWork() function lines 6 to 9. The rest can stay the same, it is just plumbing code. Conclusion: Now the Alfresco API is just a very small step away. Would like to try the VersionService? Just do a ServiceRegistry.getVersionService()..... and fire up your Groovy script. Other links to Alfresco and Groovy: WebScripts with Groovy: http://gradecak.blogspot.com/2008/04/alfresco-webscripts-with-groovy.html Alfresco with Grails: http://forge.alfresco.com/projects/minigrails/

2 comments:

Anonymous said...

Nice! I'd planned on using the same technique (which I first saw described at http://69.89.31.118/~iterativ/wordpress/2007/05/14/embedding-a-groovy-console-in-a-java-server-application/) but it looks like you saved me the effort!

My next thoughts were to do this via a "command line" Web Script ala Goosh (http://goosh.org/). This would give a cleaner authentication mechanism (since auth would be handled by the Web Script framework), as well as the ability to inject any useful root scope objects (such as the ServiceRegistry).

Lothar Märkle said...

Yes, the authen stuff is very noisy above, and should be handled outside. There are also other AJAX based terminals available like AnyTerm or ShellInABox.