<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Cédric Bosdonnat - ECM</title><link href="https://bosdonnat.fr/" rel="alternate"></link><link href="https://bosdonnat.fr/feeds/ecm.atom.xml" rel="self"></link><id>https://bosdonnat.fr/</id><updated>2013-08-07T09:54:00+02:00</updated><subtitle>A geek's perspective</subtitle><entry><title>libcmis 0.4.0 released</title><link href="https://bosdonnat.fr/libcmis-0-4-0-released.html" rel="alternate"></link><published>2013-08-07T09:54:00+02:00</published><updated>2013-08-07T09:54:00+02:00</updated><author><name>Cédric Bosdonnat</name></author><id>tag:bosdonnat.fr,2013-08-07:/libcmis-0-4-0-released.html</id><summary type="html">&lt;p&gt;After quite a long time alternating intensive hacking and inactivity, libcmis
0.4.0 is finally out and brings quite a number of great new features. The
hightlight of this release is of course the introduction of the Google Drive
protocol as a CMIS binding by &lt;strong&gt;&lt;a href="http://anonymousquark.com/"&gt;Cao Cuong Ngo&lt;/a&gt;&lt;/strong&gt; for …&lt;/p&gt;</summary><content type="html">&lt;p&gt;After quite a long time alternating intensive hacking and inactivity, libcmis
0.4.0 is finally out and brings quite a number of great new features. The
hightlight of this release is of course the introduction of the Google Drive
protocol as a CMIS binding by &lt;strong&gt;&lt;a href="http://anonymousquark.com/"&gt;Cao Cuong Ngo&lt;/a&gt;&lt;/strong&gt; for his Google Summer of
Code project with LibreOffice. This allows to connect to
your Google Drive documents in the same way than with any CMIS server.&lt;/p&gt;
&lt;p&gt;However there are quite some other important improvements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Support for OAuth2 authentication for the CMIS servers. This allows libcmis to
  connect to &lt;a href="http://www.alfresco.com/products/cloud"&gt;Alfresco cloud&lt;/a&gt;. Most of this feature comes from &lt;strong&gt;&lt;a href="http://anonymousquark.com/"&gt;Cao Cuong
  Ngo&lt;/a&gt;&lt;/strong&gt;'s work.&lt;/li&gt;
&lt;li&gt;Allow to provide custom HTTP proxy configuration.&lt;/li&gt;
&lt;li&gt;Handle invalid SSL certificates instead of simply failing them. This feature
  depends if libcurl was built with OpenSSL or not.&lt;/li&gt;
