Printing a pdf with javascript

Although i really like the IBM Content Navigator & Case Manager suites, its actually embarrassing that they lack a decent – out of the box – printing mechanism. For some reason they’re using a java applet to print jpg rendered documents to a printer, that in turn produce almost unreadable documents.

I’m not sure why they’re using 1. Java applets to print 2. pour quality documents, but it’s quite obvious there are way better mechanism’s to achieve a print.

My personal favorite: Do a back-end render to pdf, add a document.print() to the resulting PDF, and load that PDF in a hidden iframe.

This sample PDF was created using a java backend (using PDFBox) but i’m sure it’s comparable libraries are available for php, .net etc.

Now, as for the sample code:

The backend/java part:

<%@ page trimDirectiveWhitespaces="true" %>
<%@page import="java.io.File"%>
<%@page import="org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript"%>
<%@page import="org.apache.pdfbox.pdmodel.PDDocument"%>
<%@ page contentType="applicaton/octet-stream" %>

<%
ServletContext context = session.getServletContext();

//load the file on the server, or from some other source (e.g. Filenet Content Engine / accesContentStream)
String pathToPDF = context.getRealPath(request.getParameter("pdf")); 
PDDocument document = PDDocument.load(new File(pathToPDF));

//append a print instruction to execute when the PDF is opened.
PDActionJavaScript javascript = new PDActionJavaScript("this.print();");
document.getDocumentCatalog().setOpenAction(javascript);

//tell the browser to open this pdf inline 
response.setHeader("Content-Disposition", "inline");
response.setHeader("Content-Type", "application/pdf;");

document.save(response.getOutputStream());
%>

The web/javascript part:

<!DOCTYPE html>
<html>
<head>
<title>Printing :)</title>
<script>
	function print(filename) {
		//basically create a hidden i-frame showing the pdf.
		var iFrame = document.createElement("iframe");
		iFrame.style.display = "none";
		iFrame.src = "printablePDF.jsp?pdf=" + encodeURIComponent(filename);
		document.body.appendChild(iFrame);
	}
</script>
</head>
<body>

	<a href="#" onclick="print('document.pdf')">Print the /document.pdf document now!</a>

</body>
</html>

edited 28-02-2016 after Jeroen’s comment.

 

 

Generating isometric tiles and slopes

A few weeks ago i decided  to sort out the old harddrives that i’d been storing in my garage for a few years now. Some of them were at least 15 years old, and i was amazed that only one lost functionality. Anyway, while digging through the data (preserving old photos, code and documents on my novel nas), i came across a prototype of a web-based game i once made.

While not bothering you about the game (i’m actually thinking of picking up where i left it ;)). My prototype code included code to transform any 2d(square) tile, to isometric tiles, including slopes.

As i remember, the pain it was to find isometric tiles, i figured to share it with you. In the below iframe you’ll find the servlet version of the code. Just input any image file (width&height should be equal) below 500kb, and it’ll generate an isometric tileset for you.

Note: I think some improvements can still be made. I’ll probably update the tool as i start picking up the old project 🙂

For example, inputting the following:

Example

Will result in a zip containg the isometric tile (128*64) including all slopes and a sample:

example2

 

Oldschool right?

p.s. i’d be more than happy to know, if this actually helped someone on their hobby project. Feel free to reach out 🙂

p.s.
 

Installing IBM Content Navigator plugins with jenkins

Update: 01-09-2016: This jar is a little out of date as newer navigator builds require a little more for authentication..  Will post an update soon.

Last month i shared a tool that i’ve been using to automatically update code modules & event actions using the IBM Filenet Content Engine api. This month it’s time to share a tool i’ve created to automatically install or update IBM Content Navigator plugins.

Those working with ICN know the pain of navigating to the plugin page, loading, saving and refreshing – only later finding out that you re-loaded the wrong plugin.

So, in order to speed things up. Create the following batch instruction (in jenkins, or any build automation tool):

java -jar ICNPluginInstaller.jar "http://navigator:9080/navigator" "p8admin" "AYBABTU" "\\navigator\c$\IBM\plugins\cool plugin.jar"

The plugin uses the Navigator REST api to update or install the plugin, and has been tested to work on 2.0.2 fixpack 7 and 2.0.3 fixpack 5.

I’ll share the source shortly (after cleaning it up ;)). Until then you can find the .jar file here.

Installing Filenet P8 codemodules with Jenkins

I’ve been creating Filenet applications for quite a while now and as i’m a fan of continuous integration i just had to create a few tools to allow Jenkins interact with Filenet.

One of the tools i’d like to share today is a commandline-tool that can be used to update an existing codemodule & eventaction with a new .jar or .class file.

Running it is simple; After your build step, add the following windows batch command. Jenkins Update CodeModule

The app will exit with code -1 when something has gone wrong, marking the build to be failed.

Download executable jar.

 

 

On the fruits of software engineering (Literally)

I think we all agree that Software Engineers, or perhaps in general, IT employees drink a lot of coffee. Music+Coffee in, software out, that’s our process.

Now, knowing that, a few weeks ago a friend gave me one of the coolest gifts ever; An ‘oyster mushroom growkit’! That supposedly converts coffee-grounds into mushrooms.

 

The idea is simple. You get a plastic box that you initially fill with a fungi-like startup mixture, then you just keep adding coffee as you go, and when it’s filled up you wait for mushrooms to grow.

Cool isn’t it!? I’d say every IT office should have one of these at their coffee corner! Not only is it cool to grow stuff, the office also kills waste as the resulting coffee-goo afterwards is usable as a fertilizer!

 

