An Alfresco Developer’s Challenge and Journey

An idea (lit bulp)

Alfresco is a very flex­i­ble content-platform in gen­eral. It pro­vides mech­a­nisms to cus­tomize almost every com­po­nent (Spring-Bean, Web­script, Tem­plates) shipped with the core product.

Still, some­times the tech­ni­cal solu­tion does not prove to be even close to what the devel­oper had in mind. This post is about a recent per­sonal chal­lenge and the jour­ney to the solu­tion in an Alfresco Share cus­tomiza­tion project tar­get­ing ver­sion 3.4.

Busi­ness Requirements

The project con­sisted of var­i­ous sto­ries. One was about cus­tomiza­tion of the Share invi­ta­tion email with the fol­low­ing requirements:

  • As a Site-Manager, we want an optional per­sonal mes­sage to be included in the invitation-email.
  • As a Site-Manager, we want to receive invi­tee read-receipts for invitation-emails
  • As a Site-Manager, we want the com­pany logo to appear in the invi­ta­tion email.

The cus­tomer was fairly prag­matic – require­ments imple­mented quickly and decently priced being far more impor­tant than edu­ca­tional value of the code. Hence, it was ok to apply these cus­tomiza­tions on a global level - to all share sites with no fur­ther scop­ing. That all sounded rea­son­ably to me and I was con­fi­dent to get it imple­mented “properly”.

The project was of type fixed-scope and fixed-price. A No-Go due to Heisenberg’s uncer­tainty prin­ci­ple – sure, but there was no way around.

Now, if you are an Alfresco devel­oper read­ing this, please take a minute vir­tu­ally out­lin­ing your solu­tion and make a rough effort esti­ma­tion before pro­ceed­ing with solu­tion jour­ney on the next page. But even if you have no clue what Alfresco is, it might be worth read­ing further.

 
Dieser Eintrag wurde veröffentlicht in Alfresco, Spring und verschlagwortet mit , von Andreas Steffan. Permanenter Link zum Eintrag.

Über Andreas Steffan

Freelance Java-Platform and Content-Management Architect / Web-Geek / Code-Mixer / Alfresco-, Grails and Linux Evangelist / Groovy- and Clojure-Fanboy / Javascript-and Wordpress-Cherrypicker / Scala-Sceptic / Emacs-Veteran / Content-Gourmet and -Cook / Agilo / Conference-Tourist / Physicist / Father / Japanese Kitchen Explorer / BBQ-Chef / Wine-Drinker / Photographer-Wannabe / Elektronica- and Frisbee-Friend / Hammock- and Backyard-Chiller / Asia-, Outdoor and Scuba-Diving-Traveller