&lt;li&gt;Provide repository capabilities&lt;/li&gt;
&lt;li&gt;Implement renditions support&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And it's not a feature, but a great improvements from libcmis hackers: I removed
the Atom binding unit tests depending on Apache Chemistry InMemory server and
switched them to a unit test framework using a &lt;a href="https://bosdonnat.fr/testing-libcurl-based-http-clients.html"&gt;libcurl mockup&lt;/a&gt;. It heavily
reduced the unit test execution time, but the WebService binding unit test still
have to be migrated to completely get rid of the InMemory server.&lt;/p&gt;
&lt;p&gt;You can download libcmis 0.4.0 on &lt;a href="https://sourceforge.net/projects/libcmis/"&gt;SourceForge.net&lt;/a&gt; as usual. The package for
openSUSE will shortly available on &lt;a href="http://software.opensuse.org"&gt;software.opensuse.org&lt;/a&gt;&lt;/p&gt;</content><category term="ECM"></category><category term="CMIS"></category><category term="ECM"></category></entry><entry><title>Screenshots of CMIS in Nautilus</title><link href="https://bosdonnat.fr/screenshots-of-cmis-in-nautilus.html" rel="alternate"></link><published>2013-08-01T11:24:00+02:00</published><updated>2013-08-01T11:24:00+02:00</updated><author><name>Cédric Bosdonnat</name></author><id>tag:bosdonnat.fr,2013-08-01:/screenshots-of-cmis-in-nautilus.html</id><summary type="html">&lt;p&gt;Michael asked me this week to provide some screenshots of my &lt;a href="https://bosdonnat.fr/cmis-for-gnome.html"&gt;hackweek work&lt;/a&gt; on a GVFS
backend for CMIS. Sadly I had none and switched to &lt;a href="http://software.opensuse.org/developer/en"&gt;openSUSE Factory&lt;/a&gt; in the mean time so
I had to update my code for gvfs master branch. I also had an annoying bug when …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Michael asked me this week to provide some screenshots of my &lt;a href="https://bosdonnat.fr/cmis-for-gnome.html"&gt;hackweek work&lt;/a&gt; on a GVFS
backend for CMIS. Sadly I had none and switched to &lt;a href="http://software.opensuse.org/developer/en"&gt;openSUSE Factory&lt;/a&gt; in the mean time so
I had to update my code for gvfs master branch. I also had an annoying bug when browsing
a CMIS repository in Nautilus... so I had to fix that.&lt;/p&gt;
&lt;p&gt;After quite some hours searching, debugging, adding g_print in nautilus, gtk+ and glib, I
finally found the culprit: &lt;code&gt;g_vfs_encode_uri&lt;/code&gt; was leaving the &lt;code&gt;':'&lt;/code&gt; unencoded in the hostname.&lt;/p&gt;
&lt;p&gt;Now I have screenshots to show here:&lt;/p&gt;
&lt;p&gt;One from an Alfresco server:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Alfresco shown in Nautilus" src="https://bosdonnat.fr/data/ecm/nautilus-alfresco.png"&gt;&lt;/p&gt;
&lt;p&gt;One showing the SharePoint 2013 repositories:&lt;/p&gt;
&lt;p&gt;&lt;img alt="SharePoint 2013 repositories" src="https://bosdonnat.fr/data/ecm/nautilus-sharepoint_2013.png"&gt;&lt;/p&gt;</content><category term="ECM"></category><category term="Gnome"></category><category term="CMIS"></category></entry><entry><title>CMIS for GNOME</title><link href="https://bosdonnat.fr/cmis-for-gnome.html" rel="alternate"></link><published>2013-04-22T13:23:00+02:00</published><updated>2013-04-22T13:23:00+02:00</updated><author><name>Cédric Bosdonnat</name></author><id>tag:bosdonnat.fr,2013-04-22:/cmis-for-gnome.html</id><summary type="html">&lt;p&gt;At &lt;a href="http://suse.com"&gt;SUSE&lt;/a&gt;, we recently had a &lt;a href="http://hackweek.suse.com"&gt;Hackweek&lt;/a&gt;. It’s one week for all developers employed
by SUSE to hack on any innovative open source project they want. Last years, I
worked on &lt;a href="http://sourceforge.net/projects/libcmis/"&gt;libcmis&lt;/a&gt; and libcmis-c. And this year, I started implementing a GVFS
backend for CMIS using libcmis-c. GVFS is …&lt;/p&gt;</summary><content type="html">&lt;p&gt;At &lt;a href="http://suse.com"&gt;SUSE&lt;/a&gt;, we recently had a &lt;a href="http://hackweek.suse.com"&gt;Hackweek&lt;/a&gt;. It’s one week for all developers employed
by SUSE to hack on any innovative open source project they want. Last years, I
worked on &lt;a href="http://sourceforge.net/projects/libcmis/"&gt;libcmis&lt;/a&gt; and libcmis-c. And this year, I started implementing a GVFS
backend for CMIS using libcmis-c. GVFS is the one of the low-level layers of
&lt;a href="http://www.gnome.org"&gt;GNOME&lt;/a&gt; to access files. A backend is a set of features like mount, unmount, read
a document, writ a document, navigate in folders, etc. Currently GVFS has
backends for FTP, SSH, WebDAV, Trash, Audio CDs, and quite a lot of other useful
things. Having a CMIS backend would allow any Gnome application to access
documents stored on a CMIS-enabled server.&lt;/p&gt;
&lt;p&gt;What I achieved in one week:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;mount and unmount a CMIS repository&lt;/li&gt;
&lt;li&gt;read a document&lt;/li&gt;
&lt;li&gt;provide the content of the folders and repositories&lt;/li&gt;
&lt;li&gt;provide some of the CMIS properties&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To have a complete backend to upstream, I will need to implement:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;creating / writing files&lt;/li&gt;
&lt;li&gt;deleting / moving items&lt;/li&gt;
&lt;li&gt;creating folders&lt;/li&gt;
&lt;li&gt;setting properties&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The code can be found on a &lt;a href="http://cgit.freedesktop.org/~cbosdo/gvfs-cbosdo/"&gt;gvfs git clone in my freedesktop home&lt;/a&gt;. I want to
thank the Gnome hackers who kindly answered my beginner questions during this
week.&lt;/p&gt;</content><category term="ECM"></category><category term="Gnome"></category><category term="CMIS"></category></entry><entry><title>Testing libcurl-based HTTP clients</title><link href="https://bosdonnat.fr/testing-libcurl-based-http-clients.html" rel="alternate"></link><published>2013-02-14T14:48:00+01:00</published><updated>2013-02-14T14:48:00+01:00</updated><author><name>Cédric Bosdonnat</name></author><id>tag:bosdonnat.fr,2013-02-14:/testing-libcurl-based-http-clients.html</id><summary type="html">&lt;p&gt;Since the last blog post, quite some nice things happened: I moved to a new
house, we released &lt;a href="http://www.libreoffice.org"&gt;LibreOffice 4.0.0&lt;/a&gt; fantastic release and &lt;a href="http://mmohrhard.wordpress.com/"&gt;Markus&lt;/a&gt; helped me
write better unit tests for &lt;a href="http://sourceforge.net/projects/libcmis/"&gt;libcmis&lt;/a&gt;.In this post, I’ld like to give some
details on these new unit tests. To …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Since the last blog post, quite some nice things happened: I moved to a new
house, we released &lt;a href="http://www.libreoffice.org"&gt;LibreOffice 4.0.0&lt;/a&gt; fantastic release and &lt;a href="http://mmohrhard.wordpress.com/"&gt;Markus&lt;/a&gt; helped me
write better unit tests for &lt;a href="http://sourceforge.net/projects/libcmis/"&gt;libcmis&lt;/a&gt;.In this post, I’ld like to give some
details on these new unit tests. To understand the need of changing unit tests,
you need to know that libcmis test script was downloading, setting up and
starting an &lt;a href="http://chemistry.apache.org/java/developing/repositories/dev-repositories-inmemory.html"&gt;Apache Chemistry InMemory&lt;/a&gt; server to interact with. This system had
several drawbacks like slow unit tests and dependency on the test server
features and bugs for inventing new test cases. To work this around, Markus
helped me to setup a &lt;a href="http://curl.haxx.se/libcurl/"&gt;libcurl&lt;/a&gt; mockup library.&lt;/p&gt;
&lt;p&gt;The principle is pretty simple: replace the normal libcurl used to send the
HTTP requests to the server by a mockup library. The mockup can then store the
sent requests and provide the responses we want (either valid ones or invalid
ones). The code of the mockup is still evolving and can be found in the
&lt;a href="http://code.ohloh.net/project?pid=lGlZ5bFEHQc&amp;amp;did=qa%2Fmockup"&gt;qa/mockup&lt;/a&gt; folder of libcmis source tree. One of the key functions to get it
working is &lt;strong&gt;curl_mockup_addResponse&lt;/strong&gt;: it tells the mockup what response to
provide under which circumstances. This function may still need some more
parameters to cover all cases, but it will associate a response (body, headers,
status) with a request (URL, HTTP method). The other important function for
testing is &lt;strong&gt;curl_mockup_getRequest&lt;/strong&gt;: it gives back the request content for a URL
and HTTP method. It helps making sure that our code sent the proper request.&lt;/p&gt;
&lt;p&gt;As always, a small code snippet helps a lot to understand. Let’s take one
derived from libcmis unit tests.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;AtomTest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;createDocumentTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Reset the mockup configuration to avoid keeping other tests config&lt;/span&gt;
    &lt;span class="n"&gt;curl_mockup_reset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Add a response to match. In this case, a POST request with a URL like&lt;/span&gt;
    &lt;span class="c1"&gt;// http://mockup/mock/children?id=root-folder&amp;amp;amp;somethingelse will fit&lt;/span&gt;
    &lt;span class="c1"&gt;// The response will have:&lt;/span&gt;
    &lt;span class="c1"&gt;//    - the body: &amp;quot;Response body up to server&amp;quot;&lt;/span&gt;
    &lt;span class="c1"&gt;//    - the HTTP status: 201&lt;/span&gt;
    &lt;span class="c1"&gt;//    - the HTTP Headers with Location defined&lt;/span&gt;
    &lt;span class="n"&gt;curl_mockup_addResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;http://mockup/mock/children&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;id=root-folder&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;POST&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                             &lt;span class="s"&gt;&amp;quot;Response body up to server&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                             &lt;span class="s"&gt;&amp;quot;Location: http://mockup/mock/id?id=create-document&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Set the authentication credentials needed to fake the server&lt;/span&gt;
    &lt;span class="n"&gt;curl_mockup_setCredentials&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;SERVER_USERNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SERVER_PASSWORD&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Create the CURL handle (in the session for libcmis)&lt;/span&gt;
    &lt;span class="n"&gt;AtomPubSession&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getTestSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;SERVER_USERNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SERVER_PASSWORD&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Do something with the CURL handle (the session for libcmis)&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="c1"&gt;// You can check that your code worked fine (thanks to the response you provided)&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="c1"&gt;// You can also check that the request was the expected one&lt;/span&gt;
    &lt;span class="c1"&gt;// or matched some important criteria (beware of timestamps&lt;/span&gt;
    &lt;span class="c1"&gt;// and variable bits in the requests)&lt;/span&gt;
    &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;curl_mockup_getRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;http://mockup/mock/children&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                                                &lt;span class="s"&gt;&amp;quot;id=root-folder&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;POST&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;CPPUNIT_ASSERT_EQUAL_MESSAGE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Wrong request  sent&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expectedRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I hope this testing experience can help others testing their HTTP client
application based on libcurl. Of course, something similar can be done with
other HTTP client libraries.&lt;/p&gt;</content><category term="ECM"></category><category term="CMIS"></category></entry><entry><title>libcmis 0.3.0 is out</title><link href="https://bosdonnat.fr/libcmis-0-3-0-is-out.html" rel="alternate"></link><published>2012-09-13T15:16:00+02:00</published><updated>2012-09-13T15:16:00+02:00</updated><author><name>Cédric Bosdonnat</name></author><id>tag:bosdonnat.fr,2012-09-13:/libcmis-0-3-0-is-out.html</id><summary type="html">&lt;p&gt;Libcmis 0.3.0 just hatched and will bring a whole lot of
change to the way you connect to your ECM. Here is are the cool new
features that were added in this version:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;WebService binding is implemented at the same level than the Atom
    binding&lt;/li&gt;