So, for a timelapse, to get the idea (from rotterzwam.nl):

 

Now, for the current state of my own growkit:)

After about 2 weeks it has been filled up to about 60% of its contents. I’ll continue to update the images as there is progress 🙂

Growkit filled up for 60% showing fungi

99% filled up. Will now max it up, wait for everything to become white and then remove the patches 🙂

Growkit filled up for 99% showing fungi

After about 10 days of growth. It seems that growth is actually speeding up. I believe the right side is growing better as it was more directly exposed to the light.

After about 10 days of mushroom growth.

And only two days later:O

After about 12 days of mushroom growth

 

De potentie van communities – een checklist om succesvol te starten.

Enkele maanden geleden werd ik als enthousiaste consultant uitgenodigd deel te nemen aan het opzetten van een portal. Samen met een kleine groep stakeholders was onze doelstelling een informatieve portal op te zetten waarmee iedereen die ‘iets’ wilde weten op het gebied van ‘Enterprise Information Management’ (EIM) terecht kon. En hoewel we met ‘keep it simple’ een enerverend motto dachten te hebben, verdween langzaam maar zeker de interesse bij de stakeholders. Toen vervolgens ook de initiatiefnemer weg viel i.v.m. een reorganisatie was het gedaan met de ontwikkeling en verdween het idee in de ijskast.

Aangezien het niet de eerste keer was dat ik dergelijke initiatieven in de ijskast heb zien eindigen leek het mij erg interessant om te onderzoeken wat nu de voorwaarden zijn voor een succesvolle (ofwel, levendige) community.

Om tot dit inzicht te komen, ben ik in eerste instantie gaan reflecteren op mijn eigen ervaringen. Deze ben ik vervolgens gaan toetsen/scherpen op basis van bestaande literatuur en artikelen en blogs. Aansluitend heb ik vervolgens met verschillende mensen gesproken over hun ervaringen met het organiseren- en deelnemen van/aan communities(Waarvoor dank!).

Het resultaat van bovengenoemd proces, is mijn visie op de haalbaarheid van communities in de vorm van een checklist. Wellicht dat met deze checklist toekomstige initiatiefnemers inzicht krijgen in de haalbaarheid van de community – en wellicht zelfs hun kans op succes weet te vergroten.

De checklist bestaat uit twee onderdelen waarin verscherpende vragen worden gesteld over respectievelijk het onderwerp en de doelgroep van de community. Als extra paragraaf volgt tevens een overzicht van tips die het de initiatiefnemer gemakkelijker zal maken om zijn start te maken met de community.

Dit is een oud ‘verslag’ uit mijn pre-blog tijd en is voor deze publicatie licht herschreven tot blog-vorm. Ook zijn een aantal organisatie-specifieke voorbeelden en passages geschrapt om te voorkomen dat ik mensen in diskrediet breng. Mocht de tekst op sommige vlakken niet duidelijk zijn, laat dan gerust een reactie achter – ik ben zeker beschikbaar voor discussies over dit onderwerp.

1. Potentiebepaling van de community

In de volgende twee paragrafen zullen achtereenvolgens de potentie van het onderwerp en de potentie van de doelgroep worden getoetst. Hoewel dit in vorm gebeurt van een checklist is het zo geschreven dat ook de algemene lezer zijn weg kan vormen.

1.1. Checklist ‘Potentie van het onderwerp’

Uit verschillende initiatieven is gebleken dat er bij aanvang vaak niet concreet is wat men precies wilt bereiken met de community. Vaak is er wel een idee en het gevoel dat de community het juiste middel is, maar dan blijkt later dat het enorm lastig de boel gaande te houden. Onder het mom van ‘bezint eer ge begint’ volgen in deze paragraaf een aantal controle vragen over het onderwerp.

1.1.1. Is de doelstelling helder?

Wellicht een open deur, maar het hebben van een doelstelling is essentieel. De doelstelling is een stuurmiddel voor de vorming van een community en zal helpen mensen te mobiliseren en deel uit te maken van de startup. Wat is het uiteindelijke doel waarin de community zal faciliteren? Denk o.a. aan kennisdeling, innovatie, samenwerking en cocreatie.

Is er geen doel te formuleren? Dan is er ook geen valide reden om een community te starten.

Praktijk: De ‘ProPro’ community bij mijn huidige opdrachtgever heeft als doel de leden te laten leren van elkaars projecten en ervaringen. Het is een duidelijk doel die de vorming van de community vergemakkelijkt en mensen verbind.

Aanvullend: Een community dient in principe een lange termijn. Het kost veel tijd en energie om de community te vormen en om de juiste mensen bij elkaar te trekken. Daar bovenop kost het ook tijd voor de community om te groeien. Mocht het voor ogen doel dan ook van kortere duur zijn (laten we zeggen, kleiner dan een jaar), dan is een Community wellicht niet het antwoord en kan beter gedacht worden aan een projectaanpak of het starten van een werkgroep (zie ook §1.1.2). Met kortlopende communities frustreer je tevens de bezoekers ervan en beschadigen we ze mogelijkerwijs voor hun participatie met andere communities.

1.1.2. Is de community het geschikte middel?

De gedachte van een community wordt vaak snel ingezet zonder dat überhaupt duidelijk is hoe de community het probleem op gaat lossen. Te gemakkelijk wordt er gedacht dat een community automatisch leidt tot kennisdeling en “iedereen” vervolgens op de hoogte is van “alles”. De realiteit zou wel eens anders kunnen zijn, wellicht is de kennis wel voor handen – maar is er gewoon geen behoefte aan? Anderzijds is de kennis wellicht te triviaal of wellicht te breed om er überhaupt een community rond te creëren? Kortom, denk goed na: Hoe gaat de community het probleem oplossen, wellicht dat uiteindelijk een simpele afdelingsnieuwsbrief meer dan voldoende is.

Praktijk: Om kennisdeling en (sales-)promotie op het ‘vakgebied’ te bevorderen is enkele jaren geleden gepoogd een community te starten. Echter vanwege het kleine aantal actieve professionals (2 à 3) in dit gebied was de community gedoemd te mislukken. Achteraf gezien waren er tal van alternatieve middelen die wel voor het resultaat hadden kunnen zorgen, denk aan een vaste rubriek in de nieuwsbrief, een pagina op de corporate-facebook of een demo-opstelling in een klant-demo-ruimte.

Enkele suggesties tot (gebruik van) andere middelen: Blogs, vakbladen (nu-zakelijk,..), interne nieuwsbrieven, teammeetings, e-learning,  demo-ruimten, fact-sheets, werkgroepen.

1.1.3. Leeft het onderwerp in de organisatie?

Het is belangrijk te begrijpen dat een community enkel van de grond kan komen wanneer we een onderwerp raken dat ook echt ‘leeft’.  Als je aan mensen binnen het vakgebied vraagt wat hun nu bezig houdt, en ze benoemen het onderwerp dan is dit een indicatie voor succes. Anderzijds zal je ook willen vermijden dat je een volledig uitgediept onderwerp kiest voor je community; er valt immers niks meer over te schrijven, te bediscussiëren of te delen omdat alles elders al voorgesneden te vinden is. Kortom ga na of het een besproken onderwerp is.

Praktijk: Voor het opzetten van ons ‘EIM-Portal’ was het destijds nog te vroeg.  Bij navraag in de doelgroep bleek dat vrij weinig mensen notie hadden van het begrip ‘EIM’.

Let op: Je onderwerp heeft een verbindende werking tussen je leden en zorg als ‘gemene deler’ voor betrokkenheid. Waak er voor dat het onderwerp niet te breed te kiezen. Een te brede scope kan er voor zorgen dat mensen hun passie niet kunnen identificeren waardoor ze niet kunnen aarden.

1.1.4. Is de initiatiefnemer bereid tijd te investeren?

Betrokkenheid van de initiatiefnemer is essentieel in die zin dat hiermee het gevoel gegeven wordt wat voor belang er aan de community wordt gehecht. Zonder betrokkenheid is kan de indruk ontstaan slechts gebruikt te worden voor het gewin van de organisatie, dergelijke communities zijn op termijn kansloos.

Betrokkenheid van de initiatiefnemer is bovendien erg belangrijk omdat uitgerekend hij in zijn rol het momentum en het enthousiasme van de groep dient te borgen (zie ook hs. 2). Het onderhouden van een community zal veel tijd kosten en het is ook aan de organisatie om haar deel hierin te erkennen.

Praktijk: Vanwege een reorganisatie viel de initiatiefnemer van ons EIM-portal (als middel van een community) weg. Door het gebrek aan sturing voelden de deelnemers zich doelloos en lieten vervolgens hun enthousiasme en commitment vallen.

1.1.5. Is het al eerder gedaan?

Het is schijnbaar erg ‘menselijk’ om het wiel voor een tweede, derde of zelfs vierde keer uit te vinden. Waarschijnlijk is het ons vakenthousiasme  die er voor zorgt dat we direct met een community starten zonder dat we eerst goed rondkijken of deze in vergelijkbare vorm al bestaat. Aangezien het idee rondom een community is dat we mensen samenbrengen, bereiken we met het opzetten van een nieuwe vergelijkbare community slechts een averechts effect. Bovendien zul je in je zoektocht vergelijkbare communities tegenkomen waarvan een hoop geleerd kan worden.

Dat een eerdere poging niet vruchtbaar is geweest hoeft niet direct te betekenen dat de voor ogen community geen kans van slagen is. Wat echter vaak verzuimd wordt is contact te zoeken met de eerdere initiatiefnemers. Door met hun te reflecteren over het eerdere proces krijg je inzicht in de valkuilen en kansen die komen met  het onderwerp.

1.2. Checklist ‘Doelgroep van de community’

Hoe goed het idee of het onderwerp soms ook is, indien er geen of te weinig geschikte deelnemers zijn, dan zal de community op de lange termijn het onderspit delven.

 1.2.1. De belangenmatrix

Om te voorspellen of een community levensvatbaar is (n.l. ‘levendig’ kan worden) kan het beste gekeken worden naar de belangen van de betrokkenen. Simpel gezegd; Een ieder die een belang heeft bij het bestaan van een community, heeft een ‘incentive’ om deze te gaan gebruiken. Wanneer we naar belangen kijken is het tevens nuttig onderscheid te maken tussen belangen die het ‘voeden’ stimuleren en belangen die het ‘volgen’ van een community stimuleren. Uiteindelijk wil je beide hebben vanwege de symbiose tussen beide. Bovendien, zonder voeders geen volgers.

De onderstaande matrix is hierbij een hulpmiddel. Het geeft de mogelijkheid om betrokken stakeholders te identificeren en aan te geven op welke manier zij een belang hebben bij de community. Hoewel de opzet reeds generieke rollen als stakeholders bevat is het aan te bevelen om deze tevens op persoonsniveau in te vullen. Door deze op persoonsniveau in te vullen wordt het namelijk gemakkelijker om te beredeneren of een motivator ook daadwerkelijk valide is (bestaat je doelgroep wel? En om hoeveel mensen gaat het?). Bovendien geeft het een toolset om deelnemers te kiezen die je wilt betrekken bij het starten van je community.

