Skip to content

RAD! Alfresco SDK 3.0. Upgrade and enjoy!

Why upgrade SDK 3.0?

  • Support for RAD (Rapid Application Development) and TDD (Test Driven Development) via HotswapAgent and JRebel
  • Simpler SDK layout
  • Jar packaging by default
  • Support for Alfresco version 4.2 to 5.2
  • Integration testing webscripts

TL;DR

  • Update your pom.xml
  • Remove all SDK modules, except for your jar/amp project modules.
  • Update your Integration tests.
  • Add integration-tests project module, and copy src directory.
  • Re-organize your Integration tests into the integration-tests project module, and rename to *IT.java.
  • Search and replace default project name with your project name where exists.

Upgrade Notes

The instructions provided in this article is based on an SDK upgrade from Alfresco SDK 2.1.1 to Alfresco SDK 3.0

Vanilla for Reference

To get started with the upgrade, we’ll need a vanilla version of the 3.0 SDK project to get some of the new files and configurations that we’ll need.

Do this by using one of the following maven commands to generate an all in one project:

mvn archetype:generate -Dfilter=org.alfresco:
view raw gistfile1.txt hosted with ❤ by GitHub
If you don’t see the option for SDK 3.0, then use this command as per Ohej’s note
mvn archetype:generate -DarchetypeGroupId=org.alfresco.maven.archetype -DarchetypeArtifactId=alfresco-allinone-archetype -DarchetypeVersion=3.0.0 -DinteractiveMode=false -DgroupId=com.acme.alfresco -DartifactId=my-aio-project

Update our poms

First pom.xml to update would be the main pom.xml of our project.

In this pom, we will remove the alfresco-sdk-parent. With SDK 3.0, we no longer need a parent project.

Main pom.xml

<parent>
<groupId>org.alfresco.maven</groupId>
<artifactId>alfresco-sdk-parent</artifactId>
<version>2.1.1</version>
</parent>
view raw alfresco-sdk-pom.xml hosted with ❤ by GitHub

Update the properties in this pom.xml with the properties from our vanilla project

<!-- Alfresco Maven Plugin version to use -->
<alfresco.sdk.version>3.0.0</alfresco.sdk.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Alfresco Data directory, which will contain: Content Store (i.e. the files we upload) Database (i.e. the metadata for the uploaded files) Search index (i.e. the indexed content and metadata) Configured in alfresco-global.properties with the
'dir.root' property. -->
<alfresco.data.location>${session.executionRootDirectory}/alf_data_dev</alfresco.data.location>
<!-- Duplicated with alfresco.solrHome in the plugin, we need them out here to do filtering -->
<solr.home>${alfresco.data.location}/solr</solr.home>
<solr.model.dir>${solr.home}/alfrescoModels</solr.model.dir>
<solr.content.dir>${solr.home}/index</solr.content.dir>
<!-- Properties used in dependency declarations, you don't need to change these -->
<alfresco.groupId>org.alfresco</alfresco.groupId>
<!-- Alfresco Platform and Share webapp versions, these are the original Alfresco webapps that will be customized and then deployed and run by the tomcat maven plugin when executing for example $ mvn clean install alfresco:run -->
<alfresco.platform.version>5.0.d</alfresco.platform.version>
<alfresco.share.version>5.0.d</alfresco.share.version>
<!-- Default is to run with a Community edition, change to 'enterprise' if using Enterprise edition -->
<maven.alfresco.edition>community</maven.alfresco.edition>
<!-- Alfresco Surf version, if you change Share version you might need to change Surf version -->
<alfresco.surf.version>6.11</alfresco.surf.version>
<!-- JRebel Hot reloading of classpath stuff and web resource stuff -->
<jrebel.version>1.1.6</jrebel.version>
<!-- Environment to use, Alfresco Maven Plugin will copy alfresco-global-*.properties files from this directory, such as src/test/properties/local -->
<env>local</env>
<!-- Compile with Java 7, default is 5 -->
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<share.client.url>http://localhost:8080/share</share.client.url

Instead of Java 7 source/target, I prefer Java 8 targets.

Next we update the dependencyManagement section with the elements from the vanilla template

