Nate McMinn has a brief wrap up of the Alfresco developers convention.  I was unable to attend and it sounds like I missed a lot of interesting news.  I was excited to here:

One upcoming project that was discussed at DevCon is putting together a third-party components catalog for Alfresco.  Right now there is nothing like this available.  Alfresco community projects are scattered all over the place.  Some are in Alfresco Forge, some are on Google Code, still others are on developers' blogs (mine included).  I'm sure I'm forgetting a few locations, but you get the idea.  Rolling all of this up in one queryable repository would be a fantastic addition to the Alfresco community.

I wonder how this will be deployed and who will maintain it.  The wiki idea for documentation seems to be barely moving along.

JMX rocks.  When configuring a server it is a boon to developers.  Especially when combined with the Alfresco subsystem architecture.  You can interate on changes to the LDAP sync without having to restart the server.  JMX also gives savvy system administrators a way to manage and monitor what’s going on within the repository.

If you’re still unfamiliar with the basics of JMX, especially within the context of Alfresco, Jarred Ottley over at Alfresco has written a number of excellent tutorials.  I’ve added some additional articles and come up with the list below.

Some links:

With the basics out of the way it is often interesting to create your own MBean that can report custom statistics or expose custom methods.  This tutorial creates a new MBean that shows the number of Asynchronous jobs being run.  Alfresco exports beans using standard Spring practices.  This makes keeps everything well documented.  The list of things to create is small:

  • Context file to register new MBean
  • Annotated Java class

Context File

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="whySlow" class="com.zia.jmx.WhySlow"/>
<bean id="ziaExporter"
class="org.springframework.jmx.export.MBeanExporter">
<property name="assembler" ref="assembler"/>
<property name="beans">
<map>
<entry key="Zia:name=WhySlow" value-ref="whySlow"/>
</map>
</property>
</bean>
<bean id="jmxAttributeSource"
class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
<!-- will create management interface using annotation metadata -->
<bean id="assembler"
class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>
</beans>

Java Class

  @ManagedResource
public class WhySlow {
@ManagedAttribute( description = "Asynchronous actions left to run" )
public long getAsyncActions() {
AsynchronousActionExecutionQueueImpl aaeq = ( AsynchronousActionExecutionQueueImpl ) AlfUtil.getSpringBean( "defaultAsynchronousActionExecutionQueue" );
long ret = -1;
try {
Class<?> c = aaeq.getClass();
Field[] props = c.getDeclaredFields();
Field tpeField = c.getDeclaredField( "threadPoolExecutor" );
tpeField.setAccessible( true );
ThreadPoolExecutor tpe = ( ThreadPoolExecutor ) tpeField.get( aaeq );
ret = tpe.getTaskCount() - tpe.getCompletedTaskCount();
} catch( NoSuchFieldException nsfe ) {
nsfe.printStackTrace();
} catch( IllegalArgumentException e ) {
e.printStackTrace();
} catch( IllegalAccessException e ) {
e.printStackTrace();
}
return ret;
}
}

The annotations are important for documentation in the console.  There are some reflection shenanigans that allows access to private fields.  Your implementation will not need much of this code, except for the annotations.

When this code is deployed the WhySlow mbean will appear at the top level, next to Alfresco node.  This is controlled by the key of the map passed into the “beans” property(Zia:name=WhySlow) and is explained in the Spring docs.

Wrap up

A bean created under JMX tends to keep the separation of concerns better than many of the alternatives.  We have created “consoles” in webscripts, but it seems to be difficult to train the sys admins to go to multiple places for configuration.  Once the repository is started it is consistent to point users at JMX for all administration and reporting.

 

 

Zia Consulting develops in Eclipse using a setup different than described by Alfresco.  We run an embedded version of Jetty with the Alfresco default WARs.  At runtime we mix in changes using extra classpath entries and web overlays.  This has many benefits: most importantly that we develop functionality without having to restart the repository.  When there is a reason to restart the server we make efforts to fix the problem through programming or configuration.

Share has caches that make the webscripts and surf run faster.  These caches have documentation on how to turn them off but this documentation changes with every release of share or surf.  This is difficult to keep up with.

If you're interested in the documented process I have a list of articles to read:

Old Surf intro - refreshing the Surf page cache.  I don't believe this is needed in the most recent versions of share.

Official wiki documentation - For Alfresco 3.0 ➔ 3.3, before Surf joined the Spring project.

Official developer guide -  The section for debugging didn’t get finished.  Likely because they moved over to Spring.

I’m sure there are more.  Feel free to add them to the comments.

We have given up on following the documentation and developed a custom Web Script that invalidates these caches whenever a source file is changed.  The code for this Web Script is from the service index refresh that is part of “org.springframework.extensions.webscripts.bean.IndexUpdate”.  We paid particular attention to the reset method of “org.springframework.extensions.webscripts.AbstractRuntimeContainer”.  The reset method gets run when you goto http://localhost/share/service/index and click the reset button.  The important code is trivial:

  /* public void reset(){ ...*/
scriptProcessorRegistry.reset();
templateProcessorRegistry.reset();
getRegistry().reset();
configService.reset();
/* } */

Running all four of these resets takes a couple seconds and is impractical to do after every save.  Taking just the script and template reset and putting them in a Web Script keeps it pretty lean.  Running time drops from a 2 - 3 seconds to a few hundred ms.  It is fast enough that the refresh will happen before you can cmd + tab to your web browser and refresh.

We created a refresh Web Script using the above code and then setup an Eclipse builder to run when the source is updated.  To do this you need to create a few things.

  • Refresh Web Script.  It’s best to use “none” authentication.
  • Ant script that will call the new Web Script.  Shown below.
  • In Eclipse turn the directory containing javascript and freemarker templates (the config directory if your projects look like exploded amp files) into a source directory so it triggers the auto build.
  • Create a builder according to this tutorial with one change:
    • In step #11 they recommend NOTcreating an auto build.  Ignore this direction - auto building is really handy for our purposes.  It doesn’t cause performance issues, so turn it on and configure it to run “run-refresh-webscript”.

The ant file that we use:

<?xml version="1.0" encoding="UTF-8"?>
<project name="project" default="run-refresh-webscript">
<target name="run-refresh-webscript">
<get src="http://localhost:8080/share/service/zia/util/refresh"
dest="refresh-results.dat" />
</target>
</project>

Update:

I found this article by Kevin Roast that has some great tips on Share development.  The “mode” selection is of great interest.

Copyright © 2015 boulder dan
Distributed By Blogger Template | Created By Dicky Bust