Tip: Kijk ook eens naar paragraaf 2.1 waar voor een aantal stakeholders een profiel geschetst wordt.

Vul de belangenmatrix zo volledig mogelijk in

Vul de onderstaande belangenmatrix zo volledig mogelijk in. Denk goed na over de verschillende rollen die te maken zullen hebben met je community en op welke manier zij geprikkeld kunnen worden om ook daadwerkelijk te participeren.

De invuloefening zou een antwoord moeten geven op de twee:

1.2.2. Zijn er belanghebbenden die intrinsiek willen ‘voeden’?

Voeders zijn essentieel voor een community. Het zijn diegene die uit eigen beweging bereid zijn energie te steken in de community en doen dit vaak van uit hun passie of vakliefde. Er wordt wel eens geschreven dat binnen een doorsnede organisatie slechts 10% tot deze groep behoort, wat het vinden van voeders erg lastig maakt.

Praktijk: Een toetsing van de eerder mislukte community toonde dat er vrijwel geen stakeholders zijn die geprikkeld worden door het voeden. Deze constatering is bevestigd als de grootste reden voor het stil vallen van de community.

1.2.3. Zijn er belanghebbenden die intrinsiek willen ‘volgen’?

Veel van de belangen van de contribuerende stakeholders worden pas volledig gestimuleerd bij de aanwezigheid van volgers. Bovendien geld ook dat wanneer een voeder het idee heeft dat zijn inspanningen geen publiek dekt hij de handdoek snel in de ring zal gooien. Het verkrijgen van volgers is dan ook essentieel.

Wees echter bewust dat het krijgen van volgers doorgaans een langdurig proces is en dat het daarom in de beginfase aan de initiatiefnemer is om de voeders te helpen herinneren voor wie ze het uiteindelijk doen.

Praktijk: “Toen bleek dat een hoop van onze collega’s geen notie hadden van het geen ‘EIM’ nu precies is, vervloog mijn motivatie om bij te dragen als sneeuw voor de zon”.

1.2.3. Kunnen we het aantal stakeholders maximaliseren door te varieren in onderwerp, doelstelling of met behulp van externe motivatoren?

Wellicht is het mogelijk om met een kleine nuance aan het onderwerp of de scope nog meer mensen mee te krijgen. Wat gebeurt er als het onderwerp abstracter gemaakt wordt? Of juist beperkt tot een specifiek gebied?

Alternatief kan gedacht worden om externe motivatoren te introduceren. In ons geval bijvoorbeeld het beschikbaar maken van ‘een code’, of door het op te nemen als objective in het EPMS. Het is in dat geval echter aan te raden om heel goed na te denken hoe lang deze externe motivator ook daadwerkelijk een prikkel blijft.

Praktijk: Bij het opzetten van diverse VCT’s in het ECM domein bleek “het beschikbaar maken van een code al snel geen invloed meer te hebben op de bereidheid tot voeden”. Bewijs dat intrinsieke motivatoren vele malen belangrijker zijn dan extrinsieke.

2.     Hoe nu verder

Met de checklist uit het vorige hoofdstuk is inmiddels een goed gevoel ontstaat van de mate waarin de community potentie heeft. Indien is vastgesteld dat er inderdaad potentie is, dan kan gestart worden met het opzetten van de community. En hoewel richtlijnen voor het daadwerkelijke starten redelijk beschreven zijn in literatuur als het “Handboek Communities[1]”, deel ik in dit hoofdstuk graag nog een tweetal extra paragrafen die inhoudelijk gerelateerd zijn aan de kern van de checklist, namelijk “belangen”.

In paragraaf 3.1 geef ik een aantal profielen van mensen die je zou willen betrekken bij de opstart van de community. In paragraaf 3.2 volgen een aantal tips, verzameld uit literatuur en reflecties om het momentum en enthousiasme in de opstartfase vast te houden.

2.1.          Een groep ‘believers’ samenstellen.

Voor de startfase van de community zul je een groep believers willen hebben. Het is deze groep die de potentie moet hebben een sneeuwbal effect te bewerkstelligen, waarin andere mensen zich getrokken gaan voelen om deel uit te maken van de community. Focus met name op het volgende “type”personen:

De guru: Dit zijn de kernpersonen binnen het vakgebied/onderwerp die veelal binnen de organisatie bekend zijn als senior of expert, zijn extravert en nemen graag het voortouw wat betreft ontwikkeling van het vakgebied/onderwerp. Ze bezitten veelal een onuitputtelijke bron van energie die ze puur uit het onderwerp alleen al. Niet alleen zijn deze mensen super gemotiveerd om bij te dragen aan een community op ‘hun’ vakgebied, ze zijn ook een inspiratiebron voor gelijkgestemden en functioneren – eenmaal deel van de community – dan ook als een magneet voor iedereen die zichzelf ook enigszins serieus neemt binnen het onderwerp.

De gepassioneerde: De gepassioneerde is grotendeels vergelijkbaar met de guru, maar minder gemakkelijk te vinden omdat ze in mindere mate bekend staan als senior of expert. Belangrijk is echter wel dat ze de community inhoudelijk kunnen vullen en dit puur uit eigen beweging zullen doen.