<dependencyManagement>
<dependencies>
<!-- This will import the dependencyManagement for all artifacts in the selected Alfresco platform.
NOTE: You still need to define dependencies in your POM, but you can omit version as
it's enforced by this dependencyManagement.
NOTE: It defaults to the latest version this SDK pom has been tested with,
but alfresco version can/should be overridden in your project's pom
-->
<dependency>
<groupId>${alfresco.groupId}</groupId>
<artifactId>alfresco-platform-distribution</artifactId>
<version>${alfresco.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Redefine the following Share dependencies as they have different version numbers than platform.
They are defined in alfresco-platform-distribution... -->
<dependency>
<groupId>${alfresco.groupId}</groupId>
<artifactId>share</artifactId>
<version>${alfresco.share.version}</version>
<type>war</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${alfresco.groupId}</groupId>
<artifactId>share</artifactId>
<version>${alfresco.share.version}</version>
<classifier>classes</classifier>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${alfresco.groupId}</groupId>
<artifactId>alfresco-web-framework-commons</artifactId>
<version>${alfresco.share.version}</version>
<classifier>classes</classifier>
<scope>provided</scope>
</dependency>
<!-- Redefine the following surf dependencies as they have no resolvable version in the
alfresco-platform-distribution artifact -->
<dependency>
<groupId>org.alfresco.surf</groupId>
<artifactId>spring-surf</artifactId>
<version>${alfresco.surf.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.alfresco.surf</groupId>
<artifactId>spring-surf-api</artifactId>
<version>${alfresco.surf.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>
view raw pom.xml hosted with ❤ by GitHub

In the build section, we will update the pluginManagement, and the plugins section.

<pluginManagement>
<plugins>
<!--
Build an AMP if 3rd party libs are needed by the extensions
JARs are the default artifact produced in your modules, if you want to build an amp for each module
you have to enable this plugin and inspect the src/main/assembly.xml file if you want to customize
the layout of your AMP. The end result is that Maven will produce both a JAR file and an AMP with your
module.
-->
<!--
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>build-amp-file</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptor>src/main/assembly/amp.xml</descriptor>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.alfresco.maven.plugin</groupId>
<artifactId>alfresco-maven-plugin</artifactId>
<version>${alfresco.sdk.version}</version>
</dependency>
</dependencies>
</plugin>
-->
<!-- Filter resources in any sub-project with this config -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.1</version>
<configuration>
<encoding>UTF-8</encoding>
<nonFilteredFileExtensions> <!-- jpg, jpeg, gif, bmp and png are added automatically -->
<nonFilteredFileExtension>ftl</nonFilteredFileExtension>
<nonFilteredFileExtension>acp</nonFilteredFileExtension>
<nonFilteredFileExtension>svg</nonFilteredFileExtension>
<nonFilteredFileExtension>pdf</nonFilteredFileExtension>
<nonFilteredFileExtension>doc</nonFilteredFileExtension>
<nonFilteredFileExtension>docx</nonFilteredFileExtension>
<nonFilteredFileExtension>xls</nonFilteredFileExtension>
<nonFilteredFileExtension>xlsx</nonFilteredFileExtension>
<nonFilteredFileExtension>ppt</nonFilteredFileExtension>
<nonFilteredFileExtension>pptx</nonFilteredFileExtension>
<nonFilteredFileExtension>bin</nonFilteredFileExtension>
<nonFilteredFileExtension>lic</nonFilteredFileExtension>
<nonFilteredFileExtension>swf</nonFilteredFileExtension>
<nonFilteredFileExtension>zip</nonFilteredFileExtension>
<nonFilteredFileExtension>msg</nonFilteredFileExtension>
<nonFilteredFileExtension>jar</nonFilteredFileExtension>
<nonFilteredFileExtension>ttf</nonFilteredFileExtension>
<nonFilteredFileExtension>eot</nonFilteredFileExtension>
<nonFilteredFileExtension>woff</nonFilteredFileExtension>
<nonFilteredFileExtension>woff2</nonFilteredFileExtension>
<nonFilteredFileExtension>css</nonFilteredFileExtension>
<nonFilteredFileExtension>ico</nonFilteredFileExtension>
<nonFilteredFileExtension>psd</nonFilteredFileExtension>
<nonFilteredFileExtension>js</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
</plugins>
</pluginManagement>
view raw pom.xml hosted with ❤ by GitHub

For the plugins section, copy and paste the section from our vanilla pom.xml, and update the moduleDependency to include your project’s modules. Your repository module will be under the <platformModules> section, and your Share modules will be under the <shareModules> section.

<plugins>
<!-- Filter the test resource files in the AIO parent project, and do property substitutions.
We need this config so this is done before the Alfresco Maven Plugin 'run' is executed. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.1</version>
<inherited>false</inherited>
<!-- Run only for the AIO parent Project -->
<executions>
<execution>
<id>copy-and-filter-test-resources</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.testOutputDirectory}</outputDirectory>
<resources>
<testResource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
</testResource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<!--
The Alfresco Maven Plugin contains all the logic to run the extension
in an embedded Tomcat with the H2 database.
-->
<plugin>
<groupId>org.alfresco.maven.plugin</groupId>
<artifactId>alfresco-maven-plugin</artifactId>
<version>${alfresco.sdk.version}</version>
<configuration>
<!-- We need the flat file H2 database to run the Repo -->
<enableH2>true</enableH2>
<!-- We always need the Platform/Repo webapp - alfresco.war -->
<enablePlatform>true</enablePlatform>
<!-- Enable Solr webapp so we can use search -->
<enableSolr>true</enableSolr>
<!-- We need Share webapp, so we got a UI for working with the Repo -->
<enableShare>true</enableShare>
<!-- Enable the REST API Explorer -->
<enableApiExplorer>true</enableApiExplorer>
<!--
JARs and AMPs that should be overlayed/applied to the Platform/Repository WAR
(i.e. alfresco.war)
-->
<platformModules>
<!-- Share Services will be ignored if you are on Platform earlier than 5.1 -->
<moduleDependency>
<groupId>${alfresco.groupId}</groupId>
<artifactId>alfresco-share-services</artifactId>
<version>${alfresco.share.version}</version>
<type>amp</type>
</moduleDependency>
<!-- Bring in custom Modules -->
<moduleDependency>
<groupId>${project.groupId}</groupId>
<artifactId>my-repository-module</artifactId>
<version>${project.version}</version>
</moduleDependency>
<!-- Bring in the integration tests -->
<moduleDependency>
<groupId>${project.groupId}</groupId>
<artifactId>integration-tests</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
</moduleDependency>
</platformModules>
<!--
JARs and AMPs that should be overlayed/applied to the Share WAR (i.e. share.war)
-->
<shareModules>
<!-- Bring in custom Modules -->
<moduleDependency>
<groupId>${project.groupId}</groupId>
<artifactId>my-shareui-module</artifactId>
<version>${project.version}</version>
</moduleDependency>
</shareModules>
</configuration>
</plugin>
<!-- Hot reloading with JRebel -->
<plugin>
<groupId>org.zeroturnaround</groupId>
<artifactId>jrebel-maven-plugin</artifactId>
<version>${jrebel.version}</version>
<executions>
<execution>
<id>generate-rebel-xml</id>
<phase>process-resources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- For more information about how to configure JRebel plugin see:
http://manuals.zeroturnaround.com/jrebel/standalone/maven.html#maven-rebel-xml -->
<classpath>
<fallback>all</fallback>
<resources>
<resource>
<directory>${project.build.outputDirectory}</directory>
<directory>${project.build.testOutputDirectory}</directory>
</resource>
</resources>
</classpath>
<!--
alwaysGenerate - default is false
If 'false' - rebel.xml is generated if timestamps of pom.xml and the current rebel.xml file are not equal.
If 'true' - rebel.xml will always be generated
-->
<alwaysGenerate>true</alwaysGenerate>
</configuration>
</plugin>
</plugins>
view raw share-plugin-pom.xml hosted with ❤ by GitHub

Add the resources section

<resources>
    <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
    </resource>
</resources>

We will then add the resources section that will provide access to the 3.0 SDK dependencies.

<repositories>
<repository>
<id>alfresco-public</id>
<url>https://artifacts.alfresco.com/nexus/content/groups/public</url>
</repository>
<repository>
<id>alfresco-public-snapshots</id>
<url>https://artifacts.alfresco.com/nexus/content/groups/public-snapshots</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy>
</snapshots>
</repository>
<!-- Alfresco Enterprise Edition Artifacts, put username/pwd for server in settings.xml -->
<repository>
<id>alfresco-private-repository</id>
<url>https://artifacts.alfresco.com/nexus/content/groups/private</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>alfresco-plugin-public</id>
<url>https://artifacts.alfresco.com/nexus/content/groups/public</url>
</pluginRepository>
<pluginRepository>
<id>alfresco-plugin-public-snapshots</id>
<url>https://artifacts.alfresco.com/nexus/content/groups/public-snapshots</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy>
</snapshots>
</pluginRepository>
</pluginRepositories>

Finally, for this pom.xml, we will remove the <profile> section, and update our <modules> section so that we remove the old SDK module dependencies, and add the new integration-tests module. The update will look like this:

<modules>
<module>my-repository-module</module>
<module>my-shareui-module</module>
<module>integration-tests</module>
<!-- These are no longer needed for the SDK 3.0
<module>repo</module>
<module>solr-config</module>
<module>share</module>
<module>runner</module>
-->
</modules>
view raw modules-pom.xml hosted with ❤ by GitHub

pom.xml for your repository projects

If you’re changing your packaging type, like I did from amp to jar, then, update your packaging type here

    <packaging>jar</packaging>

Remove the following dependency, as it’s no longer needed

       <dependency>
            <groupId>${alfresco.groupId}</groupId>
            <artifactId>alfresco-repository</artifactId>
        </dependency>

Remove the profiles section

<profiles>
<!--
Brings in the extra Enterprise specific repository classes,
if the 'enterprise' profile has been activated, needs to be activated manually. -->
<profile>
<id>enterprise</id>
<dependencies>
<dependency>
<groupId>${alfresco.groupId}</groupId>
<artifactId>alfresco-enterprise-repository</artifactId>
<version>${alfresco.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</profile>
<!-- If we are running in embedded Tomcat skip unit tests -->
<profile>
<id>run</id>
<properties>
<skipTests>true</skipTests>
</properties>
</profile>
</profiles>
view raw profiles-pom.xml hosted with ❤ by GitHub

And add the build section from the vanilla template

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
view raw profiles-2.pom.xml hosted with ❤ by GitHub

Next pom.xml for Share project modules

Again, if you’re switching from amp to jar, then you can update the <packaging> section

    <packaging>jar</packaging>

Update the dependencies section, to remove the integration test suite dependencies, like selenium, etc.

    <dependencies>
        <dependency>
            <groupId>${alfresco.groupId}</groupId>
            <artifactId>share</artifactId>
            <classifier>classes</classifier>
        </dependency>

        <dependency>
            <groupId>org.alfresco.surf</groupId>
            <artifactId>spring-surf-api</artifactId>
        </dependency>

    </dependencies>

Then add the build section, and we’re good to go:

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

 

Copy some files

Copy the top level src directory over

Copy the src directory from the vanilla project over to your project at the same level.

From the files we copied, update the platform-hotswap-agent.properties, and share-hotswap-agent.properties, and do a search and replace for the name of your vanilla-project-share-jar, and vanilla-project-platform-jar. For example, my vanilla project was named my-aio-project.

my-aio-project-share-jar

and replace with the name of your shareui project module.

Do the same for

my-aio-project-platform-jar

and replace with the name of your repository project module.

Copy the integration-tests module over

From the files you copied over, remove the sample IT test cases and package, and add your own.

Additionally, update the parent settings in the pom.xml so that the parent is your main project.

Migrating our Integration Tests

In migrating our IT tests, we’ll need to ensure that the test names end in IT. For example MyTest should be MyTestIT.

Next, we’ll remove the old RunWith dependency, and add the new ones.

For example

@RunWith(RemoteTestRunner.class)
@Remote(runnerClass = SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:alfresco/application-context.xml")

Will become

@RunWith(value = AlfrescoTestRunner.class)

Our IT test, will then need to extend the following class.

AbstractAlfrescoIT

Different approaches for setting up our integration tests can be found in the vanilla package that we generated. Use the way that best fits your model.

In this approach, @Autowire will not work, so we’ll need to update our @Before method to initialize our service dependencies.

For example:

@Before
public void setupTestCases() {
nodeService = getServiceRegistry().getNodeService();
transactionService = getServiceRegistry().getTransactionService();
nodeLocatorService = getServiceRegistry().getNodeLocatorService();
fileFolderService = getServiceRegistry().getFileFolderService();
myService = (MyService)getApplicationContext().getBean("myServiceId");
}
view raw it-test.java hosted with ❤ by GitHub

 

Spin it up

Next, start up your project with the following command

clean install alfresco:run

If you have the JRebel plugin in intellij, run your command using the jrebel executors

 

Troubleshooting

 

http connection errors when you attempt to start up the repository

For example:

Connect to localhost:8080 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1, localhost/fe80:0:0:0:0:0:0:1%1] failed: Connection refused

Review your integration tests and verify that their names end in IT.java. For example MyTestIT.java Test cases that end in *IT.java will not be executed through the maven test phase. Also verify that you’re using the correct version of maven: mvn 3.3.3

 

References

2 replies »

  1. Hello, first thanks for this article.
    At the beginning you wrote that it is possible to test webscripts using SDK 3. I am currently trying to migrate a project from SDK 2 to 3 and i managed to make my unit-tests and integration tests pass, but not my webscripts tests. Did you do it already ? How ?

    Regards

    • See the HelloWorldWebScriptIT.java Integration test that is shipped as an example in the 3.0 SDK for calling Webscripts as part of your integration tests

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: