Archivos mensuales: abril 2016

Alfresco y Scala

scala-logo-croped¿Que es Scala?

Scala es un lenguaje multi-paradigma que integra características de lenguajes funcionales y orientados a objetos, al contrario que Java que es un lenguaje imperativo (excepto en la versión 8 que Oracle ha incluido algunas características de lenguaje funcional como las funciones lambda).

Por tanto, es una buena idea poder utilizar Scala y Java en Alfresco ya que, de esta forma, podemos tener los dos paradigmas –funcional e imperativo– a nuestro servicio.

 

Versión de Alfresco

La prueba se ha realizado sobre Alfresco 5.0.c y se ha utilizado maven con el arquetipo de creación de módulos AMP, versión 2.2.0 del SDK.

 

Instalación de componentes en Eclipse

Los siguientes componentes son recomendables para poder utilizar Scala en Eclipse IDE:

– Instalar desde Marketplace: Scala IDE 4.2.x (recomendable)
– Instalar desde «Install new software» (opcional):

Nombre: Maven for Scala
URL: http://alchim31.free.fr/m2e-scala/update-site/

Crear proyecto de módulo AMP en Alfresco (SDK 2.2.0)

mvn archetype:generate -Dfilter=org.alfresco:

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:2.2:generate (default-cli) > generate-sources
@ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:2.2:generate (default-cli) < generate-sources
@ standalone-pom <<<
[INFO]
[INFO] --- maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom --
-
[INFO] Generating project in Interactive mode
[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.
archetypes:maven-archetype-quickstart:1.0)
Choose archetype:
1: remote -> org.alfresco.maven.archetype:alfresco-allinone-archetype (Sample mu
lti-module project for All-in-One development on the Alfresco plaftorm. Includes
modules for: Repository WAR overlay, Repository AMP, Share WAR overlay, Solr co
nfiguration, and embedded Tomcat runner)
2: remote -> org.alfresco.maven.archetype:alfresco-amp-archetype (Sample project
with full support for lifecycle and rapid development of Repository AMPs (Alfre
sco Module Packages))
3: remote -> org.alfresco.maven.archetype:share-amp-archetype (Share project wit
h full support for lifecycle and rapid development of AMPs (Alfresco Module
Packages))
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive co
ntains): : 2
Choose org.alfresco.maven.archetype:alfresco-amp-archetype version:
1: 2.0.0-beta-1
2: 2.0.0-beta-2
3: 2.0.0-beta-3
4: 2.0.0-beta-4
5: 2.0.0
6: 2.1.0
7: 2.1.1
8: 2.2.0
Choose a number: 8: 8
Downloading: https://repo.maven.apache.org/maven2/org/alfresco/maven/archetype/a
lfresco-amp-archetype/2.2.0/alfresco-amp-archetype-2.2.0.jar
Downloaded: https://repo.maven.apache.org/maven2/org/alfresco/maven/archetype/al
fresco-amp-archetype/2.2.0/alfresco-amp-archetype-2.2.0.jar (26 KB at 16.2 KB/se
c)
Downloading: https://repo.maven.apache.org/maven2/org/alfresco/maven/archetype/a
lfresco-amp-archetype/2.2.0/alfresco-amp-archetype-2.2.0.pom
Downloaded: https://repo.maven.apache.org/maven2/org/alfresco/maven/archetype/al
fresco-amp-archetype/2.2.0/alfresco-amp-archetype-2.2.0.pom (3 KB at 16.3 KB/sec
)
Define value for property 'groupId': : com.fegor.alfresco.scala
Define value for property 'artifactId': : AlfScala
[INFO] Using property: version = 1.0-SNAPSHOT
Define value for property 'package': com.fegor.alfresco.scala: :
Confirm properties configuration:
groupId: com.fegor.alfresco.scala
artifactId: AlfScala
version: 1.0-SNAPSHOT
package: com.fegor.alfresco.scala
Y: :

 

Crear carpetas para trabajar con Scala

Crear los directorios para trabajar con Scala dentro del proyecto:

src/main/scala
src/test/scala

 

Modificar pom.xml para integrar compilación con Scala

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.fegorsoft.alfresco.scala</groupId>
    <artifactId>AlfScala</artifactId>
    <version>1.0-SNAPSHOT</version>  
    <name>AlfScala Repository AMP project</name>
    <packaging>amp</packaging>
    <description>Manages the lifecycle of the AlfScala Repository AMP (Alfresco Module Package)</description>

    <parent>
        <groupId>org.alfresco.maven</groupId>
        <artifactId>alfresco-sdk-parent</artifactId>
        <version>2.2.0</version>
    </parent>

  <repositories>
      <repository>
          <id>artima</id>
          <name>Artima Maven Repository</name>
          <url>http://repo.artima.com/releases</url>
      </repository>
  </repositories>

    <!-- 
        SDK properties have sensible defaults in the SDK parent,
        but you can override the properties below to use another version.
        For more available properties see the alfresco-sdk-parent POM.
       -->
    <properties>
        <!-- The following are default values for data location and Alfresco Community version.
             Uncomment if you need to change (Note. current default version for Enterprise edition is 5.1)
          <alfresco.version>5.1.e</alfresco.version>
          <alfresco.data.location>/absolute/path/to/alf_data_dev</alfresco.data.location> -->

        <!-- This control the root logging level for all apps uncomment and change, defaults to WARN
            <app.log.root.level>WARN</app.log.root.level>
        -->

        <!-- Set the enviroment to use, this controls which properties will be picked in src/test/properties
             for embedded run, defaults to the 'local' environment. See SDK Parent POM for more info.
        <env>local</env>
        -->
        <recompileMode>incremental</recompileMode>
    <fsc>false</fsc>
    </properties>

    <!-- Here we realize the connection with the Alfresco selected platform 
        (e.g.version and edition) -->
    <dependencyManagement>
        <dependencies>
            <!-- Setup what versions of the different Alfresco artifacts that will be used (depends on alfresco.version),
                 so we don't have to specify version in any of the dependency definitions in our POM.
                 For more info see:
                    http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Importing_Dependencies
            -->
            <dependency>
                <groupId>${alfresco.groupId}</groupId>
                <artifactId>alfresco-platform-distribution</artifactId>
                <version>${alfresco.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- Following dependencies are needed for compiling Java code in src/main/java;
             <scope>provided</scope> is inherited for each of the following;
             for more info, please refer to alfresco-platform-distribution POM -->
        <dependency>
            <groupId>${alfresco.groupId}</groupId>
            <artifactId>alfresco-repository</artifactId>
        </dependency>

        <!-- If we are running tests then make the H2 Scripts available
             Note. tests are skipped when you are running -Pamp-to-war -->
        <dependency>
            <groupId>${alfresco.groupId}</groupId>
            <artifactId>alfresco-repository</artifactId>
            <version>${alfresco.version}</version>
            <classifier>h2scripts</classifier>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>*</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
  	    <dependency>
          <groupId>org.scala-lang</groupId>
          <artifactId>scala-compiler</artifactId>
          <version>2.11.8</version>
          <scope>compile</scope>
      </dependency>
      <dependency>
          <groupId>org.scala-lang</groupId>
          <artifactId>scala-library</artifactId>
          <version>2.11.8</version>
      </dependency>
      <dependency>
          <groupId>com.typesafe.scala-logging</groupId>
          <artifactId>scala-logging-slf4j_2.11</artifactId>
          <version>2.1.2</version>
      </dependency>
    <dependency>
      <groupId>org.scala-lang.modules</groupId>
      <artifactId>scala-xml_2.11</artifactId>
      <version>1.0.3</version>
    </dependency>
    <dependency>
      <groupId>org.scalactic</groupId>
      <artifactId>scalactic_2.11</artifactId>
      <version>3.0.0-M15</version>
    </dependency>
    <dependency>
      <groupId>org.scalatest</groupId>
      <artifactId>scalatest_2.11</artifactId>
      <version>3.0.0-M15</version>
      <scope>test</scope>
    </dependency>
    <!-- 
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
      </dependency>
       -->
    </dependencies>

    <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>
  </profiles>
    
  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>net.alchim31.maven</groupId>
          <artifactId>scala-maven-plugin</artifactId>
          <version>3.2.1</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>2.0.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
    <plugins>
            <plugin>
                <inherited>true</inherited>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.scala-tools</groupId>
                <artifactId>maven-scala-plugin</artifactId>
                <version>2.15.2</version>
                <executions>
                    <!-- Run scala compiler in the process-resources phase, so that dependencies on
                         scala classes can be resolved later in the (Java) compile phase -->
                    <execution>
                        <id>scala-compile-first</id>
                        <phase>process-resources</phase>                        
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
 
                    <!-- Run scala compiler in the process-test-resources phase, so that dependencies on
                         scala classes can be resolved later in the (Java) test-compile phase -->                    
                    <execution>
                      <id>scala-test-compile</id>
                      <phase>process-test-resources</phase>
                      <goals>
                          <goal>testCompile</goal>
                      </goals>
                	</execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <executions>
                    <!-- Add src/main/scala to source path of Eclipse -->
                    <execution>
                        <id>add-source</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>src/main/scala</source>
                            </sources>
                        </configuration>
                    </execution>
                    <!-- Add src/test/scala to test source path of Eclipse -->
                    <execution>
                        <id>add-test-source</id>
                        <phase>generate-test-sources</phase>
                        <goals>
                            <goal>add-test-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>src/test/scala</source>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>          
            <!-- to generate Eclipse artifacts for projects mixing Scala and Java -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.8</version>
                <configuration>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                    <projectnatures>
                        <projectnature>org.scala-ide.sdt.core.scalanature</projectnature>
                        <projectnature>org.eclipse.jdt.core.javanature</projectnature>
                    </projectnatures>
                    <buildcommands>
                        <buildcommand>org.scala-ide.sdt.core.scalabuilder</buildcommand>
                    </buildcommands>
                    <classpathContainers>
                        <classpathContainer>org.scala-ide.sdt.launching.SCALA_CONTAINER</classpathContainer>
                        <classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER</classpathContainer>
                    </classpathContainers>
                    <excludes>
                        <!-- in Eclipse, use scala-library, scala-compiler from the SCALA_CONTAINER rather than POM <dependency> -->
                        <exclude>org.scala-lang:scala-library</exclude>
                        <exclude>org.scala-lang:scala-compiler</exclude>
                    </excludes>
                    <sourceIncludes>
                        <sourceInclude>**/*.scala</sourceInclude>
                        <sourceInclude>**/*.java</sourceInclude>
                    </sourceIncludes>
                </configuration>
            </plugin>
            <!-- When run tests in the test phase, include .java and .scala source files -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <includes>
                        <include>**/*.java</include>
                        <include>**/*.scala</include>
                    </includes>
                </configuration>
            </plugin>
    </plugins>
  </build>
</project>

 

Crear una prueba unitaria

En este caso se crea una prueba unitaria para recuperar el contenido que hay dentro de ‘Company Home’.

package com.fegor.alfresco.scala.test

/*
 *  @author Fernando González (fegor at fegor dot com)
 *  
 */
import org.scalatest.junit.AssertionsForJUnit
import org.slf4j.LoggerFactory
import com.typesafe.scalalogging.slf4j.Logger
import org.junit.Assert._
import org.junit.{ Test, Before }
import org.junit.runner.RunWith
import com.tradeshift.test.remote.{ Remote, RemoteTestRunner }
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner
import org.springframework.context.ApplicationContext
import org.springframework.beans.factory.annotation.{ Autowired, Qualifier }
import org.alfresco.util.ApplicationContextHelper
import org.alfresco.model.ContentModel
import org.alfresco.service.cmr.repository.{ StoreRef, NodeService }
import org.alfresco.service.cmr.search.{ SearchService, ResultSet }
import org.alfresco.repo.security.authentication.AuthenticationUtil

/** Test Alfresco in Scala
 *  
 * @constructor create tests for Alfresco with Scala
 */
@RunWith(classOf[RemoteTestRunner])
@Remote(runnerClass = classOf[SpringJUnit4ClassRunner])
@ContextConfiguration(Array("classpath:alfresco/application-context.xml"))
class RepositoryTest extends AssertionsForJUnit {
  val logger = Logger(LoggerFactory.getLogger(classOf[RepositoryTest]))
  val storeRef: StoreRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore")
  val ctx: ApplicationContext = ApplicationContextHelper.getApplicationContext
  val nodeService: NodeService = ctx.getBean("NodeService").asInstanceOf[NodeService]

  var searchService: SearchService = ctx.getBean("SearchService").asInstanceOf[SearchService]

  /* Initialize
   */
  @Before
  def initialize() {
    AuthenticationUtil.setFullyAuthenticatedUser("admin")
  }

  /* Alfresco repository test
   */
  @Test
  def testRepositoryList() {
    val rs: ResultSet = searchService.query(storeRef, SearchService.LANGUAGE_LUCENE, "PATH:\"/app:company_home/*\"")
    assert(rs.length() > 0)
    logger.info((for (i <- 0 until rs.length()) yield nodeService.getProperty(rs.getNodeRef(i), ContentModel.PROP_NAME)) mkString ",")
    rs.close()
  }
}

 

Activar depuración de clases en log4j.properties

log4j.logger.com.fegor.alfresco.scala.test.RepositoryTest=DEBUG

 

Resultado de la ejecución de la prueba

2016-03-30 21:23:09,884  INFO  [extensions.webscripts.ScriptProcessorRegistry] [main] Registered script processor javascript for extension js
 2016-03-30 21:23:10,165  INFO  [scala.test.RepositoryTest] [main] Guest Home,User Homes,Shared,Imap Attachments,IMAP Home,Sites,Data Dictionary
 Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 41.923 sec - in com.fegor.alfresco.scala.test.RepositoryTest

 

Webs de referencia

http://scala-ide.org/docs/tutorials/m2eclipse/index.html

http://www.scalatest.org/getting_started_with_junit_4_in_scala

http://ted-gao.blogspot.com.es/2011/09/mixing-scala-and-java-in-project.html

https://en.wikipedia.org/wiki/Scala_(programming_language)

https://es.wikipedia.org/wiki/Scala_(lenguaje_de_programaci%C3%B3n)

http://www.scala-lang.org/