De (jonge) energieke enthousiasteling: De Jonge enthousiasteling is de energieke level 1 of 2 medewerker die intrinsiek net wat harder loopt dan de rest. Hun energie wordt gevoed door liefde voor het vak, maar ook door prestatiedrang. Ze willen groeien binnen het bedrijf en zijn in dat kader meer dan bereid een actieve bijdrage te leveren binnen aan de nieuw te vormen community.

Een management lid: Het is bovendien belangrijk om mensen hoger in de organisatie te betrekken. Op deze manier ontstaat bij de community leden het gevoel dat ze ook daadwerkelijk nuttig  bezig zijn en het ook ergens voor doen (het bedrijf). Deelname van het management lid verhoogt de kans voor hem die gevoelig zijn voor hiërarchie (voor hen die hun netwerk of zichtbaarheid willen vergroten) om zich aan te sluiten bij de community. Aanvullend heeft kan het management lid een verzachtende functie hebben op kritiek van sceptici in de startfase van de community.

De initiatiefnemer zelf: Net als het management lid, geeft betrokkenheid van de initiatiefnemer de deelnemers een gevoel van waardering. De initiatiefnemer weet bovendien als geen ander dat er bepaalde voorwaarden verbonden zijn aan het succes van de community en dient, met name in de opstart fase continue te sturen binnen het opstartproces. De initiatiefnemer zorgt er voor dat het gemeenschappelijk doel behouden blijft en dat alle successen gevierd worden (n.b. de vieringen aan zich hebben een motiverende werking op de teamleden).

2.2.          Behoud momentum en enthousiasme.

Waar het enthousiasmeren van de groep nog goed te doen is – immers, je hebt reeds een groep van “believers” rondom je onderwerp -, is het behouden van het enthousiasme een grotere uitdaging. Vooral wanneer successen uitblijven is de kans groot dat mensen hun enthousiasme of “geloof” verliezen. Houd als initiatiefnemer dan ook rekening met het volgende:

  • Toon passie en betrokkenheid binnen elk verhaal wat je vertelt. Zorg dat je inspireert en energie geeft.
  • Zorg dat iedereen mee doet en mee praat; Zij die minder assertief / sociaal zijn zullen hun enthousiasme verliezen als ze geen podium krijgen.
  • Stel heldere/concrete korte termijn doelen; Op deze manier behaalt de groep snel tasbaar resultaat en ontstaat het gevoel van voortgang.
  • Sta stil bij successen en vier deze; Ieder behaald doel of mijlpaal dient gevierd te worden. Het tonen van continue waardering voor de inzet van de leden motiveert ze door te gaan.
  • Wees voorzichtig met “afrekenen”, indien mensen het gevoel krijgen dat ze moeten, is er kans dat er een aversie ontstaat en enthousiasme afneemt.
  • Promoot het werk van de groep binnen de organisatie. Door de groepsleden in “the picture” te zetten speel je wederom in op belangen en leg je bovendien een impliciete resultaatverwachting zonder het als “opdracht” ervaren zal worden.
  • Hou periodieke voortgangsgesprekken; Het samenbrengen van de believers creëert positieve energie en betrokkenheid. Bovendien geeft het je inzicht in de voortgang en werkt het als “een stok achter de deur”.
  • Spreek waardering uit, namens jou als initiatiefnemer en namens de organisatie.
  • Voorkom overstimulatie; overstimulatie zorgt voor aversie.
  • Creëer placeholders voor informatie of plaats onvolledige informatie. Belanghebbenden zullen getriggerd worden deze te corrigeren en uit te breiden.
  • Maak een publicatieschema, zorg voor regelmaat. Niet alleen dwing je betrokkenheid af bij jezelf en de leden; regelmaat zorgt er ook voor dat de lezers ‘weten’ dat als ze terugkomen er meer informatie te vinden is… of iets?
  • Manage expectations: Maak duidelijk wat het publiek kan verwachten en hou je daar aan. (Impliciet wat gebeurde bij de e-note).
  • Spreid je publicaties ipv alles in één keer. Geef je publiek iets om voor terug te komen.
  • Zorg voor variatie, blijf je publiek verassen.
  • Betrek je “bezoekend publiek” – hoe langer je iemand op je community kan betrekker, hoe groter de kans op loyaliteit.
  • Zorg dat je bezoekers waarde kunnen toevoegen.
  • Hou het laagdrempelig.
  • Combineer online met offline.

Zoals je ziet draait het wederom om de belangen van de leden. Vraag je dus continu af hoe je hun motivaties / belangen maximaal kan stimuleren in het proces.

3.     Slot

Als we het hebben over de potentiebepaling van communities, dan draait uiteindelijk alles om belangen. Het is erg belangrijk om te beseffen dat we mensen niet kunnen dwingen deel te nemen aan een community. En enkel wanneer ze een eigen belang hebben (bewust of onbewust) zullen ze een langdurige band op kunnen bouwen met een community.

Hoewel bovenstaande checklist en de matrix van belangen een goede indicatie geven zal het helaas geen garantie zijn voor succes. De bestudeerde cases uit het verleden lijken echter wel te bevestigen dat wanneer de checklist overwegend negatief voorspelt dat dan een community niet van de grond zal komen.

[1] Handboek Communities, Erwin Blom, ISBN 9789022959480

 

On an adventurous holiday

Although I’ve got so many things i want to write about, i’m currently spending my holiday in Norway :D.

A day under the ice

However as my personal list of to-write’s is growing, i figured i should note them additionally providing you a list of what’s to come 🙂

So on my todo-lilst are the following subjects:

  1. A detailed description on how i managed to create a Watson/Filenet P8 crawler plugin for 100% findability of documents and (IBM Case Manager) cases using their ‘context’.
  2. Write about frequent IBM Content Navigator customizations.
  3. Write about my novel prototype for automatic ‘BPF to IBM Case Manager’ migration.
  4. Write about my plans & perhaps execute to build an ant-farm (i think it will be loads of fun to create one!)
  5. Write about mygraphic generator for isometric tiles, including slope-tiles.
  6. Write about the game i’m creating that will be using the isometric tile generator:)
  7. Share some of my philosophical thoughts on the near future of our species.

Cheers!

Exporting IBM Filenet P8 query results to excel (english)

I’ve been working with IBM Filenet for a few years now, and although i’m a great fan, there are some really big shortcomings with its basic management tools such as the FEM (Filenet Enterprise Manager) or the ACCE.

One of them is the ability to – directly export CE-query results to an excel file, which can be useful when performing ad-hoc analysis. Of course there is the option to export to a comma- or tab separated plain text file. But, as it seems a lot of content happens to contain commas or tabs as well, which makes the functionality completely useless :).

So, thank god for the Java api.

I recently made this simple command-line tool, that allows you to export the results of a simple CE query to excel, using java and Apache Poi. It performs at lightspeed compared to the FEM-csv export and requires minimal configuration. Yet, i must say – its no rocketscience, anyone could have made it-.

Download: Binary with required libraries. *
Download: Source (java) – Please share any any improvements:)

* may not contain the correct version of jace.jar depending on your system.

Usage

  1. Unzip the jar
  2. Specify your connection information in the connection.properties file.
  3. Start via the commandline “java -jar P8ToXLS.jar”
  4. Provide your username & password
  5. Paste or type the query. (An empty line is considered “next”)
  6. Type a name for the output file (e.g. “output.xls”)
  7. Wait until done 🙂

Cheers!

Java EE: JAX-RS, EJB en JPA (EclipseLink / Mysql) mbv annotaties.

In de meeste gevallen kom ik als javaan ergens binnen om aan bestaande functionaliteit te werken. Maar, het leukste blijft toch om alles ‘from scratch’ bouwen.

In dit artikel niet zozeer een verhaal over nieuwe technieken, of mijn ‘from scratch’ aanpak, maar simpelweg een stuk voorbeeld code + uitleg om te laten zien hoe gemakkelijk de technieken uit de titel zijn in te zetten.

Als eerste wat context

Om het geheugen op te frissen, of om wat gaten in te vullen, van links naar rechts:

JAX-RS is een api waarmee REST webservices gemaakt kunnen worden. Deze vorm van webservices is met name populair omdat het gebouwd is op de HTTP/1.1 specificatie waardoor het super gemakkelijk te begrijpen is, of aan te sluiten aan je frontend. (Zie @Specificatie, @Wikipedia). (Sinds EE5)

EJB of”Enterpsie JavaBeans’ zijn bedoeld voor je applicatie logica en draaien binnen een EJB container op je applicatieserver. De EJB schrijft o.a. voor hoe omgegaan dient te worden met zaken als trancties, concurrency en security. Het schrijven van EJB’s is pas echt een feest sinds EJB 3.0 waar annotaties de warboel van deployment descriptors en interfaces hebben vervangen. (@Wikipedia)

JPA of ‘Java Persistence API’ is een een specificatie die beschrijft hoe van uit Java met (relationele) data omgegaan dient te worden. Met JPA breng je een object-relational-mapping tot stand o.b.v. annotaties.  JPA kent een aantal implementaties waarvan de bekendste wellicht Hibernate is.

EclipseLink is de ‘referentie implementatie’ voor JPA en is (net zoals overigens Hibernate) volledig JPA 2.0 complient.  (@EclipseLink FAQ, @Wikipedia)

MySQL is ‘s werelds meest gebruikte opensource RDBMS. En vergt volgens mij geen verdere toelichting.

De implementatie

Welnu, de voorbeeld implementatie betreft een denkbeeldig onderdeel van een beheerplatform. Het stukje ‘UserManagement’ is bedoeld om informatie van gebruikers van ‘het systeem’ aan te maken, of te raadplegen.

De demo bestaat uit een Stateless Session Bean (SSB) ‘UserManagement’ die met zijn twee methoden (t.b.v create/retreive) beschikbaar wordt gesteld via JAX-RS. De User objecten worden gemanaged, opgehaald en opgeslagen in MySQL d.m.v. EclipseLink.

1. Structuur / overzicht

Om te beginnen hieronder een overzicht van het project. In dit project zit geen web.xml, alle configuratie gebeurt o.b.v. annotaties.

Java EE JAX-RS, EJB and JPA (EclipseLink Mysql)  mbv annotaties.

2. EclipseLink & Mysql configuratie

De basisconfiguratie van JPA wordt gevormd door persistence.xml. Hierin configureer je ‘Persistence Units’. Een persistent unit is een groep van ‘persistable classes’ met bijbehorende configuratie.

<persistence-unit name="default" transaction-type="JTA">
	<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>

	<jta-data-source>java:app/ee6sample/SampleDS</jta-data-source>

	<exclude-unlisted-classes>false</exclude-unlisted-classes>

	<properties>
		<property name="eclipselink.ddl-generation" value="create-tables" />
		<property name="eclipselink.ddl-generation.output-mode"	value="database" />
	</properties>
</persistence-unit>

In bovenstaand voorbeeld configureren we een persisten-unit met de naam ‘default’. Het ‘transaction-type’ JTA (@wiki) wordt afgedwongen doordat we JPA binnen de EJB managed context gebruiken.

We gebruiken EclipseLink (<provider/>) en maken gebruik van de ‘java:app/ee6sample/SampleDS’ datasource (zie volgend onderdeel).

Waar je normaal gesproken met <class/> configureert welke klassen bij deze persistence-unit horen, geven we in dit voorbeeld aan dat niet geconfigureerde klassen opgenomen kunnen worden in deze PU. Met slechts één PU laten we alle klassen dus managen door default. (exclude-unlisted-classes = false).

Aanvullend specificeren we dat de DDL voor de tabellen direct op de databases uit laten voeren. Anders verwoord, JPA gaat de tabellen aanmaken voor onze applicatie.

3. Datasources.java – Datasource registratie m.b.v. annotaties

Sinds JSR-250 is er de mogleijkheid om datasources te regiteren met behulp van de annotaties @DataSourceDefinition en @DataSourceDefinitions. Voorheen was het altijd nodig om deze configuratie in de applicatie server uit te voeren, maar nu wordt deze configuratie dus portable.

Onderstaand codevoorbeeld registreert een datasource in de applicatie scope.

package nl.ivojonker.ee6sample.configuration;

import javax.annotation.sql.DataSourceDefinition;


/**
 * Registers the following datasources: 
 * 		java:app/ee6sample/SampleDS
 * 
 * web.xml allow's to override the defaults.
 * @author ivo.jonker
 */

@DataSourceDefinition(
		name = "java:app/ee6sample/SampleDS",
		className = "com.mysql.jdbc.jdbc2.optional.MysqlXADataSource",
		url = "jdbc:mysql://localhost:3306/ivo",
		user = "root",
		password = "") 

public class Datasources {

}

Deze configuratie valt uiteraard onder de noemer ‘hard-coded’, maar kan eventueel worden overriden in de web.xml

4. User.java – een JPA managed entiteit

De klasse User is een POJO geannoteerd met @Entity waarmee we zeggen dat dit een door ‘JPA gemanagde entiteit’ is. Met de aangebrachte annotatie zal deze entiteit corresponderen met de  tabel User (ID int(11) primary key, NAME varchar(255)) .

De tabel – indien hij niet bestaat – zal automatisch worden aangemaakt door EclipseLink. Waarden voor ID zullen automatisch worden gegenereerd (@Id).

package nl.ivojonker.ee6sample.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class User {

	@Id
	@GeneratedValue
	private int id;
	
	private String name;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

Uiteraard zijn er veel meer annotaties en instellingen, een mooi overzicht vondt ik op de website van de ObjectDB JPA implementatie.

 5. UserManagement.java – een JAX-RS exposed SSB met een EntityManager

De klasse UserManagement bevat de business logica voor het managen van users. In dit geval een Stateless Session Bean (@Stateless) met twee methoden. Een om een user mee aan te maken, een andere om user-gegevens op te vragen a.d.h.v. een user id. Beide methoden worden aangeboden via JAX-RS webservices. De annotaties spreken voor zich wanneer je beseft dat ze het volgende mogelijk maken:

HTTP PUT http://localhost:8080/Demo/rest/users?name=Ivo
Om een nieuwe gebruiker aan te maken

HTTP GET http://localhost:8080/Demo/rest/users?id=1
Om een gebruikergegevens met id 1 op te halen uit de database.

Met @PersistenceContext injecteren we een container-managed entity manager. Deze gebruiken we vervolgens om nieuwe Users aan te maken of terug te halen uit de database.

Naast de @QueryParam kun je ook nog annotaties als  @MatrixParam, @HeaderParam, @CookieParam, @FormParam gebruiken om b.v. headers of cookiers te benaderen.

package nl.ivojonker.ee6sample.logic;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;

import nl.ivojonker.ee6sample.model.User;

@Stateless
@Path("/users")
@Produces("text/plain")
public class UserManagement {
	
	@PersistenceContext
	EntityManager em;

	@GET
	public String getUser(@QueryParam("id") int id){
		User user = em.find(User.class, id);
		return "username: "+user.getName();
	}
	
	@PUT
	public String createUser(@QueryParam("name") String name){
		User newUser = new User();
		newUser.setName(name);
		
		em.persist(newUser);
		
		return "New user created with id: "+newUser.getId();
	}
}

 6. JerseyConfig.java

Jersey is JAX-RS implementatie die zich erg gemakkelijk laat configureren.  In het voorbeeld doen we dit met een annotatie waarmee we alle classes in de nl.ivojonker.ee6sample.logic package exposen binnen het rest path.

Alternatief laat Jersey zich ook prima in de web.xml file configuren.

package nl.ivojonker.ee6sample.configuration;

import javax.ws.rs.ApplicationPath;

import org.glassfish.jersey.server.ResourceConfig;

/**
 * Registers the JAX-rs path rest for classes within the nl.ivojonker.* package.
 * @author ivo.jonker
 *
 */
@ApplicationPath("rest")
public class JerseyConfig extends ResourceConfig {

    public JerseyConfig() {
        packages("nl.ivojonker.ee6sample.logic");
    }
}

Makkelijk toch?

 

Wanneer zoeken niet leidt tot vinden – het belang van Metadata.

Met een goede metadata huishouding maak je het mogelijk om langs dimensies te verkennen en te sorteren. Het stelt je in staat ‘gericht te zoeken’ en geeft je de mogelijkheid om bij het ‘vrije zoeken’  je resultaten te verfijnen met behulp van bijvoorbeeld facetten; en voor de ‘echt slimme’ ontwikkelaars biedt het zelfs mogelijkheden tot auto-classificatie, semantisch clusteren of contextuele analyse.

En toch is het maken van een gedegen metadata-ontwerp iets wat in een hoop projecten verzuimd wordt. Vaak is het metadata model iets wat impliciet ontstaan is als bijproduct van een functionele behoefte. Net zo vaak valt het aan het begin van het project buiten scope omdat de hoeveelheid informatie op dat moment prima te overzien is en terugvindbaarheid nog geen issue is. Andere keren is het simpelweg de organisatie die geen partner wilt zijn in het tot stand brengen van een model door b.v. geruzie tussen afdelingen;”wij zijn allemaal anders!”.

Hoe dan ook, naarmate het project vordert, het systeem vaker gebruikt wordt en de hoeveelheid content groeit. Wordt ook het probleem van het ‘slechte metadata ontwerp’ zichtbaar. Het zal voor de gebruikers namelijk steeds lastiger worden om nog content terug te kunnen vinden. En nee, als je denkt dat een full-text search oplossingen zal bieden, dan zul je bedrogen uit komen.

Een aantal ideeën voor als je de metadata plank hebt misgeslagen.

Ik hou van complexe uitdagingen. Een document management systeem met meerdere ‘document-klassen’ gecombineerd met ‘state-of-the-art search engines’ waarmee niks te vinden valt is dan ook een erg leuke. Wat zijn je opties?

Waar sta je?

Überhaupt de eerste stap die genomen moet worden is het inventariseren van het ‘model’ wat tot dusver is ontstaan. De kans is groot dat er toch wel het een en ander aan nuttige informatie wordt opgeslagen, maar dat deze niet beschikbaar is op het document. Indien je zaakgericht werkt, of waneer je documenten onderdeel zijn van een dossierstructuur dan is ook de metadata van deze processen,zaken, dossiers en mappen wellicht relevant voor je documenten.

Het gemakkelijkst is het om even ene tool als excel te pakken, en daarin je klassen en properties letterlijk op een rijtje te zetten . Groepeer de gelijksoortige klassen (alle documenten bij elkaar, etc.) en maak inzichtelijk welke ‘properties’/metadatavelden van deze klassen overlappen, verschillen of gelijksoortig zijn maar verschillen in naam (b.v. plaats vs woonplaats vs stad).

Kijk vervolgens naar je spreadsheet en houdt in gedachten dat als gebruikers content zoeken, ze in principe op zoek zijn naar een ‘document’ en die denken te gaan vinden door free-text-search te combineren met metadata-filters.

Her-modeleer je metadata-model.

Door te kijken van uit het ‘zoek perspectief’ kom je er achter dat je model een aantal gaten heeft. Mogelijk kom je er achter dat het zoeken op één bepaald kenmerk onbewust al zorgt voor de uit-filtering van hele groepen content. Anderzijds zul je verbaasd zijn dat sommige content essentiële kenmerken mist.

Wat je ook tegenkomt, schets je nieuwe model, pak een paar iteraties om het te verbeteren en leg het voor aan je collega’s.

Wat volgt is je referentiemodel waaraan je je huidige situatie aan kan evalueren.

Quick-wins in metadatering.

Je nieuwe referentiemodel maakt het mogelijk quick-wins te identificeren. Denk aan het toevoegen van essentiële kenmerken, het verplicht/optioneel maken van kenmerken, het toevoegen van keuzelijsten of het  harmoniseren van naamgeving (n.b. dat sec van uit het zoekperspectief de meeste tools metadata-mapping ondersteunen).

Stimuleer invoering en vul automatisch in.

Gebruikers zitten nu eenmaal niet te springen op het invullen van metadata. Wat echter wel goed is om te weten dat gebruikers wel geprikkeld worden indien ze incorrecte metadata zien staan.

Vul daarom zoveel mogelijk vooraf in. Haal kenmerken uit de gebruikerscontext(LDAP), het proces, de zaak of het bovenliggende dossier. Gebruik ook de kenmerken uit de content, zoals de bestandsnaam, de titel, het onderwerp of de auteur.

Het verplicht stellen van kenmerken is  verder tricky, maar wordt als minder vervelend ervaren wanneer het elementen met een keuzelijst betreft, maak hier dus gebruik van.

Maak een plugin voor je ‘crawler’.

Vrijwel alle search engines bieden mogelijkheden voor maatwerk – en hoewel dit binnen NL nog niet vaak gedaan is, is het makkelijker dan gedacht. Het is in ieder geval een belangrijke optie om te overwegen wanneer je zoek resultaten wilt verbeteren. Het stelt je in staat metadata op te poetsen of te verrijken zonder dat je het systeem vervuilt.

Enkele voorbeelden van nuttige plugin features:

  • Lege / null waarden voorzien van een label; ‘ Niet relevant / ingevoerd’. Heeft een gunstig effect bij facetted-search interfaces.
  • Het invullen van defaults.
  • Het overnemen van folder of dossier kenmerken die relevant zijn voor de terugvindbaarheid.
  • Het overnemen van kenmerken van andere entiteiten (procesgegevens, zaakgegevens e.d.)
  • Het vertalen van technische gegevens (sleutels) zoals userid naar username.

 n.b. dat een veel uitgevoerd alternatief wat mij betreft de plank misslaat: ‘het door-synchroniseren van metadata van aanverwante objecten (zoals bovenliggende dossiers) naar documenten’. Het verhoogt je beheerlast aan het metadatamodel – je dient de redundante properties te managen -, het vergt synchronisatiemiddelen – die waarschijnlijk gefagmenteerd in je systeem terrecht komen, en bovendien je systeem belast terwijl je zoek-service ilde staat – .