&lt;li&gt;The session factory …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;Libcmis 0.3.0 just hatched and will bring a whole lot of
change to the way you connect to your ECM. Here is are the cool new
features that were added in this version:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;WebService binding is implemented at the same level than the Atom
    binding&lt;/li&gt;
&lt;li&gt;The session factory has been improved to auto-guess the binding to
    use based on the provided URL&lt;/li&gt;
&lt;li&gt;libcmis-c provides a C wrapper API - &lt;em&gt;Thanks to SUSE hackweek&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Object move method has been implemented - &lt;em&gt;Thanks to &lt;a href="http://www.graudata.com/"&gt;Grau Data&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Versions handling has been implemented with the checkOut, checkIn,
    cancelCheckout and getAllVersions methods&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This new version of libcmis also comes with quite some fixes to support
&lt;a href="http://code.google.com/p/xcmis/"&gt;XCMIS&lt;/a&gt; and &lt;a href="http://www.cloudoku.com/"&gt;Cloudoku&lt;/a&gt; (thanks to GrauData) and SharePoint.&lt;/p&gt;
&lt;p&gt;You can download libcmis 0.3.0 on &lt;a href="https://sourceforge.net/projects/libcmis/"&gt;SourceForge.net&lt;/a&gt; as usual, or get
it for your beloved openSUSE on
&lt;a href="http://software.opensuse.org"&gt;http://software.opensuse.org&lt;/a&gt;.&lt;/p&gt;</content><category term="ECM"></category><category term="CMIS"></category><category term="ECM"></category></entry><entry><title>Alfresco and groups of admins</title><link href="https://bosdonnat.fr/alfresco-and-groups-of-admins.html" rel="alternate"></link><published>2008-06-26T11:42:00+02:00</published><updated>2008-06-26T11:42:00+02:00</updated><author><name>Cédric Bosdonnat</name></author><id>tag:bosdonnat.fr,2008-06-26:/alfresco-and-groups-of-admins.html</id><summary type="html">&lt;p&gt;I had to add groups of users as administrators to the Alfresco
configuration. As this is a common requested feature, I will explain how
I did it. This will also be a good example of how to tweak Alfresco
internal classes by overriding its Spring beans. Before reading further,
you …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I had to add groups of users as administrators to the Alfresco
configuration. As this is a common requested feature, I will explain how
I did it. This will also be a good example of how to tweak Alfresco
internal classes by overriding its Spring beans. Before reading further,
you should have read the &lt;a href="https://bosdonnat.fr/howto-create-a-new-alfresco-module.html"&gt;howto on Alfresco modules creation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In an &lt;code&gt;org.alfresco.sample&lt;/code&gt; package in the &lt;code&gt;source/java&lt;/code&gt; folder of the
module, add the following class. This class will subclass the default
Alfresco &lt;code&gt;AuthorityService&lt;/code&gt; implementation to change only the
&lt;code&gt;setAdminUsers()&lt;/code&gt; method defining the administrators from the Spring
configuration.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyAuthorityService&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;AuthorityServiceImpl&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;TransactionService&lt;/span&gt; &lt;span class="n"&gt;transactionService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setAdminUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt; &lt;span class="n"&gt;pConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;UserTransaction&lt;/span&gt; &lt;span class="n"&gt;txn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transactionService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUserTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;txn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="n"&gt;HashSet&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;HashSet&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="n"&gt;Iterator&lt;/span&gt; &lt;span class="n"&gt;iter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;iterator&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasNext&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;authority&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="n"&gt;AuthorityType&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AuthorityType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAuthorityType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authority&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AuthorityType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GROUP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;authorityExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authority&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="c1"&gt;// Get all the group&amp;#39;s users&lt;/span&gt;
                    &lt;span class="n"&gt;Set&lt;/span&gt; &lt;span class="n"&gt;groupLogins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getContainedAuthorities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AuthorityType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;USER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;authority&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;groupLogins&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authority&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setAdminUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;txn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;txn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rollback&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setTransactionService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TransactionService&lt;/span&gt; &lt;span class="n"&gt;pTransactionService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;transactionService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pTransactionService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now that the implementation is changed, we need to tell Alfresco to use
it instead of the default one. For this, add the following bean
definition to the &lt;code&gt;module-context.xml&lt;/code&gt; file. This Spring configuration
is a copy of the one in the &lt;code&gt;authority-service-context.xml&lt;/code&gt; file with
some changes to use our own implementation. As our implementation needs
the transaction service, it has been added as a property to the bean
configuration.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;authorityService&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;org.alfresco.sample.MyAuthorityService&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;authenticationComponent&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ref&lt;/span&gt; &lt;span class="na"&gt;bean=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;authenticationComponent&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/property&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;personService&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ref&lt;/span&gt; &lt;span class="na"&gt;bean=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;personService&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/property&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;nodeService&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ref&lt;/span&gt; &lt;span class="na"&gt;bean=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;nodeService&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/property&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;authorityDAO&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ref&lt;/span&gt; &lt;span class="na"&gt;bean=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;authorityDAO&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/property&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;permissionServiceSPI&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ref&lt;/span&gt; &lt;span class="na"&gt;bean=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;permissionServiceImpl&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/property&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;transactionService&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ref&lt;/span&gt; &lt;span class="na"&gt;bean=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;transactionService&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/property&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;adminUsers&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;set&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;value&amp;gt;&lt;/span&gt;admin&lt;span class="nt"&gt;&amp;lt;/value&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;value&amp;gt;&lt;/span&gt;GROUP_Administrators&lt;span class="nt"&gt;&amp;lt;/value&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/set&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/property&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It is now possible to set the full name of a groupe in the
administrators' list. In the example case, all the users of the
&lt;strong&gt;GROUP_Administrators&lt;/strong&gt; group will be administrators of Alfresco.  &lt;/p&gt;</content><category term="ECM"></category><category term="ECM"></category><category term="spring"></category></entry><entry><title>Howto create a new Alfresco module</title><link href="https://bosdonnat.fr/howto-create-a-new-alfresco-module.html" rel="alternate"></link><published>2008-06-17T08:41:00+02:00</published><updated>2008-06-17T08:41:00+02:00</updated><author><name>Cédric Bosdonnat</name></author><id>tag:bosdonnat.fr,2008-06-17:/howto-create-a-new-alfresco-module.html</id><summary type="html">&lt;p&gt;This post aims at explaining how to set up Eclipse to build a
new Alfresco module easily. Before continuing to read, be sure to have
downloaded Alfresco and its Software Development Kit (SDK). Of course
the following will assume that you have an installed Eclipse with the
J2EE plugins. This …&lt;/p&gt;</summary><content type="html">&lt;p&gt;This post aims at explaining how to set up Eclipse to build a
new Alfresco module easily. Before continuing to read, be sure to have
downloaded Alfresco and its Software Development Kit (SDK). Of course
the following will assume that you have an installed Eclipse with the
J2EE plugins. This article will not explain all the technical details on
AMP files, for more informations on this topic, please refer to the
&lt;a href="http://wiki.alfresco.com/wiki/AMP_Files"&gt;corresponding Alfresco Wiki page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This post will be composed of the following parts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Creating the project&lt;/li&gt;
&lt;li&gt;Useful settings for Alfresco development&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Creating the project&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;First we need to create a common Java project in Eclipse. What will be
interesting here is only how to structure the project and build it
easily. The only tricky thing during the project creation is to remove
the default source folder and replace it by two &lt;code&gt;source/java&lt;/code&gt; and
&lt;code&gt;config&lt;/code&gt; folders. Don't forget to add the Alfresco embedded SDK project
as a dependency of the new project.&lt;/p&gt;
&lt;p&gt;In the newly created project, create the following folders:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;source/web/jsp&lt;/code&gt;: this folder is mapped to the &lt;code&gt;jsp&lt;/code&gt; folder in the
    Alfresco WAR&lt;/li&gt;
&lt;li&gt;&lt;code&gt;source/web/scripts&lt;/code&gt;: this folder is mapped to the &lt;code&gt;scripts&lt;/code&gt; folder
    in the Alfresco WAR&lt;/li&gt;
&lt;li&gt;&lt;code&gt;source/web/images&lt;/code&gt;: this folder is mapped to the &lt;code&gt;images&lt;/code&gt; folder in
    the Alfresco WAR&lt;/li&gt;
&lt;li&gt;&lt;code&gt;source/web/css&lt;/code&gt;: this folder is mapped to the &lt;code&gt;css&lt;/code&gt; folder in the
    Alfresco WAR&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lib&lt;/code&gt;: this folder will contain all the third party dependencies to
    include in the AMP file&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WEB-INF&lt;/code&gt;: this folder will be mapped to the &lt;code&gt;WEB-INF&lt;/code&gt; folder of the
    Alfresco WAR.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now that the useful folders are created, we need to create the mandatory
files of an Alfresco module package. Before continuing, please choose an
identifier for the module: this will be needed in the next steps. For
this tutorial I will named the module &lt;code&gt;sample&lt;/code&gt;. The AMP file will need
to have a descriptor file. This one will be a &lt;code&gt;module.properties&lt;/code&gt; file
created at the project's root. This file will need to contain the
following properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;module.id&lt;/code&gt;: the chosen identifier for the module. In my case:
    &lt;code&gt;sample&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;module.version&lt;/code&gt;: the module version. Let's put &lt;code&gt;1.0&lt;/code&gt; for a first
    version, but don't forget to change it afterwards&lt;/li&gt;
&lt;li&gt;&lt;code&gt;module.title&lt;/code&gt;: a displayable title for the module&lt;/li&gt;
&lt;li&gt;&lt;code&gt;module.description&lt;/code&gt;: a longer description for the module&lt;/li&gt;
&lt;li&gt;&lt;code&gt;module.repo.version.min&lt;/code&gt;: the minimum required version of Alfresco&lt;/li&gt;
&lt;li&gt;&lt;code&gt;module.repo.version.max&lt;/code&gt;: the maximum possible version of Alfresco&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The module is almost ready, but there is still to add the
&lt;code&gt;module-context.xml&lt;/code&gt; file. This one will have to be placed in a
&lt;code&gt;alfresco.module.&amp;lt;your_id&amp;gt;&lt;/code&gt; package. In the example case, the file will
need to be created in a &lt;code&gt;alfresco.module.sample&lt;/code&gt; package in the &lt;code&gt;config&lt;/code&gt;
folder. This file only needs to contain the following content:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version=&amp;#39;1.0&amp;#39; encoding=&amp;#39;UTF-8&amp;#39;?&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE beans PUBLIC &amp;#39;-//SPRING//DTD BEAN//EN&amp;#39; &amp;#39;http://www.springframework.org/dtd/spring-beans.dtd&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;beans&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/beans&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;All the spring configuration can go in the &lt;code&gt;beans&lt;/code&gt; tag of this file.
However you can also place it in files ending with &lt;code&gt;-context.xml&lt;/code&gt; in a
&lt;code&gt;alfresco.extension&lt;/code&gt; package in the &lt;code&gt;source/java&lt;/code&gt; folder. All the Java
classes to package in a JAR and deploy with the AMP have to be placed
somewhere inside the &lt;code&gt;source/java&lt;/code&gt; folder.&lt;/p&gt;
&lt;p&gt;To make Alfresco use the &lt;code&gt;WEB-INF&lt;/code&gt; folder in the AMP file, you need to
add a new &lt;code&gt;file-mapping.properties&lt;/code&gt; file at the project's root
containing the following line. &lt;strong&gt;Do not use the &lt;code&gt;WEB-INF&lt;/code&gt; folder unless
you really know what you are doing!&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;/WEB-INF = /WEB-INF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now that all the important parts of the project are created we need to
write an ANT build file to transform this into a valid AMP file. The ANT
build file will need to know the path where to find the Alfresco SDK:
this will need to be configured in a &lt;code&gt;build.properties&lt;/code&gt; file. I won't
explain the details of the ANT build file as this is not an ANT
tutorial. However you will see that it is composed of the following
targets:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;clean&lt;/code&gt;: cleans the build results&lt;/li&gt;
&lt;li&gt;&lt;code&gt;compile&lt;/code&gt;: compile the Java code in the &lt;code&gt;source/java&lt;/code&gt; folder and
    copy the resources in the build output tree&lt;/li&gt;
&lt;li&gt;&lt;code&gt;package-jar&lt;/code&gt;: package the results of the &lt;code&gt;compile&lt;/code&gt; target into a
    JAR file&lt;/li&gt;
&lt;li&gt;&lt;code&gt;package-amp&lt;/code&gt;: package the JAR file, libraries, &lt;code&gt;WEB-INF&lt;/code&gt;, &lt;code&gt;config&lt;/code&gt;
    folders and configuration files into an AMP file&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The ANT build file is a &lt;code&gt;build.xml&lt;/code&gt; file at the project's root. This
file will contain the code shown by the following snippet. Of course it
can be changed to fit your needs, but don't forget to update the
project's structure if necessary.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;project&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Sample Module&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;default=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;package-amp&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;basedir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;project.dir&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;file=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${project.dir}/build.properties&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;file=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${project.dir}/module.properties&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;build.dir&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${project.dir}/build&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;config.dir&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${project.dir}/config&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;jar.file&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${build.dir}/lib/${module.id}.jar&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;amp.file&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${build.dir}/dist/${module.id}.amp&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;target&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;mkdirs&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;mkdir&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${build.dir}/dist&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;mkdir&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${build.dir}/lib&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;mkdir&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${build.dir}/classes&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/target&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;class.path&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;dirset&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${build.dir}&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;fileset&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${project.dir}/lib&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;includes=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;**/*.jar&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;fileset&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${alfresco.sdk.dir}/lib/server&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;includes=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;**/*.jar&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/path&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;target&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;clean&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;delete&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${build.dir}&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/target&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;target&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;compile&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;depends=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;mkdirs&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;      
        &lt;span class="nt"&gt;&amp;lt;javac&lt;/span&gt; &lt;span class="na"&gt;classpathref=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;class.path&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;debug=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${debug}&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;srcdir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${project.dir}/source/java&amp;quot;&lt;/span&gt; 
            &lt;span class="na"&gt;destdir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${build.dir}/classes&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1.5&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;encoding=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;UTF-8&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;copy&lt;/span&gt; &lt;span class="na"&gt;todir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${build.dir}/classes&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;fileset&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${project.dir}/source/java&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;defaultexcludes=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;exclude&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;**/*.java&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;exclude&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;**/.svn/**&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;exclude&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;**/CVS/**&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/fileset&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/copy&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/target&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;target&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;package-jar&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;depends=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;compile&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;jar&lt;/span&gt; &lt;span class="na"&gt;destfile=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${jar.file}&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;encoding=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;UTF-8&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;fileset&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${build.dir}/classes&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;excludes=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;**/custom*,**/*Test*&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;defaultexcludes=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;false&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/jar&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/target&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;target&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;package-amp&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;depends=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;package-jar&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;description=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Package the Module&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;zip&lt;/span&gt; &lt;span class="na"&gt;destfile=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${amp.file}&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;encoding=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;UTF-8&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;fileset&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${project.dir}/build&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;includes=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;lib/*.jar&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;fileset&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${project.dir}&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;includes=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;config/**/*.*&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;excludes=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;**/module.properties&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;fileset&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${project.dir}&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;include&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;module.properties&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;include&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;file-mapping.properties&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;include&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;WEB-INF/**/*&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;include&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;lib/**/*&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;exclude&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;WEB-INF/alfresco.tld&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;exclude&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;WEB-INF/repo.tld&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/fileset&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;zipfileset&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;source/web&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;prefix=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;web&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/zip&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/target&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/project&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The ANT build file will try to find some configuration in a
&lt;code&gt;build.properties&lt;/code&gt; file. This file will have to be created under the
project's root and have to contain the following properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;alfresco.sdk.dir&lt;/code&gt;: the absolute path to the Alfresco SDK to build
    the module for.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;debug&lt;/code&gt;: &lt;code&gt;true&lt;/code&gt; if the module should be build with the debugging
    symbols. This property is not mandatory.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Useful settings for Alfresco development&lt;br&gt;
&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now that the module is ready for development, here are some Eclipse
tricks to ease the Alfresco developement.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Copy the
    &lt;code&gt;tomcat/webapps/alfresco/WEB-INF/classes/alfresco/model/modelSchema.xsd&lt;/code&gt;
    into the SDK folder and add it to the Eclipse XML Catalog in &lt;em&gt;Window
    &gt; Preferences&lt;/em&gt;. This schema doesn't cover the constraints in
    Alfresco model definitions, but it saves a lot of time fixing dummy
    syntax errors or typos.&lt;/li&gt;
&lt;li&gt;You can do the same with the
    &lt;code&gt;tomcat/webapps/alfresco/WEB-INF/classes/alfresco/auditSchema.xsd&lt;/code&gt;
    file.&lt;/li&gt;
&lt;li&gt;Copy the &lt;code&gt;alfresco.tld&lt;/code&gt; and &lt;code&gt;repo.tld&lt;/code&gt; files into the &lt;code&gt;WEB-INF&lt;/code&gt;
    folder of your project. This will provide auto-completion for the
    Alfresco tags when writing your JSP pages.&lt;/li&gt;
&lt;li&gt;Install the Eclipse plugin for FreeMarker support: it helps a lot to
    write template and webscripts.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the created module project and some Eclipse configuration, you are
now ready for Alfresco extensions development. You can still improve the
ANT build file by adding some target to auto-deploy your changes...
Don't forget to have a look at the post explaining &lt;a href="https://bosdonnat.fr/debugging-an-alfresco-extension.html"&gt;how to debug an
Alfresco extension&lt;/a&gt;: this can save a lot of time too during your
module development.&lt;/p&gt;</content><category term="ECM"></category><category term="ECM"></category></entry><entry><title>Debugging an Alfresco extension</title><link href="https://bosdonnat.fr/debugging-an-alfresco-extension.html" rel="alternate"></link><published>2008-06-10T08:45:00+02:00</published><updated>2008-06-10T08:45:00+02:00</updated><author><name>Cédric Bosdonnat</name></author><id>tag:bosdonnat.fr,2008-06-10:/debugging-an-alfresco-extension.html</id><summary type="html">&lt;p&gt;You may remember that I have written a post on &lt;a href="https://bosdonnat.fr/debugging-an-ooo-extension-with-eclipse.html"&gt;how to debug
an OpenOffice.org extension&lt;/a&gt;. This post is about to explain how to do
the same for an Alfresco extension. In fact the principle is the same.
To set Alfresco in a debug mode, edit the &lt;code&gt;tomcat/bin …&lt;/code&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;You may remember that I have written a post on &lt;a href="https://bosdonnat.fr/debugging-an-ooo-extension-with-eclipse.html"&gt;how to debug
an OpenOffice.org extension&lt;/a&gt;. This post is about to explain how to do
the same for an Alfresco extension. In fact the principle is the same.
To set Alfresco in a debug mode, edit the &lt;code&gt;tomcat/bin/startup.sh&lt;/code&gt; file
and change the last line into:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$PRGDIR&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;/&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$EXECUTABLE&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; jpda start &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The next time Alfresco is started it will be listening on the 8000 port.
Then you will be able to set up the Eclipse debugging session in the
same way than the one I described in the post on OOo extension
debugging.&lt;/p&gt;
&lt;p&gt;To avoid lengthy Alfresco restarts when you change some code, you can
unset the automatic build, and use the &lt;strong&gt;Project &gt; Build All&lt;/strong&gt; menu for
a hot replace of code. This doesn't work when you have changed the
signature of a method or of a class. There are some cases where it
doesn't work... but I still haven't identified why it sometimes fails. I
only have noticed that you shouldn't change code when the debug session
isn't running or when you are stepping in the code.&lt;/p&gt;</content><category term="ECM"></category><category term="ECM"></category></entry><entry><title>Removing My Alfresco</title><link href="https://bosdonnat.fr/removing-my-alfresco.html" rel="alternate"></link><published>2008-06-09T16:24:00+02:00</published><updated>2008-06-09T16:24:00+02:00</updated><author><name>Cédric Bosdonnat</name></author><id>tag:bosdonnat.fr,2008-06-09:/removing-my-alfresco.html</id><summary type="html">&lt;p&gt;I needed to remove the &lt;strong&gt;My Alfresco&lt;/strong&gt; part in Alfresco
Navigator. This is a piece of JSF hack that I'll share here. The way it
is done here isn't the way it should be done in order to properly
package it... but it's a hack.&lt;/p&gt;
&lt;p&gt;Copy the source code of …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I needed to remove the &lt;strong&gt;My Alfresco&lt;/strong&gt; part in Alfresco
Navigator. This is a piece of JSF hack that I'll share here. The way it
is done here isn't the way it should be done in order to properly
package it... but it's a hack.&lt;/p&gt;
&lt;p&gt;Copy the source code of the
&lt;code&gt;org.alfresco.web.ui.repo.component.UINavigator&lt;/code&gt; class and remove the
following blocks:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;treePanel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;areaTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NavigationBean&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;MSG_MYALFRESCO&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;and&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NavigationBean&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LOCATION_MYALFRESCO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;area&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;encodeSidebarButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sideBarStyle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;NavigationBean&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LOCATION_MYALFRESCO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;NavigationBean&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;MSG_MYALFRESCO&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Compile the Java class and put the result into a JAR file. Then place
the jar file into the &lt;code&gt;WEB-INF/lib&lt;/code&gt; folder and restart Alfresco.&lt;/p&gt;
&lt;p&gt;Of course you should also remove the tag corresponding to &lt;strong&gt;My
Alfresco&lt;/strong&gt; in the &lt;code&gt;jsp/parts/titlebar.jsp&lt;/code&gt; page to remove the link from
the page.&lt;/p&gt;</content><category term="ECM"></category><category term="ECM"></category></entry><entry><title>Alfresco Database schema</title><link href="https://bosdonnat.fr/alfresco-database-schema.html" rel="alternate"></link><published>2008-06-05T08:32:00+02:00</published><updated>2008-06-05T08:32:00+02:00</updated><author><name>Cédric Bosdonnat</name></author><id>tag:bosdonnat.fr,2008-06-05:/alfresco-database-schema.html</id><summary type="html">&lt;p&gt;I'm often looking for some precise informations in Alfresco
database. This is quite hard when you don't have a graph showing the
database schema.&lt;/p&gt;
&lt;p&gt;I have recently discovered that &lt;a href="http://squirrel-sql.sourceforge.net"&gt;SQuirreL SQL&lt;/a&gt; could help me in this
task. Select each table to show in the graph, right-clic and select
&lt;strong&gt;Add to …&lt;/strong&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;I'm often looking for some precise informations in Alfresco
database. This is quite hard when you don't have a graph showing the
database schema.&lt;/p&gt;
&lt;p&gt;I have recently discovered that &lt;a href="http://squirrel-sql.sourceforge.net"&gt;SQuirreL SQL&lt;/a&gt; could help me in this
task. Select each table to show in the graph, right-clic and select
&lt;strong&gt;Add to graph&lt;/strong&gt;. There is now only to reorganize the graph manually to
make it readable. The graph can be renamed and saved with the contextual
menu of the graph.&lt;/p&gt;
&lt;p&gt;Here is a picture showing Alfresco database schema created using this
method.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://bosdonnat.fr/data/alfresco/schema_bd_alfresco.jpg"&gt;&lt;img alt="Alfresco database schema" src="https://bosdonnat.fr/data/alfresco/preview_schema_bd_alfresco.jpg"&gt;&lt;/a&gt;&lt;/p&gt;</content><category term="ECM"></category><category term="ECM"></category></entry><entry><title>Toggle Alfresco in a read-only mode</title><link href="https://bosdonnat.fr/toggle-alfresco-in-a-read-only-mode.html" rel="alternate"></link><published>2008-06-04T18:35:00+02:00</published><updated>2008-06-04T18:35:00+02:00</updated><author><name>Cédric Bosdonnat</name></author><id>tag:bosdonnat.fr,2008-06-04:/toggle-alfresco-in-a-read-only-mode.html</id><summary type="html">&lt;p&gt;Have you ever wondered how to keep Alfresco running while
backing it up? As you may have found it, Alfresco database and data
filesystem have to be saved in a coherent state. For this, Alfresco
should be turned off, or in a read-only mode. A read-only mode is also
useful …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Have you ever wondered how to keep Alfresco running while
backing it up? As you may have found it, Alfresco database and data
filesystem have to be saved in a coherent state. For this, Alfresco
should be turned off, or in a read-only mode. A read-only mode is also
useful for some maintainance operations.&lt;/p&gt;
&lt;p&gt;On Alfresco 1.4, I could put it in a read-only mode by changing the
&lt;code&gt;transactions.properties&lt;/code&gt; file and restarting Alfresco. This doesn't
work on Alfresco 2.1 as Alfresco tries to write some informations in the
system repositories during the bootstrap. Thus the only way to set it in
a read-only mode is to do it without stopping it, by interacting with
the &lt;code&gt;TransactionService&lt;/code&gt;. This post is about to explain how to create a
webscript to toggle Alfresco in read-only or read-write mode.  &lt;/p&gt;</content><category term="ECM"></category><category term="ECM"></category></entry><entry><title>Who's using my Alfresco?</title><link href="https://bosdonnat.fr/whos-using-my-alfresco.html" rel="alternate"></link><published>2008-05-31T19:25:00+02:00</published><updated>2008-05-31T19:25:00+02:00</updated><author><name>Cédric Bosdonnat</name></author><id>tag:bosdonnat.fr,2008-05-31:/whos-using-my-alfresco.html</id><summary type="html">&lt;p&gt;Every shared file server administrator has this problem: "who
is taking most of the space?". This question is also a valid one for
Alfresco administrators, but they do not have any easy tool to answer
it. Adding this feature to Alfresco isn't very hard but for those who
prefer reusing …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Every shared file server administrator has this problem: "who
is taking most of the space?". This question is also a valid one for
Alfresco administrators, but they do not have any easy tool to answer
it. Adding this feature to Alfresco isn't very hard but for those who
prefer reusing the others work, I will present a piece of Freemarker
template doing it. This template will be also a good way to introduce
interesting Alfresco Freemarker use.&lt;/p&gt;
&lt;p&gt;First, here is a preview of the final result.&lt;br&gt;
&lt;a href="https://bosdonnat.fr/data/alfresco/shot-alf-size.png"&gt;&lt;img alt="Preview of the space size template" src="https://bosdonnat.fr/data/alfresco/shot-alf-size.miniature.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I will present the template file in two steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Showing a table with the current space children and their total size&lt;/li&gt;
&lt;li&gt;Showing the same information as a pie chart&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;STEP 1: Showing the table&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;First of all, having a function returning the total size of a space is
necessary. This function will have to recurse over the whole hierarchy
to compute the real size of the space. The following piece of Freemarker
code defines this function and can be called either on a container or on
a leaf of the tree.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;&amp;lt;#function getSize node&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt;    &amp;lt;#assign sum = 0/&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt;    &amp;lt;#if node.children?size = 0&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt;        &amp;lt;#assign sum = node.size/&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt;    &amp;lt;#else&amp;amp;gt;&lt;/span&gt;
&lt;span class="err"&gt;        &amp;lt;#list node.children as child&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt;            &amp;lt;#assign sum = sum + getSize(child)/&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt;        &amp;lt;!--#list--&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt;    &amp;lt;!--#if--&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt;    &amp;lt;#return sum /&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt;&amp;lt;!--#function--&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now that the function computing a node's real size is written, the
template showing the table is easy to do. Here is a way to do it like
the screenshot. The only noticeable point in this code could be the way
to alternate the CSS class for the data rows.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;table&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;recordSet&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;border=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;cellspacing=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;cellpadding=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;100%&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;tbody&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;th&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;recordSetHeader&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;padding: 2px; text-align: left;&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Node&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;th&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;recordSetHeader&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;padding: 2px; text-align: left;&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Size (in Byte)&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
        &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;#if document?exists&amp;gt;
        &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;recordSetRow&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;getSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
        &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;#else&amp;gt;
        &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;#assign i = 0/&amp;gt;
        &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;#list space.children as child&amp;gt;
        &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;td&lt;/span&gt; &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;padding: 2px; text-align: left;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class="s"&gt;            &amp;lt;td style=&amp;quot;padding:&lt;/span&gt; &lt;span class="err"&gt;2px;&lt;/span&gt; &lt;span class="err"&gt;text-align:&lt;/span&gt; &lt;span class="err"&gt;left;&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;getSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
        &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;#assign i = i + 1 /&amp;gt;
        &lt;span class="c"&gt;&amp;lt;!--#list--&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!--#if--&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;STEP 2: Showing the pie chart&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To show a chart, an existing library for charts creation will be
necessary. I have chosen to use &lt;a&gt;PlotKit&lt;/a&gt; Javascript library. This
library depends on the &lt;a&gt;MochiKit&lt;/a&gt; Javascript library. There is an
example of chart with labels among the PlotKit examples to know how to
create the pie chart with the children names as labels. The problem is
that the JavaScript function used to create the chart will need the data
and these ones can't be computed another time for obvious performance
reasons.&lt;/p&gt;
&lt;p&gt;The previously written function will have to be reused to produce the
JavaScript function. In order to reuse the data for both the chart and
the table, the data have to be put in a Freemarker sequence. But as
creating an empty Freemarker sequence and fill it in a loop doesn't seem
to be possible, the only solution is to create the Freemarker definition
of the sequence and evaluate it. Here is how to do it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;#&lt;/span&gt;&lt;span class="n"&gt;assign&lt;/span&gt; &lt;span class="n"&gt;ftlArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;[&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;#&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="k"&gt;exists&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;#&lt;/span&gt;&lt;span class="n"&gt;assign&lt;/span&gt; &lt;span class="n"&gt;ftlArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;[[&amp;quot;&amp;quot; + document.name + &amp;quot;&amp;quot;,&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;getSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;]]&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;#&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;#&lt;/span&gt;&lt;span class="n"&gt;assign&lt;/span&gt; &lt;span class="k"&gt;first&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;#&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="k"&gt;space&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;#&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;first&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;#&lt;/span&gt;&lt;span class="n"&gt;assign&lt;/span&gt; &lt;span class="n"&gt;ftlArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ftlArray&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;,&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;!&lt;/span&gt;&lt;span class="c1"&gt;--#if--&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;#&lt;/span&gt;&lt;span class="n"&gt;assign&lt;/span&gt; &lt;span class="n"&gt;ftlArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ftlArray&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;[&amp;quot;&amp;quot; + child.name + &amp;quot;&amp;quot;,&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;getSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;]&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;#&lt;/span&gt;&lt;span class="n"&gt;assign&lt;/span&gt; &lt;span class="k"&gt;first&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;!&lt;/span&gt;&lt;span class="c1"&gt;--#list--&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;#&lt;/span&gt;&lt;span class="n"&gt;assign&lt;/span&gt; &lt;span class="n"&gt;ftlArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ftlArray&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;]&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;!&lt;/span&gt;&lt;span class="c1"&gt;--#if--&amp;gt;&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;#&lt;/span&gt;&lt;span class="n"&gt;assign&lt;/span&gt; &lt;span class="k"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ftlArray&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;eval&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After this Freemarker code, the &lt;code&gt;values&lt;/code&gt; variable will contain the data
as a sequence of sequences. The JavaScript function to add in the
template and the HTML tag for the chart rendering are done in the
following way. For it to work, the files provided in the &lt;code&gt;lib/MochiKit&lt;/code&gt;
directory of the MochiKit distribution and the files found in the
&lt;code&gt;PlotKit&lt;/code&gt; directory of the MochiKit distribution have to be placed in
&lt;code&gt;/scripts/mochikit&lt;/code&gt; and &lt;code&gt;/scripts/plotkit&lt;/code&gt; in the alfresco WAR.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/alfresco/scripts/mochikit/MochiKit.js&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="nx"&gt;mce&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/alfresco/scripts/plotkit/excanvas.js&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="nx"&gt;mce&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/alfresco/scripts/plotkit/Base.js&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="nx"&gt;mce&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/alfresco/scripts/plotkit/Layout.js&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="nx"&gt;mce&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/alfresco/scripts/plotkit/Canvas.js&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="nx"&gt;mce&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/alfresco/scripts/plotkit/SweetCanvas.js&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="nx"&gt;mce&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="nx"&gt;mce&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The chart will be rendered in the canvas element. The code shown in the
first step for the table printing has to be adapted to use the &lt;code&gt;values&lt;/code&gt;
variable instead of using directly the &lt;code&gt;getSize()&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;In order to use the template, place it in the
&lt;code&gt;Data Dictionary/Presentation Templates&lt;/code&gt; space in Alfresco. Then simply
apply the template on the space for which to get the table and chart.&lt;/p&gt;
&lt;p&gt;Here are some useful links to create more templates like this one for
Alfresco:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a&gt;Freemarker reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a&gt;Alfresco Freemarker guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a&gt;Alfresco Freemarker cookbook&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="ECM"></category><category term="ECM"></category></entry><entry><title>Alfresco and categories</title><link href="https://bosdonnat.fr/alfresco-and-categories.html" rel="alternate"></link><published>2008-05-23T20:15:00+02:00</published><updated>2008-05-23T20:15:00+02:00</updated><author><name>Cédric Bosdonnat</name></author><id>tag:bosdonnat.fr,2008-05-23:/alfresco-and-categories.html</id><summary type="html">&lt;p&gt;Have you ever counted the number of clics needed to select a
Category on a document in Alfresco? The user interface for the category
selection was really hard to understand for a normal user up to in the
2.x series and will be improved in the 3.0 version …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Have you ever counted the number of clics needed to select a
Category on a document in Alfresco? The user interface for the category
selection was really hard to understand for a normal user up to in the
2.x series and will be improved in the 3.0 version. This can already be
tested in the 2.9 Beta version.&lt;/p&gt;
&lt;p&gt;I have worked on a little test with &lt;a href="http://www.jboss.org/jbossrichfaces/"&gt;RichFaces&lt;/a&gt; to make it better.
When I hear that the 2.9 had changed the categories selection I needed
to see how it was done... It's better than the previous interface but
not yet perfect for me: my test is still useful.&lt;/p&gt;
&lt;p&gt;My test presents the categories as a tree in a modal dialog. Here is a
screenshot to better understand what I am talking about.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://bosdonnat.fr/data/alfresco/screenshot1.png"&gt;&lt;img alt="Alfresco categories test screenshot" src="https://bosdonnat.fr/data/alfresco/screenshot1.miniature.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As you can guess this is a test on a blank page... it still needs to be
integrated but it looks promising. To make it work I am using a
combination of the JSF RichFaces taglib and WebScripts.&lt;/p&gt;
&lt;p&gt;The next steps are&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;to support list of categories&lt;/li&gt;
&lt;li&gt;to embed all the JSF part into a tag lib to make it easier to embed
    everywhere&lt;/li&gt;
&lt;li&gt;test it as a replacement for Alfresco standard categories selection
    UI&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That said Alfresco 2.9 has a nice feature around the categories. In the