7 Gedanken zu “An Alfresco Developer’s Challenge and Journey

  1. Hi Andreas,
    mmmh — really dirty, isn’t it?
    mod­i­fy­ing the processs­de­f­i­n­i­tion is OK, but why didn’t you add a tiny Javascript exten­sion to replace org.alfresco.repo.site.script.Site.inviteNominated?

  2. Hi Jan,

    I tried to make clear that the solu­tion intro­duced may not be the most beau­ti­ful one in the world and I’m not proud of it.

    org.alfresco.repo.site.script.Site.inviteNominated calls

    pub­lic Nom­i­nate­d­In­vi­ta­tion inviteNom­i­nated(
    String invi­teeUser­Name,
    Invitation.ResourceType resource­Type,
    String resource­Name,
    String invi­tee­Role,
    String server­Path,
    String accep­tUrl,
    String rejectUrl) ;

    defined by Invi­ta­tion­Ser­vice (inter­face) imple­mented in Invi­ta­tion­Ser­vi­ceImpl. Para­me­ters seman­tics look fairly strict to me and I don’t see a clean way to get the addi­tional infor­ma­tion through here.

    Or are you sug­gest­ing to bypass InvitationService ?

  3. Hi,
    no, not bypass­ing:
    1.) cus­tom JS exten­sion with a method appro­pri­ate to your para­me­ters & calls Cus­tom­Site­Ser­vi­ceImpl (= bean site­Ser­vice)
    2) Cus­tom­Site­Ser­vice exten­tends Site­Ser­vi­ceImpl & declares cus­tom inviteNom­i­nated method
    3.) Cus­tom­Site­Ser­vi­ceImpl extends Site­Ser­vi­ceImpl, imple­ments Cus­tom­Site­Ser­vice with imple­mented cus­tom invi­ta­tion logic…

  4. Ok, but pro­vid­ing a cus­tom inviteNom­i­nated method effec­tively bypasses dec­la­ra­tions of the inter­face, right ?

    That would have been fine with me in this case — Javascript does not care about inter­faces any­ways. I even con­sid­ered doing this in the beginning.

    Abon­doned the idea because I felt bypass­ing an inter­face is ugly and con­fus­ing. :) Besides the method doing the heavy-lifting in Invi­ta­tion­Ser­vi­ceImpl (as shipped) is

    pri­vate Nom­i­nate­d­In­vi­ta­tion startNominatedInvite(…)

    It has almost the same para­me­ters as inviteNom­i­nated and rougly 250 LOC, so this class does not really make a good can­di­date for subclassing.

    That was the time I con­cluded it would be over­all eas­ier and safer to abuse a String para­me­ter. :) I chose accep­tUrl because I was fairly sure, its only pur­pose is to get ren­dered into the email.

    Either way, at this point you are only half way down the rabbit-hole, you still have to pass the BPM layer, ren­der the mail text, and set head­ers and content-type.

    Thanks for commenting.

  5. Nice exposé about the draw­backs of a pretty hard-set/-coded inter­face and work­flow. This reminds me of the efforts that we once had to put into adding cus­tom per­mis­sions to an Alfresco sys­tem, restrict­ing what kind of site roles could invite other users using role-based restricted lists of invi­tee roles to choose from.

    Con­sid­er­ing the project para­me­ters you explained I find it an accept­able solu­tion. In terms of using the accep­tUrl as your “trans­port medium” I would tend towards using the trans­ac­tion con­text instead (Alfres­co­Trans­ac­tion­Sup­port instead of the men­tioned ThreadLocal).

    I per­son­ally do not like cus­tom exten­sions of Alfresco ser­vices as I have seen too many exam­ples that vio­late inter­nal ser­vice con­tracts. Facad­ing in com­bi­na­tion with trans­ac­tion con­text data or imple­ment­ing a con­tributable patch to the OOTB ser­vice are my pre­ferred options. In terms of the Invi­ta­tion­Ser­vice I could see a sim­ple API exten­sion which would allow pass­ing of a cus­tom data / prop­erty map, pro­vide a “map-to-workflow map­per strat­egy” and a “mail / noti­fi­ca­tion action” exten­sion point (del­e­gat­ing based on site type / state evaluators).

  6. Thanks for your feed­back, Axel.

    Funny, it reminds you of secu­rity related efforts you had. I am right now fac­ing require­ments to extend the Share Site secu­rity model. :)

    For the par­tic­u­lar case of the Invi­ta­tion­Ser­vice, it might indeed make sense to widen the tight inter­face we have today and work out a longer term solu­tion. But an approach like that is of course not fea­si­ble in most real world projects.

    Hon­estly — the more I think about it, the more I real­ize that “hacks” in gen­eral (i.e. not only in Alfresco envi­ron­ments) are actu­ally fairly com­mon. Truth is, that I am now exer­cis­ing all kinds of nasty Javascript while imple­ment­ing the new secu­rity requirements.

    In the end, I guess a big share of these prob­lems boils down to the nature of the tools we are given — the Java type sys­tem, acces­si­bil­ity mod­i­fiers (pri­vate, pack­age, final) and so on. For me, these tend to get in the way quite often. That is why I like “tools” such as dynam­i­cally typed lan­guages in cus­tomiza­tion projects.

    Maybe I’ll start a “best hacks” or “worst prac­tice” post series. ;)

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

*

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>