<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Under the (Content-)Hood &#187; Entwicklung</title>
	<atom:link href="http://axel-faust.de/?cat=16&#038;feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://axel-faust.de</link>
	<description>Alfresco et al in depth</description>
	<lastBuildDate>Mon, 15 Jul 2013 22:08:21 +0000</lastBuildDate>
	<language>de-DE</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.0.38</generator>
	<item>
		<title>Alfresco mit Arquillian #1 &#8211; &#8220;Managed Tomcat&#8221;</title>
		<link>http://axel-faust.de/?p=95&#038;lang=de</link>
		<comments>http://axel-faust.de/?p=95&#038;lang=de#comments</comments>
		<pubDate>Sun, 07 Jul 2013 17:53:22 +0000</pubDate>
		<dc:creator><![CDATA[afaust]]></dc:creator>
				<category><![CDATA[Arquillian]]></category>
		<category><![CDATA[Entwicklung]]></category>
		<category><![CDATA[JUnit]]></category>
		<category><![CDATA[Qualitätssicherung]]></category>
		<category><![CDATA[Alfresco]]></category>
		<category><![CDATA[QA]]></category>

		<guid isPermaLink="false">http://axel-faust.de/?p=95&#038;lang=de</guid>
		<description><![CDATA[Hinweis: Das Editor / Code Formatter Plugin wandelt leider einige XML-Tags in eine falsche Schreibweise um. Bei Übernahme der Beispiele sind daher die betroffenen Tags zu korrigieren (u.a. dependencyManagement, groupId, artifactId, activeByDefault, systemPropertyVariables, containerProfile, arquillian.launch). Content Repositories sind komplexe und &#8230;<p class="read-more"><a href="http://axel-faust.de/?p=95&#038;lang=de">Weiterlesen &#187;</a></p>]]></description>
				<content:encoded><![CDATA[<p><strong><em>Hinweis: Das Editor / Code Formatter Plugin wandelt leider einige XML-Tags in eine falsche Schreibweise um. Bei Übernahme der Beispiele sind daher die betroffenen Tags zu korrigieren (u.a. dependencyManagement, groupId, artifactId, activeByDefault, systemPropertyVariables, containerProfile, arquillian.launch).</em></strong></p>
<p>Content Repositories sind komplexe und zentrale Komponenten einer IT Infrastruktur / Content Management Lösung. Dies zieht entsprechend hohe Ansprüche im Punkt Qualitätsmanagement nach sich. Bei Alfresco Entwicklungsprojekten wird überwiegend JUnit eingesetzt um Entwicklertests zu realisieren. Das Alfresco Repository kann dabei innerhalb eines einfachen JUnit-TestCase eines fachlichen Moduls durch die Alfresco-Klasse <em>ApplicationContextHelper</em> im gleichen Prozess gestartet oder in einem eingebetteten Container (z.B. Jetty im Rahmen eines Maven-Builds) betrieben werden. Dabei werden in der Regel individuelle fachliche Komponenten nur isoliert und in einem von einer realistischen Umgebung stark abweichenden Konfiguration (u.a. mit umfangreichen Mocks) getestet. Dies kann dazu führen, dass eine hohe Codeabdeckung und Erfolgsquote von Tests nur eingeschränkt aussagekräftig für die Qualität eines Projekts sind und ein böses Erwachen in dedizierten Test- / Abnahmeumgebungen droht.</p>
<p>Im Rahmen unserer Tätigkeit als Alfresco Partner beschäftige ich mich in meiner verfügbaren Zeit außerhalb von Projekten und Vertrieb unter anderem damit, für Entwickler- und Integrationstests Alfresco mit dem auf JUnit basierenden Framework <a href="http://arquillian.org/" title="Arquillian Homepage">Arquillian</a> zusammen zu bringen. Die verschiedenen Aspekte, Probleme und Ansätze werde ich versuchen, in spezfischen Posts zusammen zu fassen.</p>
<h4>Probleme mit &#8220;Embedded Tomcat&#8221; Setup</h4>
<p>Für viele Entwicklungsprojekte mag ein &#8220;Embedded&#8221; Setup für die Durchführung von lokalen Tests die einfachste Konfiguration darstellen &#8211; sowohl in Bezug auf Unabhängigkeit der Konfiguration vom jeweiligen Setup der Entwickler als auch auf die Roundtrip-Zeit der Testdurchführung. Zusammen mit meinen Kollegen habe ich versucht, ein &#8220;Embedded Tomcat&#8221; Setup mit Arquillian zusammen zu stellen. Es ist jedoch nicht gelungen, die diversen Classloading Probleme, welche sich bei einer Ausführung von Tomcat im gleichen Prozess ergaben, aufzulösen. Speziell mit diversen XML-APIs, welche sowohl im Tomcat als auch im JDK enthalten sind und von Alfresco referenziert werden, kam es zu großen Inkompatibilitäten zwischen dem Arquillian / Maven / Boot-Classloader und dem Classloader für die Alfresco Webapplikation.</p>
<h4>Vorbereitungen Tomcat-Instanz / globale Alfresco Konfiguration</h4>
<p>Für die Durchführung von Test in einem &#8220;Managed Tomcat&#8221; Instanz muss eine lokale Tomcat-Instanz bereitgestellt werden, welche Arquillian zur Laufzeit der Tests anspricht und darauf das Alfresco Repository WAR deployed. Entsprechend der zu testenden Alfrescoversion kommt hier entweder Tomcat 6 oder 7 zum Einsatz. Es ist empfehlenswert, einen eigene Tomcat-Instanz für Arquillian aufzusetzen und nicht den ggf. mit dem Alfresco Installer installierten Tomcat zu verwenden.</p>
<p>Damit Arquilian Alfresco nach dem Start des Tomcat auch auf diesen deployen kann, ist es notwendig, die &#8220;Manager&#8221; Webanwendung von Tomcat auf diesem bereit zu stellen und eine entsprechende Konfiguration der <em>tomcat-users.xml</em> vorzunehmen. Alle anderen Webanwendungen, welche von Tomcat ausgeliefert werden (ROOT / host-manager o.ä.) können bedenkenlos entfernt werden. Eine einfache Konfiguration der <em>tomcat-users.xml</em> kannwie folgt aussehen:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;">&lt; ?xml <span style="color: #000066;">version</span>=<span style="color: #ff0000;">'1.0'</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">'utf-8'</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;tomcat</span> -users<span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;role</span> <span style="color: #000066;">rolename</span>=<span style="color: #ff0000;">&quot;manager&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;user</span> <span style="color: #000066;">username</span>=<span style="color: #ff0000;">&quot;arquillian&quot;</span> <span style="color: #000066;">password</span>=<span style="color: #ff0000;">&quot;arquillian&quot;</span> <span style="color: #000066;">roles</span>=<span style="color: #ff0000;">&quot;manager&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/tomcat<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Um die Testfälle möglichst frei von umgebungsspezifischer Konfiguration zu halten sollte innerhalb der Tomcatinstanz eine <em>alfresco-global.properties</em> mit einer funktionsfähigen Grundkonfiguration sowie die notwendigen Datenbanktreiber bereitgestellt werden. Diese sind wie gewohnt unter <em>&lt;tomcat&gt;/shared/classes</em> abzulegen. Die Konfiguration der Datenbankanbindung, Ablage von Dokumentinhalten sowie unterstützender Komponenten ist hier vorrangig, allerdings können auch Subsysteme (vor-)konfiguriert werden. Für wahrscheinlich 80 % der Testfälle treffen folgende Grundeinstellungen zu:</p>
<ul>
<li>Subsystem &#8220;fileServers&#8221;: Deaktivierung von CIFS, NFS und FTP (über JUnit i.d.R. nicht getestet)</li>
<li>Subsystem &#8220;email&#8221;: Deaktivierung des IMAP / SMTP Servers (über JUnit i.d.R. nicht getestet)</li>
</ul>
<p>Wird die Subsystemkonfiguration über die korrekte Vorgehensweise, d.h. unter Verwendung von <em>&lt;tomcat&gt;/shared/classes/alfresco/extension/subsystems/&lt;Subsystem&gt;/&#8230;</em> durchgeführt, können die Voreinstellungen bei Bedarf in einzelnen Testfällen unter Ausnutzung des ClassLoader-Verhaltens überschrieben werden. Unter keinen Umständen sollte Subsystemkonfigurationen daher in <em>alfresco-global.properties</em> durchgeführt werden (auch unabhängig von Arquillian eher &#8220;Bad Practice&#8221;).</p>
<h4>Projektsetup</h4>
<p>Die Einbindung von Arquillian in ein bestimmtes Entwicklungsprojekt kann sehr individuell erfolgen. Zu Demonstrationszwecken dient ein einfaches Maven Java-Projekt als Grundlage der weiteren Ausführungen. Die Integration mit dem Alfresco Maven SDK ist dem geneigten Leser überlassen.<br />
Mit <code>mvn archetype:generate -DgroupId={project-packaging} -DartifactId={project-name} -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false</code> oder dem entsprechenden Wizard-Äquivalent der IDE lässt sich ein einfaches Projekt erstellen. Um Arquillian für den Anwendungsfall von Alfrescotests im Maven Lifecycle zu integrieren, sollte folgende Dependency-Konfiguration vorgenommen werden:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;repositories<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;repository<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jboss-public-repository<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>JBoss Public Repository<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>https://repository.jboss.org/nexus/content/groups/public<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/repository<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/repositories<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependencymanagement<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependencies<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.jboss.arquillian<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>arquillian-bom<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.0.4.Final<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>import<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;type<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>pom<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/type<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependencies<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependencymanagement<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependencies<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>junit<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>junit<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>4.8.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>test<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.jboss.arquillian.junit<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>arquillian-junit-container<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>test<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.jboss.arquillian.extension<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>arquillian-service-integration-spring-inject<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.0.0.Beta1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>test<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.jboss.arquillian.extension<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>arquillian-service-deployer-spring-3<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.0.0.Beta1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>test<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.jboss.shrinkwrap.resolver<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>shrinkwrap-resolver-impl-maven<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>test<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependencies<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Diese Abhängigkeiten bilden die Grundlage für das im Arquillian Test-Lifecycle notwendige Zusammenbauen des Alfresco Deployments über die ShrinkWrap API sowie den Zugriff auf Beans des Alfresco Repository für eingebettete JUnit-Tests. Die Spring-bezogenen Abhängigkeiten können weggelassen werden, falls Arquillian ausschließlich für Remote-Tests verwendet werden soll.</p>
<p>Die Verwendung eines von Arquillian gesteuerten Tomcats bedarf der Erstellung des folgenden Profils:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;profiles<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;profile<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>tomcat-managed<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;activation<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;activebydefault<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/activebydefault<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/activation<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependencymanagement<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependencies<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #808080; font-style: italic;">&lt;!-- Lock the version, since additional dependencies (i.e. from Alfresco) often clash --&gt;</span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>commons-codec<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>commons-codec<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.5<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependencies<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependencymanagement<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependencies<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.jboss.arquillian.container<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>arquillian-tomcat-managed-6<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.0.0.CR4<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>test<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependencies<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/profile<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/profiles<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Für Tests von Alfresco 4.2 mit Tomcat 7 ist die entsprechend alternative Abhängigkeit <em>arquillian-tomcat-managed-7</em> zu verwenden.</p>
<p>Die zu verwendende Tomcat-Instanz ist über eine <em>arquillian.xml</em> innerhalb des Classpaths des Projekts zu konfigurieren. Diese Datei kann z.B. unter <em>src/test/resources</em> abgelegt werden, um eine globale Konfiguration für das gesamte Projekt zu liefern, oder ein einem Profil-spezifischen Pfad, um individuelle Konfigurationen je nach aktuellem Entwickler zu realisieren. Eine Profil-spezifische Ablage der Datei ist an sich grundsätzlich nicht notwendig, da sich die verschiedenen Konfigurationen innerhalb dieser Datei durch eine Konfiguration des Surefire Plugins individuell ansprechen lassen. Eine Grundkonfiguration er <em>arquillian.xml</em> kann wie folgt aussehen:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;">&lt; ?xml <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;arquillian</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://jboss.org/schema/arquillian&quot;</span> <span style="color: #000066;">xmlns:xsi</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span> <span style="color: #000066;">xsi:schemaLocation</span>=<span style="color: #ff0000;">&quot;http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd&quot;</span> <span style="color: #000066;">xmlns:spring</span>=<span style="color: #ff0000;">&quot;urn:arq:org.jboss.arquillian.container.spring.embedded_3&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;container</span> <span style="color: #000066;">qualifier</span>=<span style="color: #ff0000;">&quot;tomcat-managed-6&quot;</span> <span style="color: #000066;">default</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #808080; font-style: italic;">&lt;!-- Must match HTTP port from Tomcat server configuration file --&gt;</span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;bindHttpPort&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>8680<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;bindAddress&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>localhost<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #808080; font-style: italic;">&lt;!-- The prepared Tomcat instance --&gt;</span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;catalinaHome&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>D:/Applications/Arquillian/tomcat-repo<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;javaHome&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>C:/Program Files/Java/jdk1.6.0_30<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #808080; font-style: italic;">&lt;!-- Allow generous Heap and PermGen since we may deploy + start Alfresco multiple times --&gt;</span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;javaVmArguments&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>-Xmx2G -Xms2G -XX:MaxPermSize=1G -Dnet.sf.ehcache.skipUpdateCheck=true -Dorg.terracotta.quartz.skipUpdateCheck=true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #808080; font-style: italic;">&lt;!-- Must match configured manager from tomcat-users.xml --&gt;</span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;user&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>arquillian<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;pass&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>arquillian<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;urlCharset&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>UTF-8<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;startupTimeoutInSeconds&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>120<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #808080; font-style: italic;">&lt;!-- Local copy of Tomcat server configuration file --&gt;</span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;serverConfig&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>server.xml<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/container<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;extension</span> <span style="color: #000066;">qualifier</span>=<span style="color: #ff0000;">&quot;spring&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #808080; font-style: italic;">&lt;!-- Deactive automatic inclusion of Spring artifacts in deployments as Alfresco already contains them --&gt;</span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;auto-package&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>false<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/extension<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/arquillian<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Die notwendige <em>server.xml</em> kann aus der konfigurierten Tomcatinstanz in den Classpath des Projekts (<em>src/test/resources</em>) kopiert werden. Aus noch nicht nachvollzogenen Gründen kann hier keine Pfadangabe auf die Datei innerhalb der Tomcatinstanz verwendet werden.</p>
<p>Der Wert des <em>qualifier</em>-Attributs der <em>container</em>-Konfiguration kann wie folgt zum Selektieren eines speifischen Profils aus der POM heraus verwendet werden:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;build<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugins<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.apache.maven.plugins<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>maven-surefire-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;systempropertyvariables<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;arquillian</span> .launch<span style="color: #000000; font-weight: bold;">&gt;</span></span>${containerProfile}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/arquillian<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/systempropertyvariables<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugins<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/build<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;profiles<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;profile<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Dev XY<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;properties<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;containerprofile<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>xy-tomcat-managed-6<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/containerprofile<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/properties<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/profile<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/profiles<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Bei Verwendung der JUnit-Integration in Eclipse ist entsprechend der <em>-Darquillian.launch</em> Parameter in der Startkonfiguration zu setzen.</p>
<h4>Ein einfacher REST API Test</h4>
<p>Die einfachste Verwendung, welche sich mit Arquillian ohne größere Anpassungen realisieren lässt, sind Tests der REST API von Alfresco. Folgender TestCase kann mit der bisherigen Konfiguration (zzgl. Abhängigkeiten auf <em>org.jboss.resteasy:resteasy-jaxrs</em> und <em>org.json:json</em>) direkt ausgeführt werden:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="java" style="font-family:monospace;">@RunWith<span style="color: #009900;">&#40;</span>Arquillian.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> SimpleLoginRemoteTest <span style="color: #009900;">&#123;</span>
    @ArquillianResource <span style="color: #666666; font-style: italic;">// HTTP base-URl specific for our test deployment</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">URL</span> baseURL<span style="color: #339933;">;</span>
&nbsp;
    @Deployment <span style="color: #666666; font-style: italic;">// build the Repository WAR we want to test</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> WebArchive createDeployment<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// initialize Maven resolver from our project POM (specifically: repository-configuration to retrieve artifacts)</span>
        <span style="color: #000000; font-weight: bold;">final</span> MavenDependencyResolver resolver <span style="color: #339933;">=</span> DependencyResolvers.<span style="color: #006633;">use</span><span style="color: #009900;">&#40;</span>MavenDependencyResolver.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">loadMetadataFromPom</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;pom.xml&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// we want a standard Alfresco WAR for our tests - no modifications</span>
        <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">File</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> files <span style="color: #339933;">=</span> resolver.<span style="color: #006633;">artifact</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;org.alfresco.enterprise:alfresco:war:4.1.4&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">exclusion</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;*:*&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">resolveAsFiles</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// there is a simpler &quot;createFromZipFile&quot; method, but we want to provide a custom webapp-name to avoid deployment conflicts</span>
        <span style="color: #666666; font-style: italic;">// files[0] is the resolved alfresco.war</span>
        <span style="color: #000000; font-weight: bold;">final</span> WebArchive webArchive <span style="color: #339933;">=</span> ShrinkWrap.<span style="color: #006633;">create</span><span style="color: #009900;">&#40;</span>WebArchive.<span style="color: #000000; font-weight: bold;">class</span>, <span style="color: #0000ff;">&quot;SimpleLoginRemoteTest.war&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">as</span><span style="color: #009900;">&#40;</span>ZipImporter.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">importFrom</span><span style="color: #009900;">&#40;</span>files<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">as</span><span style="color: #009900;">&#40;</span>WebArchive.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">return</span> webArchive<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    @RunAsClient @Test
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> testAdminRESTLogin<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// use JBoss resteasy-library + org.json (add to POM) to perform a login</span>
        <span style="color: #000000; font-weight: bold;">final</span> ClientRequest loginRequest <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ClientRequest<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">baseURL</span>.<span style="color: #006633;">toURI</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;s/api/login&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        loginRequest.<span style="color: #006633;">accept</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;application/json&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">final</span> JSONObject loginReqObj <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> JSONObject<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        loginReqObj.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;username&quot;</span>, <span style="color: #0000ff;">&quot;admin&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;password&quot;</span>, <span style="color: #0000ff;">&quot;admin&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        loginRequest.<span style="color: #006633;">body</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;application/json&quot;</span>, loginReqObj.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">final</span> ClientResponse<span style="color: #339933;">&lt;</span> String<span style="color: #339933;">&gt;</span> loginResponse <span style="color: #339933;">=</span> loginRequest.<span style="color: #006633;">post</span><span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span>.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">Assert</span>.<span style="color: #006633;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Login failed&quot;</span>, <span style="color: #cc66cc;">200</span>, loginResponse.<span style="color: #006633;">getStatus</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Erläuterungen zum Beispiel:</p>
<ul>
<li>Arquillian-spezifische TestCase-Klassen müssen mit einem entsprechenden Arquillian-Runner ausgeführt werden, welcher den Lifecycle des TestCase abweichend vom JUnit-Standard steuert.</li>
<li>Pro TestCase gibt es eine statische Methode mit <em>@Deployment</em> Annotation, welche das zu testende Artefakt über ShrinkWrap erstellt. Hier können die notwendigen bzw. zu testenden Teilkomponenten individuell zusammengeführt werden.</li>
<li>Testmethoden mit <em>@RunAsClient</em> Annotation werden von Arquillian innerhalb des JUnit-Prozesses / -Kontext ausgeführt und haben können keinen direkten Zugriff auf Beans des Alfresco Repository nehmen. Fehlt diese Annotation, wird die jeweilige Testmethode über ein automatisch von Arquillian in das <em>WebArchive</em> eingefügtes <em>ArquillianServletRunner</em>-Servlet innerhalb der Alfresco Repository Webanwendung ausgeführt.</li>
<li>Für Testmethoden, welche via <em>@RunAsClient</em> remote auf das Alfresco Repository zugreifen müssen, wird über ein mit <em>@ArquillianResource</em> annotiertes <em>URL</em> Instanzfeld die HTTP URL für den Kontext der Webanwendung bereitgestellt.</li>
<li>Bei Verwendung des <em>MavenDependencyResolver</em> auf Basis der Projekt-POM müssen die notwendigen Repositories für Alfresco-Artefakte (z.B. http://artifacts.alfresco.com/&#8230;) in der POM eingetragen werden.</li>
</ul>
<p>Bei der Ausführung über die JUnit-Integration der IDE oder <code>mvn test</code> startet Arquillian die Tomcatinstanz, baut über die entsprechende Callback-Methode das zu testende Artefakte zusammen und überträgt/startet dieses über die Tomcat Manager Webanwendung. Sofern die Tomcatinstanz konfiguriert wurde, sollte entweder ein grüner Balken im JUnit-Fenster oder ein <em>BUILD SUCCESS</em> auf der Maven Konsole erscheinen.</p>
<h4>Ein einfacher (Service-)Bean Test</h4>
<p>Sollen mit Arquillian individuelle (Service-)Beans getestet werden muss eine Testklasse direkt auf den Spring-Kontext der Alfresco Repository Webanwendung zugreifen. Entegegen den regulären Alfresco JUnit-Tests (z.B. <em>NodeServiceTest</em>) kann dies nicht über den <em>ApplicationContextHelper</em> erfolgen. Da aufgrund der Mischung von regulären Testmethoden und <em>@RunAsClient</em>-Methoden in einer Klasse dies Klasse in zwei unterschiedlichen Kontexten laufen kann, ist es auch nicht ohne weiteres (sauber) möglich, in einer <em>@Before</em>/<em>@BeforeClass</em> und mithilfe <em>ContextLoader.getCurrentWebApplicationContext()</em> auf den Spring-Kontext zuzugreifen um notwendige Beans zu ermitteln. Mit einer einfachen Anpassung an der Erstellung des Deployments und unter Verwendung der <em>@Autowired</em> sowie <em>@Qualifier</em> Annotationen kann man sich die benötigten Beans durch den <em>ArquillianServletRunner</em> bereitstellen lassen.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="java" style="font-family:monospace;">@RunWith<span style="color: #009900;">&#40;</span>Arquillian.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span> @SpringWebConfiguration
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> SimpleNodeServiceLocalTest <span style="color: #009900;">&#123;</span>
    @Deployment
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> WebArchive createDeployment<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">final</span> MavenDependencyResolver resolver <span style="color: #339933;">=</span> DependencyResolvers.<span style="color: #006633;">use</span><span style="color: #009900;">&#40;</span>MavenDependencyResolver.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">loadMetadataFromPom</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;pom.xml&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">File</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> files <span style="color: #339933;">=</span> resolver.<span style="color: #006633;">artifact</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;org.alfresco.enterprise:alfresco:war:4.1.4&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">exclusion</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;*:*&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">resolveAsFiles</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">final</span> WebArchive webArchive <span style="color: #339933;">=</span> ShrinkWrap.<span style="color: #006633;">create</span><span style="color: #009900;">&#40;</span>WebArchive.<span style="color: #000000; font-weight: bold;">class</span>, <span style="color: #0000ff;">&quot;SimpleNodeServiceLocalTest.war&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">as</span><span style="color: #009900;">&#40;</span>ZipImporter.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">importFrom</span><span style="color: #009900;">&#40;</span>files<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">as</span><span style="color: #009900;">&#40;</span>WebArchive.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        webArchive.<span style="color: #006633;">addAsResource</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;arquillian-alfresco-context.xml&quot;</span>, <span style="color: #0000ff;">&quot;alfresco/extension/arquillian-alfresco-context.xml&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">return</span> webArchive<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    @Autowired @Qualifier<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;NodeService&quot;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">protected</span> NodeService nodeService<span style="color: #339933;">;</span>
&nbsp;
    @Autowired @Qualifier<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;TransactionService&quot;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">protected</span> TransactionService transactionService<span style="color: #339933;">;</span>
&nbsp;
    @Test
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> testNodeService<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">Assert</span>.<span style="color: #006633;">assertNotNull</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;NodeService not injected&quot;</span>, <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">nodeService</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">Assert</span>.<span style="color: #006633;">assertNotNull</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;TransactionService not injected&quot;</span>, <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">transactionService</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        AuthenticationUtil.<span style="color: #006633;">setFullyAuthenticatedUser</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;admin&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">transactionService</span>.<span style="color: #006633;">getRetryingTransactionHelper</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">doInTransaction</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> RetryingTransactionCallback<span style="color: #339933;">&lt;</span> Void<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">Void</span> execute<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Throwable</span> <span style="color: #009900;">&#123;</span>
                    <span style="color: #000000; font-weight: bold;">final</span> List<span style="color: #339933;">&lt;</span> StoreRef<span style="color: #339933;">&gt;</span> stores <span style="color: #339933;">=</span> SimpleNodeServiceLocalTest.<span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">nodeService</span>.<span style="color: #006633;">getStores</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
                    <span style="color: #000000; font-weight: bold;">Assert</span>.<span style="color: #006633;">assertFalse</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;List of stores is empty&quot;</span>, stores.<span style="color: #006633;">isEmpty</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
                    <span style="color: #666666; font-style: italic;">// check default / standard stores</span>
                    <span style="color: #000000; font-weight: bold;">Assert</span>.<span style="color: #006633;">assertTrue</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Store workspace://SpacesStore not contained in list of stores&quot;</span>, stores.<span style="color: #006633;">contains</span><span style="color: #009900;">&#40;</span>StoreRef.<span style="color: #006633;">STORE_REF_WORKSPACE_SPACESSTORE</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                    <span style="color: #000000; font-weight: bold;">Assert</span>.<span style="color: #006633;">assertTrue</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Store archive://SpacesStore not contained in list of stores&quot;</span>, stores.<span style="color: #006633;">contains</span><span style="color: #009900;">&#40;</span>StoreRef.<span style="color: #006633;">STORE_REF_ARCHIVE_SPACESSTORE</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                    <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span>, <span style="color: #000066; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">finally</span> <span style="color: #009900;">&#123;</span>
            AuthenticationUtil.<span style="color: #006633;">clearCurrentSecurityContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Die <em>arquillian-alfresco-context.xml</em> zum Beispiel:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;">&lt; ?xml <span style="color: #000066;">version</span>=<span style="color: #ff0000;">'1.0'</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">'UTF-8'</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;beans</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://www.springframework.org/schema/beans&quot;</span> <span style="color: #000066;">xmlns:xsi</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span> <span style="color: #000066;">xmlns:context</span>=<span style="color: #ff0000;">&quot;http://www.springframework.org/schema/context&quot;</span></span>
<span style="color: #009900;">    <span style="color: #000066;">xsi:schemaLocation</span>=<span style="color: #ff0000;">&quot;</span>
<span style="color: #009900;">            http://www.springframework.org/schema/beans</span>
<span style="color: #009900;">            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd</span>
<span style="color: #009900;">            http://www.springframework.org/schema/context</span>
<span style="color: #009900;">            http://www.springframework.org/schema/context/spring-context-3.0.xsd&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;context:annotation</span> -config <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/beans<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Erläuterungen zum Beispiel:</p>
<ul>
<li>Über die <em>@SpringWebConfiguration</em> Annotation wird deklariert, dass bei Ausführung des Tests im Container Beans aus dem aktuellen Spring-Kontext der Webanwendung benötigt werden. Sofern Servlets individuelle Kontexte hätten, könnten dieser über einen optionalen Parameter gezielt angesprochen werden.</li>
<li>Mit den <em>@Autowired</em> und <em>@Qualifier</em> werden über die Autowiring-Funktionalität von Spring spezifische Beans in die Instanz der Testklasse injeziert, sofern diese im Container ausgeführt wird. Autowiring ist in Alfresco nicht vorkonfiguriert, weswegen im Deployment eine zusätzliche Spring XML Konfigurationsdatei zum WAR hinzugefügt wird. Diese Datei ändert faktisch nichts an der Spring-Konfiguration von Alfresco, aktiviert aber implizit die Unterstützung von Autowiring.</li>
<li>Testmethoden laufen grundsätzlich ohne Authentifizierung oder einem Transaktionskontext. Sofern dieser für Tests benötigt wird, muss dieser im Test initiiert werden. Bei Verwendung von öffentlichen Service-Beans (z.B. &#8220;NodeService&#8221;) kann dieser wegfallen, wenn eine atomare Operation getestet wird, da öffentliche Service-Beans (bei korrekter Konfiguration) automatisch bei einem Aufruf für einen gültigen Transaktionskontext sorgen.</li>
<li>In der POM des Projekts ist die Alfresco Repository JAR der entsprechenden Alfresco Version als Abhängigkeit einzutragen, damit der Test kompilieren kann.</li>
</ul>
<h4>Offene Punkte / Probleme</h4>
<p>Mit den bereit gestellten Beispielen lässt sich Alfresco allumfänglich in einem &#8220;Managed Tomcat&#8221; Szenario testen. Allerdings gibt es wie bei allen Testansätzen auch hier diverse Punkte / Probleme, welche die Nutzbarkeit / Effizienz einschränken können. Im folgenden seien die aus meiner Sicht kritischsten Punkte genannt:</p>
<ul>
<li>Dauer des Deployment &#8211; Jedes Deployment einer Testfall-spezifischen Alfresco Repository WAR verbaucht eine enorme Zeit für die Übertragung sowie das Hoch- und Runterfahren Teilkomponenten. Auf meinem Lenovo T520 mit einer aktuellen SSD und 16 GiB RAM beläuft sich ein Durchlauf von 2 Testklassen (Komplexität nicht viel höher als die Beispiele hier) auf ca. 3 Minuten. Für einzelne Komponententests mag dies mit einer kleinen Kaffeepause durchaus noch vertragbar sein &#8211; für größere bzw. häufige Integrationstests z.B. in einem Continuous Integration Kontext wäre dies aber ein erhebliches Problem.</li>
<li>Speicherlast &#8211; Das vielfache Durchführen von Deployments in Tomcat erfordert große Mengen an Speicher, speziell für die Permanent Generation. Je nach Ausstattung der Entwicklungsumgebung kann dieser u.U. nicht bereitgestellt werden, sodass nur einzelne / wenige Testfälle in einem Durchgang ausgeführt werden können.</li>
<li>Deploymentfehler &#8211; Bei mehreren Durchläufen sind in meiner Konstellation Fehler beim (Un-)Deployment der Webanwendungen aufgetreten, welche nur durch manuelle Eingriffe bereinigt werden konnten. Für ein Continuous Integration Szenario ist dies nicht akzeptabel.</li>
<li>Kleinere Inkonsistenzen zwischen Tomcat-Versionen &#8211; Bei Test von Alfresco 4.2 auf Tomcat 7 wurde durch Arquillian das benötigte <em>ArquillianServlertRunner</em> Servlet nicht automatisch in die <em>web.xml</em> eingefügt. Dadurch konnten keine Tests gegen (Service-)Beans durchgeführt werden. Die (unschöne) Lösung des Problems bestand darin, eine angepasste <em>web.xml</em> mit expliziter Konfiguration des <em>AruillianServletRunner</em> Servlets in das <em>WebArchive</em> zu integrieren.</li>
<li>Bereitstellung einer definierten Datenbasis &#8211; Für einzelne Tests kann es notwendig sein, dass diese einen definierten Zustand von Daten (Datenbank, Inhalte, Index) vorfinden. Die Datenhaltung erfolgt bei einem &#8220;Managed Tomcat&#8221; Setup aber außerhalb der Testfalllogik und kann von dieser nicht ohne umgebungspezifischen Code beeinflusst werden.</li>
</ul>
<p>In weiteren Blog-Posts sollen für einige dieser Punkte mögliche Ansätze / Lösungen beschrieben werden.</p>
]]></content:encoded>
			<wfw:commentRss>http://axel-faust.de/?feed=rss2&#038;p=95</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Skriptimporte mit sauberer API</title>
		<link>http://axel-faust.de/?p=75&#038;lang=de</link>
		<comments>http://axel-faust.de/?p=75&#038;lang=de#comments</comments>
		<pubDate>Sun, 11 Mar 2012 22:00:00 +0000</pubDate>
		<dc:creator><![CDATA[afaust]]></dc:creator>
				<category><![CDATA[Alfresco]]></category>
		<category><![CDATA[Entwicklung]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Mozilla]]></category>
		<category><![CDATA[Rhino Script Engine]]></category>
		<category><![CDATA[Mozilla Rhino]]></category>

		<guid isPermaLink="false">http://axel-faust.de/?p=75&#038;lang=de</guid>
		<description><![CDATA[Update: Der Patch wurde ins Alfresco JIRA übertragen und kann unter ALF-13631 verfolgt werden. Im Rahmen meiner Bemühungen, mittels Eclipse JSDT Alfresco JavaScript remote zu debuggen, stellte sich die Art und Weise, wie in Alfresco JavaScript andere Skripte importiert werden, &#8230;<p class="read-more"><a href="http://axel-faust.de/?p=75&#038;lang=de">Weiterlesen &#187;</a></p>]]></description>
				<content:encoded><![CDATA[<p><em>Update: Der Patch wurde ins Alfresco JIRA übertragen und kann unter <a href="https://issues.alfresco.com/jira/browse/ALF-13631">ALF-13631</a> verfolgt werden.</em></p>
<p>Im Rahmen meiner Bemühungen, mittels <a title="Debugging Alfresco #1 – Eclipse JavaScript Debugger und Alfresco Repository" href="http://axel-faust.de/?p=47&amp;lang=de">Eclipse JSDT Alfresco JavaScript remote zu debuggen</a>, stellte sich die Art und Weise, wie in Alfresco JavaScript andere Skripte importiert werden, als eines der zentralen Probleme heraus. Aktuell wird hier ein Ansatz ähnlich einem Präprozessor verwendet und Skripte erst unmittelbar vor ihrer Ausführung endgültig zusammengefügt. Die für diesen Mechanismus notwendige Importdirektive sieht sowohl im Repository als in Share wie folgt aus:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #339933;">&lt;</span><span style="color: #FF0000;">import</span> resource<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;classpath:/alfresco/templates/org/alfresco/import/alfresco-util.js&quot;</span><span style="color: #339933;">&gt;</span>
<span style="color: #006600; font-style: italic;">/**
 * Main entrypoint
 */</span>
<span style="color: #000066; font-weight: bold;">function</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
   <span style="color: #000066; font-weight: bold;">var</span> activityFeed <span style="color: #339933;">=</span> getActivities<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #000066; font-weight: bold;">var</span> activities <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> activity<span style="color: #339933;">,</span> item<span style="color: #339933;">,</span> summary<span style="color: #339933;">,</span> fullName<span style="color: #339933;">,</span> date<span style="color: #339933;">,</span> sites <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> siteTitles <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
   <span style="color: #000066; font-weight: bold;">var</span> dateFilter <span style="color: #339933;">=</span> args.<span style="color: #660066;">dateFilter</span><span style="color: #339933;">,</span> oldestDate <span style="color: #339933;">=</span> getOldestDate<span style="color: #009900;">&#40;</span>dateFilter<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   ...
<span style="color: #009900;">&#125;</span>
main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">&lt;/</span>import<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>

<p>Vor der Ausführung wird ein Skript von Beginn an nach import-Tags durchsucht und alle Fragmente zu einer Gesamtdatei zusammen gefügt. Der Prozess stoppt beim ersten Zeichen (Whitespaces ausgenommen), welches nicht Teil eines import-Tags ist. Dieses Vorgehen hat einschränkende Konsequenzen:</p>
<ol>
<li>Imports an anderen Stellen außer dem Kopf eines Skripts sind nicht möglich.</li>
<li>Dynamische Imports sind nicht möglich, d.h. es können nicht dynamisch im Laufe der Logikausführung Skripte eingebunden werden.</li>
<li>Syntaxprüfungen von IDEs bemängeln die Importsyntax zu Recht als nicht valide.</li>
<li>Rhino Fehlermeldungen zeigen eine Zeilennummer an, die nicht mit dem Quellcode übereinstimmt &#8211; man ist häufig gezwungen, über alle Imports manuell und fehleranfällig die echte Zeilennummer in der Originaldatei auszurechnen, um sich besagte Zeile anschauen zu können.</li>
<li>Breakpoints beim Debuggen können nicht vor der Ausführung eines Skripts gesetzt werden. Das trifft meinen Ansatz mit JSDT härter als die mitgelieferten Rhino Debugger UI, da mir im JSDT die aggregierten Dateien zu keinem Zeitpunkt zur Verfügung stehen.</li>
</ol>
<p>Ich hatte mir schon länger vorgenommen, hier einen alternativen Ansatz zu finden &#8211; nicht nur um sinnvolles Debuggen mit JSDT zu ermöglichen, sondern auch auf eine flexiblere Nutzung / Wiederverwendung von Skripten zurück greifen zu können. Dieses Wochenende blieb mir dann auch endlich die ersehnte Zeit, hier aktiv zu werden. Ziel sollte es sein, eine kleine JavaScript API Erweiterung zur Verfügung zu stellen, mit der sich andere Skripte an beliebigen Stellen im Code importieren lassen. Zusätzlich wollte ich es ermöglichen, dass der Skript-Lookup Mechanismus einfach durch zusätzliche Lookup-Komponenten erweitert werden kann, ohne in die JavaScript API eingreifen zu müssen.</p>
<p>Alfresco selber bietet mit seinen javaScriptExtension Beans Möglichkeiten, neue Root Objekte in die API zu integrieren. Für mein Vorhaben war dieser Ansatz jedoch nicht ausreichend &#8211; die Java-basierten Services, die man über diesen Mechanismus zur Verfügung stellen kann, haben nicht den notwendigen Zugriff auf den Ausführungskontext der Rhino Script Engine. Mit einem Patch des RhinoScriptProcesor dagegen lässt sich eine native JavaScript Funktion einfach im globalen Kontext bekannt machen, die zusätzlich den notwendigen Zugriff auf Interna des Prozessors wie u.A. den ScriptCache hat. Die fertige Importfunktion steht in JavaScript wie folgt zur Verfügung:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;">importScript<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;legacy&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;classpath:/alfresco/templates/webscripts/org/alfresco/repository/forms/pickerresults.lib.js&quot;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Die drei Parameter der Funktion werden wie folgt verwendet:</p>
<ol>
<li>Die zu verwendende Lookup-Komponente für den Import. Mit &#8220;legacy&#8221; wird der grundsätzliche Ansatz des alten import-Tags verwendet, sodass sich bestehender Code mit RegEx-basiertem Suchen &amp; Ersetzen schnell anpassen lässt. Weiter habe ich zwei dedizierte Komponenten für &#8220;classpath&#8221; und &#8220;xpath&#8221; umgesetzt.</li>
<li>Eine textbasierte Referenz auf ein Skript, welches durch die gewählte Importer-Komponente aufzulösen ist.</li>
<li>Ein Boolean-Parameter, welcher bestimmt, ob der Import bei einem nicht auflösbaren Import mit einer ScriptException fehlschlagen soll.</li>
</ol>
<p>Die Funktion führt das zu importierende Skript im gleichen Kontext und Scope des Aufrufs aus. Das importierte Skript kann somit auf Variablen und Funktionen des aufrufenden Skripts zugreifen und mit diesen interagieren. Die Funktion hat einen Boolean-Rückgabeparameter, über welchen ein erfolgreich durchgeführter Import geprüft werden kann, wenn ein nicht auflösbarer Import nicht automatisch zu einem Fehlschlag führt. Als JavaScript Funktion kann der Import an jeder beliebigen Stelle eines Skripts erfolgen und bei Verwendung von berechneten Variablen dynamisch beliebige Skripte importieren.</p>
<p>Zusätzliche Import-Komponenten können durch Implementierung eines kleinen Java Interfaces und Verknüpfung mit dem RhinoScriptProcessor zur Verfügung gestellt werden. Das Interface definiert dabei nur eine Methode zum Auflösen des Referenzparameters. Mit einem zusätzlichen Kontextparameter für den Ablageort des aktuell ausgeführten Skripts lassen sich auch relative Referenzen realisieren.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">interface</span> ScriptLocator <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #008000; font-style: italic; font-weight: bold;">/**
	 * Resolves a string-based script location to a wrapper instance of the
	 * {@link ScriptLocation} interface usable by the repository's script
	 * processor. Implementations may support relative script resolution - a
	 * reference location is provided in instances an already running script
	 * attempts to import another.
	 *
	 * @param referenceLocation
	 *            a reference script location if a script currently in execution
	 *            attempts to import another, or {@code null} if either no
	 *            script is currently being executed or the script being
	 *            executed is not associated with a script location (e.g. a
	 *            simple script string)
	 * @param locationValue
	 *            the simple location to be resolved to a proper script location
	 * @return the resolved script location or {@code null} if it could not be resolved
	 *
	 */</span>
	ScriptLocation resolveLocation<span style="color: #009900;">&#40;</span>ScriptLocation referenceLocation,
			<span style="color: #003399;">String</span> locationValue<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>


<div class="wp_syntax"><table><tr><td class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;javaScriptProcessor&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;org.alfresco.repo.jscript.RhinoScriptProcessor&quot;</span> <span style="color: #000066;">init-method</span>=<span style="color: #ff0000;">&quot;register&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #808080; font-style: italic;">&lt;!-- ... --&gt;</span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;scriptLocators&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;map<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;entry</span> <span style="color: #000066;">key</span>=<span style="color: #ff0000;">&quot;classpath&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ref</span> <span style="color: #000066;">bean</span>=<span style="color: #ff0000;">&quot;javaScriptProcessor.classpathScriptLocator&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/entry<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;entry</span> <span style="color: #000066;">key</span>=<span style="color: #ff0000;">&quot;xpath&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ref</span> <span style="color: #000066;">bean</span>=<span style="color: #ff0000;">&quot;javaScriptProcessor.xPathScriptLocator&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/entry<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;entry</span> <span style="color: #000066;">key</span>=<span style="color: #ff0000;">&quot;legacy&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ref</span> <span style="color: #000066;">bean</span>=<span style="color: #ff0000;">&quot;javaScriptProcessor.legacyScriptLocator&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/entry<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/map<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;javaScriptProcessor.classpathScriptLocator&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;org.alfresco.repo.jscript.ClasspathScriptLocator&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;javaScriptProcessor.xPathScriptLocator&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;org.alfresco.repo.jscript.XPathScriptLocator&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;serviceRegistry&quot;</span> <span style="color: #000066;">ref</span>=<span style="color: #ff0000;">&quot;ServiceRegistry&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;javaScriptProcessor.legacyScriptLocator&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;org.alfresco.repo.jscript.LegacyScriptLocator&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #ddbb00;">&amp;lt;</span>property name=&quot;services&quot; ref=&quot;ServiceRegistry&quot;/&gt;
        <span style="color: #ddbb00;">&amp;lt;</span>property name=&quot;storeUrl&quot;&gt;
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>${spaces.store}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;storePath&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>${spaces.company_home.childname}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Soweit zur Umsetzung auf Seiten des Repository. Den gleichen Ansatz wollte ich für Share bzw. Spring Surf äquivalent umsetzen &#8211; allerdings bin ich schnell über die Tatsache gestolpert, dass Spring Surf / Web Scripts grundsätzlich schon über einen Ansatz zum Auflösen von Abhängigkeiten verfügen. Dieser kommt im aktuellen Präprozessorschritt der Skript-Aggregation auch schon zum Tragen. Mit Hilfe eines sog. &#8220;Store&#8221; lassen sich schon längst abstrakte Pfade entweder auf dem Classpath oder einem Remote-Store, wie z.B. einem Alfresco Repository, auflösen. Dieser Mechanismus ist ausreichend erweiterbar, sodass hier ein neuer Ansatz fehl am Platz wäre.</p>
<p>Für Share / Spring Surf habe ich daher eine abgespeckte API in JavaScript zur Verfügung gestellt, welche auf den bestehenden Mechanismus zurückgreift &#8211; der &#8220;legacy&#8221; Modus aus dem Repository wird hiermit implizit vorgegeben.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;">importScript<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;classpath:/alfresco/templates/org/alfresco/import/alfresco-util.js&quot;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Die Funktion steht sowohl für Web Scrpts als auch Template Controller zur Verfügung, und unterstützt neben explizitem Classpath wie im obigen Beispiel auch besagte abstrakte Pfade und relative Auflösung. Eine relative Auflösung wird dabei nur unterstützt, wenn das aktuell ausgeführte Skript vom Classpath geladen wurde. In einem solchen Fall wird zuerst eine relative Auflösung versucht, und erst im Anschluss &#8211; im Falle eines Fehlschlags &#8211; der angegebene Dateipfad versucht als abstrakter Pfad über einen Store zu einem Skript aufzulösen (relative Pfadangaben sind nicht eindeutig von abstrakten zu differenzieren).</p>
<p>Um die neue API zu testen habe ich in meiner lokalen Alfresco 4.0 Enterprise Installation üer Suchen &amp; Ersetzen ALLE Vorkommnisse des alten import-Tags mit der neuen Funktion ersetzt. Die Umstellung verlief dabei reibungslos. In der Rhino Debugger UI tauchen alle Teilskripte fortan als einzelne Skripte auf und Breakpoints lassen sich nun auch vor Ausführung / Zusammenfügen eines Skripts verlässlich setzen. Zeilennummern in JavaScript Exceptions sind endlich überwiegend korrekt.</p>
]]></content:encoded>
			<wfw:commentRss>http://axel-faust.de/?feed=rss2&#038;p=75</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Debugging Alfresco #1 &#8211; Eclipse JavaScript Debugger und Alfresco Repository</title>
		<link>http://axel-faust.de/?p=47&#038;lang=de</link>
		<comments>http://axel-faust.de/?p=47&#038;lang=de#comments</comments>
		<pubDate>Fri, 03 Feb 2012 23:32:04 +0000</pubDate>
		<dc:creator><![CDATA[afaust]]></dc:creator>
				<category><![CDATA[Alfresco]]></category>
		<category><![CDATA[Debugger]]></category>
		<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Entwicklung]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Mozilla]]></category>
		<category><![CDATA[Rhino Script Engine]]></category>
		<category><![CDATA[Mozilla Rhino]]></category>

		<guid isPermaLink="false">http://axel-faust.de/?p=47&#038;lang=de</guid>
		<description><![CDATA[Das Debuggen von Alfresco ist nicht immer ein einfaches Spiel. Die Java Bestandteile können mit den jeweiligen Remote Debugger der gängigen IDEs im laufenden System untersucht werden. Bei JavaScript und FreeMarker Templates stellt sich die Sache schon etwas komplizierter dar. &#8230;<p class="read-more"><a href="http://axel-faust.de/?p=47&#038;lang=de">Weiterlesen &#187;</a></p>]]></description>
				<content:encoded><![CDATA[<p>Das Debuggen von Alfresco ist nicht immer ein einfaches Spiel. Die Java Bestandteile können mit den jeweiligen Remote Debugger der gängigen IDEs im laufenden System untersucht werden. Bei JavaScript und FreeMarker Templates stellt sich die Sache schon etwas komplizierter dar.</p>
<p>Während die in Alfresco verbaute Rhino Engine mit einem eigenen, embedded Debugger daher kommt, gibt es für FreeMarker aktuell &#8211; zumindest meines Wissens &#8211; kein Tooling. Aber auch der embedded Rhino Debugger ist alles andere als handlich. Zum Einen stellt er für Entwickler einen Bruch in einer schon umfangreichen Ansammlung von Tools dar und zum Anderen kann er nur auf Servern mit graphischer Oberfläche eingesetzt werden &#8211; ein Debugging einer Entwicklungs- / Testumgebung auf einem Blech oder einer einfachen Server VM ist somit nicht möglich. Ich habe mir daher zuletzt etwas Zeit genommen, die neuen JavaScript Debugger Features des <a title="JavaScript Development Tools (JSDT)" href="http://www.eclipse.org/webtools/jsdt/">Eclipse JavaScript Development Tools (JSDT)</a> Projekts auszuprobieren.</p>
<p>Seit Version 3.7 der Eclipse IDE sind die notwendigen Bestandteile des JSDT in jeder Distribution enthalten, die das Web Standard Tools Sub-Projekt mitliefert. Nach anfänglichen Problemen aufgrund der noch jungen Debugger Komponente bin ich bei meinen Tests schnell beim aktuellen Milestone 4 des Juno Releases gelandet. Das Wiki des Projekts enthält eine recht nützliche Anleitung zur Verwendung des <a title="JSDT Rhino Integration" href="http://wiki.eclipse.org/JSDT/Debug/Rhino">Rhino Debugger Supports</a> als auch zu unserem speziellen Anwendungsfall der <a title="JSDT Rhino Embedded Integration" href="http://wiki.eclipse.org/JSDT/Debug/Rhino/Embedding_Rhino_Debugger">Integration in eine embedded Rhino Engine</a>. Ein kleines <a title="JSDT Debug FAQ" href="http://wiki.eclipse.org/JSDT/Debug/FAQ">FAQ</a> zu den häufigsten Problemen gibt es natürlich ebenfalls.</p>
<p>Damit man mit Eclipse remote den JavaScript Code von Web Scripten und Co debuggen kann, muss im Alfresco Server eine entsprechende Debugger-Komponente laufen und über eine TCP Schnittstelle angesprochen werden können (vgl. der <a title="Java Platform Debugger Architecture" href="http://java.sun.com/javase/technologies/core/toolsapis/jpda/">Java Platform Debugger Architecture</a>). Die notwendigen JARs liefert das JSDT gleich als Teil seiner Plugins mit, sodass diese &#8220;nur noch&#8221; in das &lt;tomcat&gt;/webapps/alfresco/WEB-INF/lib Verzeichnis kopiert werden müssen (wegen einer Class-Abhängigkeit auf die Rhino Engine ist &lt;tomcat&gt;/shared/lib nicht möglich). Die notwendigen Bibliotheken sind:</p>
<ul>
<li>org.eclipse.wst.jsdt.debug.rhino.debugger_&lt;version&gt;.jar</li>
<li>org.eclipse.wst.jsdt.debug.transport_&lt;version&gt;.jar</li>
</ul>
<p>Entsprechend der Anleitung zum Embedden müssen wir den Debugger an den Rhino Context binden und aktivieren. Dazu reicht es, eine kleine Bean zu implementieren und durch Spring beim Bootstrap der Alfresco Webapplikation ausführen zu lassen.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">com.prodyna.debug.rhino</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.text.MessageFormat</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.eclipse.wst.jsdt.debug.rhino.debugger.RhinoDebugger</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.mozilla.javascript.ContextFactory</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.springframework.beans.factory.InitializingBean</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> RemoteJSDebugInitiator <span style="color: #000000; font-weight: bold;">implements</span> InitializingBean <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span> DEFAULT_PORT <span style="color: #339933;">=</span> <span style="color: #cc66cc;">9000</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> DEFAULT_TRANSPORT <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;socket&quot;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">boolean</span> suspend <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// suspend until debugger attaches itself</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">boolean</span> trace <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// trace-log the debug agent</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">int</span> port <span style="color: #339933;">=</span> DEFAULT_PORT<span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> transport <span style="color: #339933;">=</span> DEFAULT_TRANSPORT<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// the global context factory used by Alfresco</span>
	<span style="color: #000000; font-weight: bold;">private</span> ContextFactory contextFactory <span style="color: #339933;">=</span> ContextFactory.<span style="color: #006633;">getGlobal</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> afterPropertiesSet<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">// setup debugger based on configuration</span>
		<span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> configString <span style="color: #339933;">=</span> <span style="color: #003399;">MessageFormat</span>.<span style="color: #006633;">format</span><span style="color: #009900;">&#40;</span>
			<span style="color: #0000ff;">&quot;transport={0},suspend={1},address={2},trace={3}&quot;</span>,
			<span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Object</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">transport</span>, <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">suspend</span> <span style="color: #339933;">?</span> <span style="color: #0000ff;">&quot;y&quot;</span> <span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;n&quot;</span>,
				<span style="color: #003399;">String</span>.<span style="color: #006633;">valueOf</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">port</span><span style="color: #009900;">&#41;</span>, <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">trace</span> <span style="color: #339933;">?</span> <span style="color: #0000ff;">&quot;y&quot;</span> <span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;n&quot;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000000; font-weight: bold;">final</span> RhinoDebugger debugger <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> RhinoDebugger<span style="color: #009900;">&#40;</span>configString<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">contextFactory</span>.<span style="color: #006633;">addListener</span><span style="color: #009900;">&#40;</span>debugger<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		debugger.<span style="color: #006633;">start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> setSuspend<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">boolean</span> suspend<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">suspend</span> <span style="color: #339933;">=</span> suspend<span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> setTrace<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">boolean</span> trace<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">trace</span> <span style="color: #339933;">=</span> trace<span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> setPort<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> port<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">port</span> <span style="color: #339933;">=</span> port<span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> setTransport<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> transport<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">transport</span> <span style="color: #339933;">=</span> transport<span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> setContextFactory<span style="color: #009900;">&#40;</span>ContextFactory contextFactory<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">contextFactory</span> <span style="color: #339933;">=</span> contextFactory<span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Diese Bean kann dann durch folgende Beandeklaration in der &lt;tomcat&gt;/shared/classes/alfresco/extension/dev-context.xml aktiviert werden.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;pd.jsRemoveDebugger&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;com.prodyna.debug.rhino.RemoteJSDebugInitiator&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;port&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>8000<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;trace&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Nach dem Neustart des Alfresco Repository Servers kann man sich mit Eclipse via Remote JavaScript Debugging auf die Rhino Engine aufschalten. Hierzu muss lediglich die entsprechende Debug Configuration angelegt werden, bei der die verwendeten Parameter der Serverkomponente einzutragen sind.</p>
<p><a href="http://axel-faust.de/wp/wp-content/uploads/2012/01/Rhino-Debug-Configuration.png"><img class="alignnone size-full wp-image-53" title="Eclipse JavaScript Debugger - Rhino Connector Konfiguration" src="http://axel-faust.de/wp/wp-content/uploads/2012/01/Rhino-Debug-Configuration.png" alt="" width="1014" height="640" /></a></p>
<p>Leider ist damit noch nicht alles getan, um erfolgreich serverseitiges JavaScript aus Eclipse heraus debuggen zu können. Ähnlich wie der Classpath müssen Skripte im Eclipse in einer bestimmten Struktur liegen, damit sie mit den auf den Server ausgeführten Skripten abgeglichen werden können. Nur wenn dieser Abgleich erfolgt ist, werden Breakpoints, die in JavaScript Dateien ähnlich wie in Java mit einem Doppelklick auf den sog. Ruler eingestellt werden, von Eclipse an den Server übermittelt und aktiviert.</p>
<p>Die notwendige Source Code Struktur für remote debuggte Skripte richtet sich nach dem bei der Übergabe an die Rhino Engine angegebenen Source Namen. Alfresco verwendet hier durchgehen die File URI des Hauptskripts, d.h. also für einen Repository Server, welcher in &#8220;D:\Applications\Swift\tomcat&#8221; deployed wurde, beträgt die URI für den Web Script Controller sites.get.js &#8220;file://D:/Applications/Swift/tomcat/webapps/alfresco/WEB-INF/classes/alfresco/templates/webscripts/org/alfresco/repository/sites/sites.get.js&#8221;. Laut dem FAQ des JSDT wird eine solche URI ohne den &#8220;file://D:/&#8221; Prefix auf ein automatisch angelegtes Source Projekt &#8220;External JavaScript Source&#8221; gemapped. Dies traf bei mir nicht zu und nach Studium des Source Code des JSDT Plugins habe ich eine funktionierende Alternative gefunden: das erste Pfadelement entspricht einem Source Projekt und der Rest des Pfades ist relativ zu diesem zu betrachten. Um also JavaScript Web Script <a href="http://axel-faust.de/wp/wp-content/uploads/2012/02/JS-Debug-Source-Project.png"><img class="size-medium wp-image-59 alignleft" title="Source Projekt - Struktur" src="http://axel-faust.de/wp/wp-content/uploads/2012/02/JS-Debug-Source-Project-300x149.png" alt="" width="300" height="149" /></a>Controller in meinem Swift Repository debuggen zu können, musste ich dessen Web Scripte in einem Projekt namens &#8220;Applications&#8221; in einer Ordnerstruktur &#8220;Swift/t/tomcat/webapps/alfresco/WEB-INF/classes/alfresco/templates/webscripts/&#8221; zur Verfügung stellen. Am einfachsten geht dies, indem man den Source Code des Alfresco Remote API Projekts als Source in eine solche Struktur linkt.</p>
<p><a href="http://axel-faust.de/wp/wp-content/uploads/2012/02/JS-Debug-Source-Project-Linking.png"><img class="alignnone size-full wp-image-61" title="Source Projekt - Externe Sourcen Linken" src="http://axel-faust.de/wp/wp-content/uploads/2012/02/JS-Debug-Source-Project-Linking.png" alt="" width="1148" height="548" /></a></p>
<p>Nachdem diese letzte Konfiguration abgeschlossen wurde, werden Breakpoints, die in Alfresco Web Script, wie z.B. sites.get.js gesetzt wurden, sauber an den Server übertragen. Bei der nächsten Ausführung einer Site Suche in Alfresco Share hält der Debugger dann entsprechend an der definierten Position an und lässt das Web Script mit den gewohnten Funktionen wie Step Over / Into, der Variables sowie Expressions View untersuchen. Besonders letztere ist aktuell noch übermäßig wertvoll, da der Debugger mit Java Objekten als Variablenwerte in der Variables View nicht viel anfangen kann.</p>
<p><a href="http://axel-faust.de/wp/wp-content/uploads/2012/02/debug_sites_get.png"><img class="alignnone size-full wp-image-62" title="Eclipse JavaScript Debugger - Variables" src="http://axel-faust.de/wp/wp-content/uploads/2012/02/debug_sites_get.png" alt="" width="1300" height="768" /></a></p>
<p><a href="http://axel-faust.de/wp/wp-content/uploads/2012/02/debug_sites_get_expressions.png"><img class="alignnone size-full wp-image-66" title="Eclipse JavaScript Debugger - Expressions" src="http://axel-faust.de/wp/wp-content/uploads/2012/02/debug_sites_get_expressions.png" alt="" /></a></p>
<p><em><strong>Zwischenfazit: </strong></em>Mit dem Eclipse JSDT lassen sich JavaScript Dateien, die Teil der Alfresco Applikation &#8211; d.h. dessen Classpath &#8211; sind, aus der gewohnten Entwicklungsumgebung heraus remote debuggen. Damit entfällt die bisherige Einschränkung des Rhino Debuggers, dass JavaScript Dateien nur auf lokalen Servern bzw. Servern mit graphischer Oberfläche debug-bar sind. Die Einrichtung des JSDT Remote Debuggers mag etwas gewöhnungsbedürftig sein, ist jedoch mit den zur Verfügung stehenden Mitteln des Source Linkings  schnell und ohne unnötige Code Redundanz im Workspace realisierbar. Aktuell gibt es aufgrund des noch jungen Debuggers und der Art und Weise, wie Alfresco die Rhino Engine integriert hat, ein paar Besonderheiten und Einschränkungen in der Nutzung des Debuggers. Auf diese werden ich in kommenden Posts dieser Serie eingehen und &#8211; soweit möglich &#8211; Lösungen vorstellen.</p>
]]></content:encoded>
			<wfw:commentRss>http://axel-faust.de/?feed=rss2&#038;p=47</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