left panel you can show the list of your document sorted in the
categories tree...&lt;/p&gt;
&lt;p&gt;Useful link: &lt;a href="http://livedemo.exadel.com/richfaces-demo/index.jsp"&gt;the RichFaces live demo&lt;/a&gt;.&lt;/p&gt;</content><category term="ECM"></category><category term="ECM"></category></entry><entry><title>Changing Alfresco Breadcrumb</title><link href="https://bosdonnat.fr/changing-alfresco-breadcrumb.html" rel="alternate"></link><published>2008-05-23T08:05:00+02:00</published><updated>2008-05-23T08:05:00+02:00</updated><author><name>Cédric Bosdonnat</name></author><id>tag:bosdonnat.fr,2008-05-23:/changing-alfresco-breadcrumb.html</id><summary type="html">&lt;p&gt;Since I am configuring and installing Alfresco for customers I
have a remark about the breadcrumb. Many of the customers want it to be
a path showing the current node location instead of the default
breadcrumb. In fact it behaves like a path if you are using only the
browsing …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Since I am configuring and installing Alfresco for customers I
have a remark about the breadcrumb. Many of the customers want it to be
a path showing the current node location instead of the default
breadcrumb. In fact it behaves like a path if you are using only the
browsing interface, but not if you are using the navigator on the left.
This is often seen as a bug by the users.&lt;/p&gt;
&lt;p&gt;The good news is that Alfresco breadcrumb will be configurable in
version 3.0. This feature is already present in Alfresco 2.9. The &lt;a href="http://wiki.alfresco.com/wiki/Web_Client_Customisation_FAQ#Changing_Breadcrumb_Mode"&gt;Web
client customisation FAQ&lt;/a&gt; page from the Alfresco Wiki explains how to
configure it. However, if you want this feature on a previous version of
Alfresco this can also be done... even if it is a bit more tricky.&lt;/p&gt;
&lt;p&gt;To do this, you will have to override the
&lt;code&gt;org.alfresco.web.ui.common.renderer.BreadcrumbRenderer&lt;/code&gt; class and
implement the &lt;code&gt;encodeBegin()&lt;/code&gt; method yourself by using the
&lt;code&gt;NavigatorBean.getCurrentNode()&lt;/code&gt; method and the &lt;code&gt;NodeService&lt;/code&gt;. To make
Alfresco use your renderer instead of the defaults, don't forget to add
something like the following section in the &lt;code&gt;faces-config-custom.xml&lt;/code&gt;
file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;render-kit&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;renderer&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;component-family&amp;gt;&lt;/span&gt;org.alfresco.faces.Controls&lt;span class="nt"&gt;&amp;lt;/component-family&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;renderer-type&amp;gt;&lt;/span&gt;org.alfresco.faces.BreadcrumbRenderer&lt;span class="nt"&gt;&amp;lt;/renderer-type&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;renderer-class&amp;gt;&lt;/span&gt;some.company.alfresco.MyBreadcrumbRenderer&lt;span class="nt"&gt;&amp;lt;/renderer-class&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/renderer&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/render-kit&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And do not forget to change the class name in this small XML code...  &lt;/p&gt;</content><category term="ECM"></category><category term="ECM"></category></entry><entry><title>Using webscripts to extend Alfresco Web client</title><link href="https://bosdonnat.fr/using-webscripts-to-extend-alfresco-web-client.html" rel="alternate"></link><published>2008-05-18T23:39:00+02:00</published><updated>2008-05-18T23:39:00+02:00</updated><author><name>Cédric Bosdonnat</name></author><id>tag:bosdonnat.fr,2008-05-18:/using-webscripts-to-extend-alfresco-web-client.html</id><summary type="html">&lt;p&gt;Alfresco Webscripts are really easy to code and can help to do
many things (but not the coffee yet). They can even be used to create
new dialogs in Alfresco, for example to show some custom informations.
This post will explain how to setup a simple mechanism to help creating …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Alfresco Webscripts are really easy to code and can help to do
many things (but not the coffee yet). They can even be used to create
new dialogs in Alfresco, for example to show some custom informations.
This post will explain how to setup a simple mechanism to help creating
Alfresco dialogs based on webscript with only an action configuration.&lt;/p&gt;
&lt;p&gt;The steps are the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a generic dialog configured in &lt;code&gt;web-client-config-custom.xml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create the Webscript to display in the dialog&lt;/li&gt;
&lt;li&gt;Create the action configuration to display the dialog with the
    webscript&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In this post, I will assume that you already have a webscript to show
and that you are already quite used to Alfresco extensions developement:
these could be topics for some other posts and are well explained on
Alfresco Wiki.  &lt;/p&gt;</content><category term="ECM"></category><category term="ECM"></category><category term="web"></category></entry><entry><title>Alfresco Webscripts contest</title><link href="https://bosdonnat.fr/alfresco-webscripts-context.html" rel="alternate"></link><published>2008-03-24T18:46:00+01:00</published><updated>2008-03-24T18:46:00+01:00</updated><author><name>Cédric Bosdonnat</name></author><id>tag:bosdonnat.fr,2008-03-24:/alfresco-webscripts-context.html</id><summary type="html">&lt;p&gt;Only 7 days before the end of the first period of the Alfresco Webscript
contest. Alfresco has launched a context to stimulate the creation of
nice and useful webscripts from the community. You can read the
&lt;a href="http://www.alfresco.com/partners/programme/webscripts/"&gt;Alfresco contest page&lt;/a&gt; to get more informations on this context.&lt;/p&gt;
&lt;p&gt;During my previous missions …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Only 7 days before the end of the first period of the Alfresco Webscript
contest. Alfresco has launched a context to stimulate the creation of
nice and useful webscripts from the community. You can read the
&lt;a href="http://www.alfresco.com/partners/programme/webscripts/"&gt;Alfresco contest page&lt;/a&gt; to get more informations on this context.&lt;/p&gt;
&lt;p&gt;During my previous missions an Alfresco, customers often complains that
there is no tool to easily view the permissions of a given user. In the
Alfresco web client, the administrator has to navigate to the space or
document, look for the permissions and possibily needs to look at the
permissions set on the parent spaces. I submitted a webscript for this
problem to the contest. This Alfresco WebScript shows all the
permissions of the selected user on the content. If you click on the
permissions summary you even have all the roles set for the user.&lt;/p&gt;
&lt;p&gt;Here is a screenshot of the webscript:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Admin webscript screenshot" src="https://bosdonnat.fr/data/alfresco/alfresco-admin.png"&gt;&lt;/p&gt;
&lt;p&gt;The WebScript module can be downloaded from here:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://bosdonnat.fr/data/alfresco-admin.amp"&gt;alfresco-admin.amp&lt;/a&gt;&lt;/p&gt;</content><category term="ECM"></category><category term="ECM"></category></entry><entry><title>My first post on Alfresco</title><link href="https://bosdonnat.fr/my-first-post-on-alfresco.html" rel="alternate"></link><published>2008-03-10T10:03:00+01:00</published><updated>2008-03-10T10:03:00+01:00</updated><author><name>Cédric Bosdonnat</name></author><id>tag:bosdonnat.fr,2008-03-10:/my-first-post-on-alfresco.html</id><summary type="html">&lt;p&gt;Even if I'm working on &lt;a href="http://alfresco.com/"&gt;Alfresco&lt;/a&gt; projects for a little bit
more than one year, I haven't posted any message on this development
adventure. Today will be the first post on that topic but maybe not the
only one.&lt;/p&gt;
&lt;p&gt;To get introduced to Alfresco development it takes quite a long …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Even if I'm working on &lt;a href="http://alfresco.com/"&gt;Alfresco&lt;/a&gt; projects for a little bit
more than one year, I haven't posted any message on this development
adventure. Today will be the first post on that topic but maybe not the
only one.&lt;/p&gt;
&lt;p&gt;To get introduced to Alfresco development it takes quite a long time
because of the numerous extension points and concepts to learn. A good
starting point is to read the &lt;a href="http://wiki.alfresco.com/wiki/Developer_Guide"&gt;Developers guide on the wiki&lt;/a&gt;. However,
unlike many other internet resources you will need to read it quite
sequentially if you want to understand everything... otherwise you will
be told about Data Dictionary and Model and you won't know what it is
(this is an example).&lt;/p&gt;
&lt;p&gt;There are several ways to extend Alfresco. The following ones are some
examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Extend or customize the Web Client using JSF development or Alfresco
    actions creation&lt;/li&gt;
&lt;li&gt;Create jBPM workflows, Javascript automated rules, Java behaviour
    policies&lt;/li&gt;
&lt;li&gt;Extend the existing Data Model to match your needs&lt;/li&gt;
&lt;li&gt;Extend the Alfresco Core using Spring beans&lt;/li&gt;
&lt;li&gt;Extend the remote API using WebScripts and defining your own REST
    API&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I will certainly detail some interesting development points or existing
Alfresco extensions in next posts: stay tuned...  &lt;/p&gt;</content><category term="ECM"></category><category term="ECM"></category><category term="web"></category></entry></feed>