Blog Pro de Jean-Baptiste HEREN Notes d'un consultant Freelance en Informatique 2015-11-03T21:34:19+01:00 JB HEREN urn:md5:e39389b5ec134d99645112fce3d957df Dotclear Activer le mode modem sur Iphone 3G avec free mobile sous OSX urn:md5:d74fff12219c3bf1c82061c6a4d09966 2012-02-23T21:51:00+01:00 2012-05-11T14:38:46+02:00 Jean-Baptiste Heren Veille techno iPhoneMacOSX <p>Pour activer le partage de connexion avec free sur iOS inférieur à 5, il faut se débrouiller tout seul.</p> <h2>1 - Télécharger la configuration opérateur free mobile chez apple</h2> <p><a href="http://appldnld.apple.com/iPhone/CarrierBundles/Free_fr_iPhone.ipcc" hreflang="en" title="ipcc free fr">http://appldnld.apple.com/iPhone/CarrierBundles/Free_fr_iPhone.ipcc</a></p> <h2>2 - Activer le mode carrier-testing de iTunes</h2> <p>Aprés avoir fermé itunes, ouvrez le Terminal et tapez ceci&nbsp;:</p> <pre>[script] defaults write com.apple.iTunes carrier-testing -bool TRUE </pre> <h2>3 - Mise à jour des paramètres opérateur</h2> <ul> <li>Démarrez itunes et branchez votre iPhone</li> <li>Cliquez sur "Recherche des mises à jour" en maintanant la touche alt enfoncée</li> <li>Sélectionnez le fichier .ipcc</li> </ul> <h2>4 - activer le partage de connexion sur l'iphone dans Réglages/Général/Réseau.</h2> <p><img src="http://blog.jbheren.com/public/tuto/iphone/IMG_0407.PNG" alt="Partage de connexion iphone free mobile" title="Partage de connexion iphone free mobile, fév. 2012" /></p> <p>Bon surf&nbsp;!</p> Cognos Report : Display a different measure in row for the aggregated column urn:md5:6ccc97632f467975c6b7413cdfb5c47f 2012-01-30T19:43:00+01:00 2012-01-30T20:34:34+01:00 Jean-Baptiste Heren Décisionnel Business IntelligenceCognosCognos Report Studio <p>Following tip is when you use a Relational Datamodel (DMR).</p> <p>In a Cognos Report crosstab, If You need to Display different measure in the aggregated column, you can do it using a simple if-then-else expression.</p> <p><a href="http://blog.jbheren.com/public/Decisionnel/conditional_measure/result_crosstab.png" title="result_crosstab.png"><img src="http://blog.jbheren.com/public/Decisionnel/conditional_measure/.result_crosstab_m.jpg" alt="result_crosstab.png" title="result_crosstab.png, janv. 2012" /></a></p> <p>Explanation: You know if you are on a total column when the <strong>current context</strong> gives you <strong>more than one value</strong> for the <strong>year</strong> Axis.</p> <p><img src="http://blog.jbheren.com/public/Decisionnel/conditional_measure/query_items.png" alt="query_items.png" title="query_items.png, janv. 2012" /></p> <p><strong>isTotalYear</strong> Expression:</p> <pre>[script] if(count(distinct [year]) &gt; 1) then(1) else (0) </pre> <p><strong>Conditional</strong> Expression:</p> <pre>[script] if(count(distinct [year]) &gt; 1) then([PackName].[Measures].[M1]) else ([PackName].[Measures].[M2]) </pre> Matériel Open Source & Introduction à RepRap urn:md5:68dd2f717faebce6cb7e494aac33d6c4 2011-12-02T13:58:00+01:00 2012-02-24T16:48:38+01:00 Jean-Baptiste Heren DIY DIYfablabopen source hardwarereprap <p><img src="http://blog.jbheren.com/public/diy/150px-Reprap-qr-logo-wide.png" alt="150px-Reprap-qr-logo-wide.png" style="float:left; margin: 0 1em 1em 0;" title="150px-Reprap-qr-logo-wide.png, janv. 2012" /></p> <p>Le mouvement Open Source vous est familier&nbsp;? C'est assez peu connu, mais ce mouvement ne concerne pas seulement le secteur du logiciel ou de l'immatériel, mais aussi le matériel. L'<a href="http://en.wikipedia.org/wiki/Open-source_hardware" hreflang="en">Open Source Hardware</a> correspond aux objets qui respectent le principe de l'ouverture des méthodes et moyens de fabrication, permettant comme pour le logiciel, à chacun de fabriquer et d'améliorer le projet initial.</p> <p><q>APPRENDRE - PARTAGER - PRODUIRE</q></p> <p>On peut ainsi aujourd'hui se procurer les plans de nombreux appareils conçus et continuellement améliorés par une communauté. Des objets dont chacun maitrise le fonctionnement, modifiables et réparables.</p> <p>Le projet <a href="http://www.reprap.org" hreflang="en" title="reprap Community">Reprap</a> est l'un des ces projets les plus populaires, Il s'agit d'une machine capable d'imprimer des objets en trois dimensions, par l'application de couches successives de plastique déposé par la tête d'impression.</p> <div class="external-media" style="float: right; margin: 0 0 1em 1em;"> <iframe src="http://player.vimeo.com/video/5202148" width="640" height="512" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe> <br /><a href="http://player.vimeo.com/video/5202148">RepRap Introduction</a> </div> <p>Si ce type d'appareils existe déjà, dans des versions propriétaires, la reprap se distinque par plusieurs aspects&nbsp;:</p> <ul> <li>Une machine bon marché. Selon le mode d'approvisionnement, compter entre 600€ et 800€ pour un Kit complet livré clef en main (à monter soi-même). Les équivalents commerciaux sont au moins 10 fois plus chers&nbsp;!</li> <li>Une communauté active. On pourra profiter de toutes les améliorations proposées par la communauté, ainsi que de toute l'aide nécessaire à la mise au point de son propre appareil.</li> <li>Reprap peut en imprimer une partie des pièces qui la composent. C'est pourquoi Reprap est connu comme le premier objet "auto-réplicant".</li> </ul> <p>Quelques liens pour aller plus loin&nbsp;:</p> <ul> <li><a href="http://www.thingiverse.com/" hreflang="en">thingiverse.com</a>&nbsp;: Un site communautaire regroupant des Gides de construction d'objets, notamment avec une imprimante 3D.</li> <li><a href="http://www.makergear.com/products/3d-printers" hreflang="fr" title="reprap Prusa Mendel Kit">makergear.com</a>&nbsp;: Vente de Kits complets pour Reprap PRUSA. C'est chez eux que j'ai acheté le Kit de ma première imprimante 3D.</li> <li><a href="http://cgi.ebay.fr/ws/eBayISAPI.dll?ViewItem&amp;item=230700566122&amp;ssPageName=STRK:MEWAX:IT&amp;_trksid=p3984.m1423.l2649#ht_550wt_1413" hreflang="fr" title="Kit Reprap printed parts">ebay.fr</a>&nbsp;: On y retrouve de nombreux kits de pièces plastique imprimées, indispensables pour fabriquer sa propre reprap.</li> <li>Et bien évidemment le labo où je sévis&nbsp;: <a href="http://www.etolab.com/tag/imprimante-3d/" hreflang="fr" title="fablab amiénois catégorie imprimante 3D">etolab</a>.</li> </ul> automatic ftp tranfers on windows OS client using the command line urn:md5:095889337a165f98a9556881fb9ade07 2011-06-27T20:55:00+02:00 2011-12-02T11:07:36+01:00 Jean-Baptiste Heren Veille techno batchChilkat FTPcommand lineftpvbswindowswinSCP <p>Here is a little trick we used on a recent project.</p> <p>We needed to automatize :</p> <ol> <li>(local &lt;-- remote) download files from an ftp server specified folder</li> <li>(remote --&gt; remote/subfolder) move the downloaded files on the source server so that we do not download them again on next run.</li> </ol> <h2>Needed Tools</h2> <h3>ftp Client</h3> <p>I decided to use the WINSCP Command wich is part of the WinSCP client package. This tool works as a command line client and is scriptable. It is possible also to use the ftp command directly but it does not work properly whan you want to send ftp commands on the fly.</p> <h3>Scripting language</h3> <p>The following example uses Visual basic scripting.</p> <h2>The Script</h2> <p>After creating a new conenction in WINSCP client, we can use it on command line by running the following script :</p> <pre>[script] cscript move.vbs D:\FTPROOT\IN\LOCAL IN/FOO OUT/FOO DONE MYACCOUNT </pre> <pre>[VB] 'contact@jbheren.com 'this code builds a move command from the file list in specified directory &amp; runs it in WSCP 'usage: cscript move.vbs source_local_full_path remote_initial_directory remote_final_subdirectory Dim fso, folder, files, localPath, localFolder, remoteFolder, moveSubFolder, connexionName, oShell, oExec, winscp ' Check parameters If( WScript.Arguments.Count &lt; 4 ) Then WScript.Echo( vbCrLf &amp;&quot; usage: cscript move.vbs source_local_full_path local_ftp_path remote_ftp_path move_to_path connection_name&quot;) WScript.Echo( vbCrLf &amp;&quot; example: &quot; &amp;vbCrLf &amp;&quot; cscript move.vbs D:\FTPROOT\IN\LOCAL IN/FOO OUT/FOO DONE MYACCOUNT&quot;) WScript.Echo( vbCrLf &amp;&quot; &quot; &amp;vbCrLf &amp;&quot; 1 - Gets files from OUT/FOO -&gt; IN/FOO using the recorded MYACCOUNT WINSCP connection&quot;) WScript.Echo( vbCrLf &amp;&quot; &quot; &amp;vbCrLf &amp;&quot; 2 - moves files names found in D:\FTPROOT\IN\LOCAL, on remote from OUT/FOO -&gt; OUT/FOO/DONE&quot;) WScript.Quit End If ' ------------------------------------------- '| MAIN | ' ------------------------------------------- ' Set Winscp com path winscp = &quot;C:\Program Files\WinSCP\winscp.com&quot; commandTxt = &quot;&quot; ' Empty current command Set fso = CreateObject(&quot;Scripting.FileSystemObject&quot;) ' retreive parameters localPath = Wscript.Arguments.Item(0) localFolder = Wscript.Arguments.Item(1) remoteFolder = Wscript.Arguments.Item(2) moveSubFolder = Wscript.Arguments.Item(3) connexionName = Wscript.Arguments.Item(4) If localPath = &quot;&quot; Then Wscript.Echo &quot;No Folder parameter was passed&quot; Wscript.Quit Else Wscript.Echo &quot;Runing For &quot; &amp; localPath &amp; &quot; , &quot; &amp; localFolder &amp; &quot; , &quot; &amp; remoteFolder &amp; &quot; , &quot; &amp; moveSubFolder &amp; &quot; on connection &quot; &amp; connexionName End If ' Open ftp command Set oShell = CreateObject(&quot;wscript.shell&quot;) 'Set oExec = oShell.Exec(&quot;ftpgenerix.bat&quot;) Set oExec = oShell.Exec(winscp) ' Build the list of Commands to be ran by FTP command. ' login oExec.StdIn.Writeline &quot;option batch abort&quot; WScript.Sleep 100 oExec.StdIn.Writeline &quot;open &quot; &amp; connexionName WScript.Sleep 100 ' 00 - Set Current Folders oExec.StdIn.Writeline(&quot;cd &quot; &amp; remoteFolder) WScript.Sleep 100 oExec.StdIn.Writeline(&quot;lcd &quot; &amp; localFolder) WScript.Sleep 100 ' 01 - DOWNLOAD oExec.StdIn.Writeline(&quot;get *.*&quot;) Wscript.Echo &quot;Getting All files from &quot; &amp; remoteFolder &amp; &quot; to &quot; &amp; localFolder WScript.Sleep 1000 ' 02 - RENAME (Move files) ' list current local files Set folder = fso.GetFolder(localPath) Set files = folder.Files ' move each one on distant server from current folder to dFolder For each file In files commandTxt = &quot;rename &quot; &amp; file.Name &amp; &quot; &quot; &amp; moveSubFolder &amp; &quot;/&quot; &amp; file.Name oExec.StdIn.Writeline(commandTxt) Wscript.Echo commandTxt WScript.Sleep 100 Next ' Finish session oExec.StdIn.Writeline &quot;exit&quot; Wscript.Echo &quot;exit&quot; WScript.Sleep 100 WScript.Echo oExec.Status </pre> <p>Hope it will help !</p> <h2>Alternatives to WinSCP</h2> <p>I just reworked on this task (same actions) and wrote a vbs script doing the same task, but replaced winscp with an ActiveX control object : <a href="http://www.chilkatsoft.com/ftp-activex.asp" hreflang="en" title="http://www.chilkatsoft.com/ftp-activex.asp">Chilkat FTP ActiveX</a></p> <p>Here is the code</p> <pre>[VB] 'moveocx.vbs 'contact@jbheren.com 'this code builds a move command from the file list in specified directory &amp; runs it FTP Session 'uses ActiveX component from http://www.chilkatsoft.com/ftp-activex.asp 'usage: cscript move.vbs source_local_full_path remote_initial_directory remote_final_subdirectory Dim fso, ftpo, folder, files, localPath, localFolder, remoteFolder, moveSubFolder, host, user, pass, ok ' Check parameters If( WScript.Arguments.Count &lt; 4 ) Then WScript.Echo( vbCrLf &amp;&quot; usage: cscript moveocx.vbs source_local_full_path local_ftp_path remote_ftp_path move_to_path user pass host&quot;) WScript.Echo( vbCrLf &amp;&quot; example: &quot; &amp;vbCrLf &amp;&quot; cscript moveocx.vbs D:\FTPROOT\IN\LOCAL IN/FOO OUT/FOO DONE MYLOGIN MYPASS MYHOST&quot;) WScript.Echo( vbCrLf &amp;&quot; &quot; &amp;vbCrLf &amp;&quot; 1 - Gets files from OUT/FOO -&gt; IN/FOO using the recorded MYLOGIN connection&quot;) WScript.Echo( vbCrLf &amp;&quot; &quot; &amp;vbCrLf &amp;&quot; 2 - moves files names found in D:\FTPROOT\IN\LOCAL, on remote from OUT/FOO -&gt; OUT/FOO/DONE&quot;) WScript.Quit End If ' ------------------------------------------- '| MAIN | ' ------------------------------------------- ' Set Basic path commandTxt = &quot;&quot; ' Empty current command ' instanciate chilkat FTP Component Set fso = CreateObject(&quot;Scripting.FileSystemObject&quot;) ' retreive parameters localPath = Wscript.Arguments.Item(0) localFolder = Wscript.Arguments.Item(1) remoteFolder = Wscript.Arguments.Item(2) moveSubFolder = Wscript.Arguments.Item(3) user = Wscript.Arguments.Item(4) pass = Wscript.Arguments.Item(5) host = Wscript.Arguments.Item(6) If localPath = &quot;&quot; Then Wscript.Echo &quot;No Folder parameter was passed&quot; Wscript.Quit Else Wscript.Echo &quot;Runing For &quot; &amp; localPath &amp; &quot; , &quot; &amp; localFolder &amp; &quot; , &quot; &amp; remoteFolder &amp; &quot; , &quot; &amp; moveSubFolder &amp; &quot; on connection &quot; &amp; host End If ' JBH - Open ftp command 'Set ftpo = CreateObject(&quot;InetCtls.Inet.1&quot;) 'Msinet.ocx Set ftpo = CreateObject(&quot;ChilkatFTP.ChilkatFTP.1&quot;) ftpo.Username = user ftpo.Password = password ftpo.Hostname = host ftpo.Password = pass ftpo.Passive = true Wscript.Echo &quot;Connecting...&quot; if (ftpo.Connect()) &lt;&gt; 1 Then Wscript.Echo &quot;Failed Connection : &quot; &amp; ftpo.LastErrorText ftpo.Disconnect() Wscript.Quit else ' 00 - Set Remote Folder Wscript.Echo &quot;00 - Set remote folder to &quot; &amp; remoteFolder If (ftpo.ChangeRemoteDir( remoteFolder )) &lt;&gt; 1 Then Wscript.Echo &quot;Failed setting remote dir : &quot; &amp; ftpo.LastErrorText ftpo.Disconnect() Wscript.Quit End If ' 01 - DOWNLOAD Wscript.Echo &quot;01 - Getting All files from &quot; &amp; remoteFolder &amp; &quot; to &quot; &amp; localFolder ok = ftpo.MGetFiles(&quot;*.*&quot;, localPath) If (ok) &lt;&gt; 1 Then Wscript.Echo &quot; Download returned &quot;&amp; ok &amp;&quot; : &quot; &amp; ftpo.LastErrorText 'ftpo.Disconnect() 'Wscript.Quit End If ' 02 - RENAME (Move files) ' list current local files Set folder = fso.GetFolder(localPath) Set Files = folder.Files ' move each one on distant server from current folder to dFolder Wscript.Echo &quot; Move files present in &quot; &amp; localPath &amp; &quot; to remote folder &quot; &amp; remoteFolder &amp; &quot;/&quot; &amp; moveSubFolder For each file In Files Wscript.Echo &quot; Rename &quot; &amp; file.Name &amp; &quot; to &quot; &amp; moveSubFolder &amp; &quot;/&quot; &amp; file.Name ok = ftpo.RenameRemoteFile(file.Name, moveSubFolder &amp; &quot;/&quot; &amp; file.Name) If (ok) &lt;&gt; 1 Then Wscript.Echo &quot; Rename Returned unexpected value (&quot; &amp; ok &amp; &quot;) &quot; &amp; ftpo.LastErrorText 'ftpo.Disconnect() 'Wscript.Quit End If Next ' Finish session WScript.Echo &quot;Closing&quot; ftpo.Disconnect() WScript.Echo &quot;Done!&quot; End if </pre> Convert virtual drive from virtualbox to vmware urn:md5:56e6f94f6456c20b4e5820e481930c13 2011-06-21T23:03:00+02:00 2011-06-22T09:23:05+02:00 Jean-Baptiste Heren Linux cloud computing <p><img src="http://blog.jbheren.com/public/tuto/virtualbox/.vbox_logo_t.jpg" alt="vbox_logo.png" style="float:left; margin: 0 1em 1em 0;" title="vbox_logo.png, juin 2011" />You have a virtualbox image and want to use it in VMWARE ?</p> <p>If the .ova file does not fits your needs, you can try to convert the hard drive and then use it directly in a configured vmware machine.</p> <p>VirtualBox provides a command line tool to convert from .vdi to .vmdk : <a href="http://www.virtualbox.org/manual/ch08.html#vboxmanage-clonevdi" hreflang="en">VBoxManage clonehd</a></p> <h2>Here is an Example</h2> <pre>[script] jb$ cd /Users/jb/VirtualBox VMs/myvirtualdrive-bash: cd: /Users/jb/VirtualBox: No such file or directory jb$ cd &quot;/Users/jb/VirtualBox VMs/myvirtualdrive&quot; jb$ ls Logs myvirtualdrive.vbox myvirtualdrive.vbox-prev myvirtualdrive.vdi jb$ VBoxManage clonehd myvirtualdrive.vdi --format VMDK myvirtualdrive.vmdk 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100% Clone hard disk created in format 'VMDK'. UUID: xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx </pre> <h2>Documentation from VirtualBox</h2> <p>This command duplicates a registered virtual hard disk image to a new image file with a new unique identifier (UUID). The new image can be transferred to another host system or imported into VirtualBox again using the Virtual Media Manager; see the section called “The Virtual Media Manager” and the section called “Cloning disk images”. The syntax is as follows:</p> <pre> VBoxManage clonehd &lt;uuid&gt;|&lt;filename&gt; &lt;outputfile&gt; [--format VDI|VMDK|VHD|RAW|&lt;other&gt;] [--variant Standard,Fixed,Split2G,Stream,ESX] [--existing] </pre> <p>where the parameters mean:</p> <p><strong>format</strong> Allow to choose a file format for the output file different from the file format of the input file.</p> <p><strong>variant</strong> Allow to choose a file format variant for the output file. It is a comma-separated list of variant flags. Not all combinations are supported, and specifying inconsistent flags will result in an error message.</p> <p><strong>existing</strong> Perform the clone operation to an already existing destination medium. Only the portion of the source medium which fits into the destination medium is copied. This means if the destination medium is smaller than the source only a part of it is copied, and if the destination medium is larger than the source the remaining part of the destination medium is unchanged.</p> Finding one component location in the peoplesoft portal urn:md5:dfe98200e5cd1aba7b5a61190d1de890 2011-05-26T11:50:00+02:00 2011-12-02T15:52:54+01:00 Jean-Baptiste Heren Peoplesoft <p>Just replace the 'MY_COMPONENT_GBL' parameter in the following sql script. This works for MS SQl Server. You can add more levels by adding Outer Joins.</p> <pre>[SQL] /* Where is my component in the portal */ SELECT A.PORTAL_NAME, E.PORTAL_LABEL AS Parent4_folder, D.PORTAL_LABEL AS Parent3_folder, C.PORTAL_LABEL AS Parent2_folder, B.PORTAL_LABEL AS Parent_folder, A.PORTAL_LABEL AS Component FROM PSPRSMDEFN A LEFT JOIN PSPRSMDEFN B ON B.PORTAL_NAME = A.PORTAL_NAME AND B.PORTAL_OBJNAME = A.PORTAL_PRNTOBJNAME LEFT JOIN PSPRSMDEFN C ON C.PORTAL_NAME = B.PORTAL_NAME AND C.PORTAL_OBJNAME = B.PORTAL_PRNTOBJNAME LEFT JOIN PSPRSMDEFN D ON D.PORTAL_NAME = C.PORTAL_NAME AND D.PORTAL_OBJNAME = C.PORTAL_PRNTOBJNAME LEFT JOIN PSPRSMDEFN E ON E.PORTAL_NAME = D.PORTAL_NAME AND E.PORTAL_OBJNAME = D.PORTAL_PRNTOBJNAME WHERE A.PORTAL_REFTYPE = 'C' -- Parameter to set : AND A.PORTAL_URI_SEG2 = 'MY_COMPONENT_GBL' </pre> <p>Thanks to François R. for the following code which will do the same recursively. (Oracle only)</p> <pre>[SQL] SELECT DISTINCT RTRIM(REVERSE (SYS_CONNECT_BY_PATH(REVERSE ((SELECT B.PORTAL_LABEL FROM PSPRSMDEFNLANG B WHERE A.PORTAL_NAME = B.PORTAL_NAME AND A.PORTAL_OBJNAME = B.PORTAL_OBJNAME AND A.PORTAL_REFTYPE = B.PORTAL_REFTYPE AND B.LANGUAGE_CD = 'FRA')), ' &gt; ')), ' &gt; ') CHEMIN FROM PSPRSMDEFN A WHERE A.PORTAL_NAME = 'EMPLOYEE' AND A.PORTAL_PRNTOBJNAME = 'PORTAL_ROOT_OBJECT' START WITH PORTAL_URI_SEG2 = 'MY_COMPONENT' CONNECT BY PRIOR A.PORTAL_PRNTOBJNAME = A.PORTAL_OBJNAME; </pre> Cognos 8 - convert a member unique name from one hierarchy to another urn:md5:07d53922a2168685fa5806e759b000d5 2011-04-06T15:45:00+02:00 2011-05-09T09:25:21+02:00 Jean-Baptiste Heren Décisionnel CognosReport Studio <p>If you need to build any report or Event studio Query using the same data from different packages; and you want to prompt just once.</p> <p>You can convert the member unique name from one hierarchy to another, using the <a href="http://blog.jbheren.com/post/2009/11/13/Cognos-8-Macro-functions-list">cognos substitute macro</a>.</p> <h3>Consider the following example :</h3> <h4>You prompt on level value using the following hierarchy :</h4> <pre>[SQL] [First package].[First dimension].[First hierarchy].[First Level] </pre> <h4>Then you want to filter one Query built on another package using the same prompt value :</h4> <pre>[SQL] [Second package].[Second dimension].[Second hierarchy].[Second Level] </pre> <h4>It means yo uwant to convert :</h4> <pre>[SQL] -- Source hierarchy [First package].[First dimension].[First hierarchy].[First Level]-&gt;:[YK].[[First dimension]].[First hierarchy]].[First Level]].&amp;[00004]]] -- to Destination Hierarchy [Second package].[Second dimension].[Second hierarchy].[Second Level]-&gt;:[YK].[[Second dimension]].[Second hierarchy]].[Second Level]].&amp;[00004]]] </pre> <p>So you can use a Query element containing a <a href="http://blog.jbheren.com/post/2009/11/13/Cognos-8-Macro-functions-list">substitute macro</a> :</p> <pre>[SQL] -- Formula # sq(substitute ('First package','Second package', substitute ('First hierarchy','Second hierarchy', substitute ('First dimension','Second dimension', substitute ('First Level','Second Level', prompt('First Level Prompt Name', 'token')))))) # </pre> model.xml documentation in cognos 8 with xslt urn:md5:88da78e37f99ab7b588f608cb2ed9ca9 2011-03-30T06:56:00+02:00 2011-04-07T15:16:44+02:00 Jean-Baptiste Heren Décisionnel cognos 8xmlxslt <p>In one of my recent projects, I had to build an automatic documentation builded on top of a database, using <a href="http://blog.jbheren.com/tag/cognos%208">cognos 8</a> reporting itself.</p> <p>This article covers the way I could extract technical informations using the Cognos Framework manager project model.xml file.</p> <h3>1- Build xsl files</h3> <p>The XSLT language is used to define the way an xml should be displayed. This means you can select any parts of teh xml, based on his structure and build the output you want.</p> <h4>Defining the stylesheet</h4> <p>Here is an example witch displays a list of Query Subjects extracted from your project :</p> <pre>[XML] &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &lt;xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt; &lt;xsl:template match=&quot;/&quot;&gt; &lt;html&gt; &lt;body&gt; &lt;h1&gt;Query Subjects&lt;/h1&gt; &lt;table border=&quot;1&quot;&gt; &lt;tr&gt; &lt;td&gt;&lt;h2&gt;refObj&lt;/h2&gt;&lt;/td&gt; &lt;td&gt;&lt;h2&gt;Source Type&lt;/h2&gt;&lt;/td&gt; &lt;td&gt;&lt;h2&gt;Namespace&lt;/h2&gt;&lt;/td&gt; &lt;td&gt;&lt;h2&gt;Folder&lt;/h2&gt;&lt;/td&gt; &lt;td&gt;&lt;h2&gt;Query Subject&lt;/h2&gt;&lt;/td&gt; &lt;td&gt;&lt;h2&gt;dataSource&lt;/h2&gt;&lt;/td&gt; &lt;td&gt;&lt;h2&gt;sql&lt;/h2&gt;&lt;/td&gt; &lt;/tr&gt; &lt;xsl:for-each select=&quot;//querySubject[@status = 'valid']&quot;&gt; &lt;tr&gt; &lt;td&gt;&lt;p&gt;[&lt;xsl:value-of select=&quot;../../name&quot;/&gt;].[&lt;xsl:value-of select=&quot;name&quot;/&gt;]&lt;/p&gt;&lt;/td&gt; &lt;td&gt;&lt;p&gt;&lt;xsl:value-of select=&quot;definition/dbQuery/tableType&quot;/&gt;&lt;/p&gt;&lt;/td&gt; &lt;td&gt;&lt;p&gt;&lt;xsl:value-of select=&quot;../../name&quot;/&gt;&lt;/p&gt;&lt;/td&gt; &lt;td&gt;&lt;p&gt;&lt;xsl:value-of select=&quot;../name&quot;/&gt;&lt;/p&gt;&lt;/td&gt; &lt;td&gt;&lt;p&gt;&lt;xsl:value-of select=&quot;name&quot;/&gt;&lt;/p&gt;&lt;/td&gt; &lt;td&gt;&lt;p&gt;&lt;xsl:value-of select=&quot;definition/dbQuery/sources/dataSourceRef&quot;/&gt;&lt;/p&gt;&lt;/td&gt; &lt;td&gt;&lt;p&gt;&lt;xsl:value-of select=&quot;definition/dbQuery/sql&quot;/&gt;&lt;/p&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/xsl:for-each&gt; &lt;/table&gt; &lt;/body&gt; &lt;/html&gt; &lt;/xsl:template&gt;&lt;/xsl:stylesheet&gt; </pre> <h4>Applying the stylesheet</h4> <p>During the XSL development, we need to test the output of our xsl applyend to our model.xml "live". To do this, we will :</p> <p>- Add the stylesheed definition to your <strong>local copy</strong> of model.xml, like that :</p> <pre>[XML] &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &lt;?xml-stylesheet type=&quot;text/xsl&quot; href=&quot;modelspecs.xsl&quot;?&gt; &lt;project&gt; </pre> <p>- Open your xml in Internet Explorer or any other modern navigator and see the output.</p> <h3>2- Automatic processing</h3> <p>For my specific need, I wanted to generate automatic data files from different project's model.xml, to be used as source for some DTS.</p> <p>Here are four examples of XSL files extracting different informations. Of course, we can also build one single xml file containing all the informations :</p> <p>- cubes definitions : This example outputs pure text to be used as a CVS source in SSIS.</p> <pre>[XML] &lt;xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;&lt;xsl:strip-space elements=&quot;*&quot;/&gt;&lt;xsl:output method=&quot;text&quot;/&gt;&lt;xsl:template match=&quot;/&quot;&gt;refObj;Source type &lt;xsl:for-each select=&quot;//namespace&quot;&gt; &lt;xsl:if test=&quot;string-length(property[@name = 'dynamicContent']) != 0&quot;&gt;[&lt;xsl:value-of select=&quot;name&quot;/&gt;];Cube &lt;/xsl:if&gt; &lt;/xsl:for-each&gt; &lt;/xsl:template&gt;&lt;/xsl:stylesheet&gt; </pre> <p>- Query Subjects &amp; SQL : This example outputs simple xml file to be used as a XML source in SSIS.</p> <pre>[XML] &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &lt;xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt; &lt;xsl:output method=&quot;xml&quot; version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; indent=&quot;yes&quot; cdata-section-elements=&quot;sql&quot;/&gt; &lt;xsl:template match=&quot;/&quot;&gt; &lt;xsl:element name=&quot;root&quot;&gt; &lt;xsl:for-each select=&quot;//querySubject[@status = 'valid']&quot;&gt; &lt;xsl:element name=&quot;querySubjects&quot;&gt; &lt;xsl:element name=&quot;refObj&quot;&gt;[&lt;xsl:value-of select=&quot;../../name&quot;/&gt;].[&lt;xsl:value-of select=&quot;name&quot;/&gt;]&lt;/xsl:element&gt; &lt;xsl:element name=&quot;sourceType&quot;&gt;&lt;xsl:value-of select=&quot;definition/dbQuery/tableType&quot;/&gt;&lt;/xsl:element&gt; &lt;xsl:element name=&quot;namespace&quot;&gt;&lt;xsl:value-of select=&quot;../../name&quot;/&gt;&lt;/xsl:element&gt; &lt;xsl:element name=&quot;folder&quot;&gt;&lt;xsl:value-of select=&quot;../name&quot;/&gt;&lt;/xsl:element&gt; &lt;xsl:element name=&quot;querySubject&quot;&gt;&lt;xsl:value-of select=&quot;name&quot;/&gt;&lt;/xsl:element&gt; &lt;xsl:element name=&quot;dataSource&quot;&gt;&lt;xsl:value-of select=&quot;definition/dbQuery/sources/dataSourceRef&quot;/&gt;&lt;/xsl:element&gt; &lt;xsl:element name=&quot;sql&quot;&gt;&lt;xsl:value-of disable-output-escaping=&quot;yes&quot; select=&quot;definition/dbQuery/sql&quot;/&gt;&lt;/xsl:element&gt; &lt;/xsl:element&gt; &lt;/xsl:for-each&gt; &lt;/xsl:element&gt; &lt;/xsl:template&gt;&lt;/xsl:stylesheet&gt; </pre> <p>- Query Subjects &amp; Query items detail : This example outputs simple xml file to be used as a XML source in SSIS.</p> <pre>[XML] &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &lt;xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt; &lt;xsl:output method=&quot;xml&quot; version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; indent=&quot;yes&quot; cdata-section-elements=&quot;sql&quot;/&gt; &lt;xsl:template match=&quot;/&quot;&gt; &lt;xsl:element name=&quot;root&quot;&gt; &lt;xsl:for-each select=&quot;//querySubject[@status = 'valid']/queryItem&quot;&gt; &lt;xsl:element name=&quot;QueryItems&quot;&gt; &lt;xsl:element name=&quot;refObj&quot;&gt;[&lt;xsl:value-of select=&quot;../../../name&quot;/&gt;].[&lt;xsl:value-of select=&quot;../name&quot;/&gt;].[&lt;xsl:value-of select=&quot;name&quot;/&gt;]&lt;/xsl:element&gt; &lt;xsl:element name=&quot;parentRefObj&quot;&gt;[&lt;xsl:value-of select=&quot;../../../name&quot;/&gt;].[&lt;xsl:value-of select=&quot;../name&quot;/&gt;]&lt;/xsl:element&gt; &lt;xsl:element name=&quot;QueryItem&quot;&gt;&lt;xsl:value-of select=&quot;name&quot;/&gt;&lt;/xsl:element&gt; &lt;/xsl:element&gt; &lt;/xsl:for-each&gt; &lt;/xsl:element&gt; &lt;/xsl:template&gt;&lt;/xsl:stylesheet&gt; </pre> <p>- Framework Packages Definition and contents : This example outputs simple xml file to be used as a XML source in SSIS.</p> <pre>[XML] &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &lt;xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt; &lt;xsl:output method=&quot;xml&quot; version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; indent=&quot;yes&quot; cdata-section-elements=&quot;sql&quot;/&gt; &lt;xsl:template match=&quot;/&quot;&gt; &lt;xsl:element name=&quot;root&quot;&gt; &lt;xsl:for-each select=&quot;//securityView/definition/set/refobj&quot;&gt; &lt;xsl:element name=&quot;packages&quot;&gt; &lt;xsl:element name=&quot;packageName&quot;&gt;&lt;xsl:value-of select=&quot;../../../name&quot;/&gt;&lt;/xsl:element&gt; &lt;xsl:element name=&quot;contentRefObj&quot;&gt;&lt;xsl:value-of select=&quot;.&quot;/&gt;&lt;/xsl:element&gt; &lt;/xsl:element&gt; &lt;/xsl:for-each&gt; &lt;/xsl:element&gt; &lt;/xsl:template&gt;&lt;/xsl:stylesheet&gt; </pre> <p>- Framework Dimensions Definitions and contents : This example outputs simple xml file to be used as a XML source in SSIS.</p> <pre>[XML] &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &lt;xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt; &lt;xsl:output method=&quot;xml&quot; version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; indent=&quot;yes&quot; cdata-section-elements=&quot;sql&quot;/&gt; &lt;xsl:template match=&quot;/&quot;&gt; &lt;xsl:element name=&quot;root&quot;&gt; &lt;xsl:for-each select=&quot;//dimension[@status = 'valid']&quot;&gt; &lt;xsl:element name=&quot;dimensions&quot;&gt; &lt;xsl:element name=&quot;namespace&quot;&gt;&lt;xsl:value-of select=&quot;../name&quot;/&gt;&lt;/xsl:element&gt; &lt;xsl:element name=&quot;dimension&quot;&gt;&lt;xsl:value-of select=&quot;name&quot;/&gt;&lt;/xsl:element&gt; &lt;xsl:element name=&quot;modelQuery&quot;&gt;&lt;xsl:value-of select=&quot;definition/modelQuery/sql&quot;/&gt;&lt;/xsl:element&gt; &lt;xsl:for-each select=&quot;hierarchy&quot;&gt; &lt;xsl:element name=&quot;hierarchy&quot;&gt; &lt;xsl:element name=&quot;name&quot;&gt;&lt;xsl:value-of select=&quot;name&quot;/&gt;&lt;/xsl:element&gt; &lt;xsl:for-each select=&quot;.//refobj&quot;&gt; &lt;xsl:element name=&quot;refobject&quot;&gt;&lt;xsl:value-of select=&quot;.&quot;/&gt;&lt;/xsl:element&gt; &lt;/xsl:for-each&gt; &lt;/xsl:element&gt; &lt;/xsl:for-each&gt; &lt;/xsl:element&gt; &lt;/xsl:for-each&gt; &lt;/xsl:element&gt; &lt;/xsl:template&gt;&lt;/xsl:stylesheet&gt; </pre> <p>Command line xsl transformation is possible using the xslproc program :</p> <pre>[script] xsltproc mysxmltocsv.xsl model.xml &gt; doc.csv or xsltproc mysxmltoxml.xsl model.xml &gt; doc.xml </pre> <p>the unix tool xmlproc is also available in the libxslt binary package for windows at following address : ftp://ftp.zlatkovic.com/libxml/</p> <h3>3- Conclusion</h3> <p>Hope it will help someone, it's quite hard to find informations on how to dicument Cognos. if anyone has anything to share, I am still interested ^^.</p> Generate Extended properties in MS Sql Server 2005+ urn:md5:c93bd7c9259f6303069b285bf0dc2c62 2011-03-28T23:02:00+02:00 2011-03-29T13:46:40+02:00 Jean-Baptiste Heren Décisionnel Business IntelligenceExcelSQL Server 2005 <p>When you work with databases, it's cool to Keep all the documentation in the system, so that it is available for reporting and all kind of analysis.</p> <p>Microsoft <a href="http://blog.jbheren.com/tag/SQL%20Server%202005">SQL Server 2005</a>+ provides the ability to create Extended properties on tables (or even fields). Those properties are available using SQL management studio, on the tables properties panel.</p> <p><img src="http://blog.jbheren.com/public/Decisionnel/sql_server/.extended_properties_panel_m.jpg" alt="extended_properties_panel.jpg" title="extended_properties_panel.jpg, mar. 2011" /></p> <p>Here I will explain how you can generate them fast using Excel and macro AND Extract them using SQL.</p> <h2>1- Generate SQL Script to insert properties and values from an <a href="http://blog.jbheren.com/tag/Excel">Excel</a> sheet</h2> <p>Usually, for any initial documentation, it will be easyer to fill an excel sheet and generate allk the indidual properties automatically. You don't want to spend a week filling all the stuff manually(!). You will find as an attachment to this post, an <a href="http://blog.jbheren.com/tag/Excel">Excel</a> demonstration excel file containing a simple sheet template and a macro. The maco will gerenate SQL instructions like this :</p> <pre>[SQL] EXEC sys.sp_addextendedproperty @name=N'MY_PROPERTY_NAME', @value=N'MY_PROPERTY_VALUE', @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'MY_TABLE_NAME'; </pre> <p>Here is the SQL macro code</p> <pre>[VB] Sub generateSQLSpecialProperties() ' Author: Jean-Baptiste Heren - 2011-03-29 - http://blog.jbheren.com ' Loop on current scheet and generate sql sys.sp_addextendedproperty based on sheet contents ' First column contains the table name ' first line contains the Properties names ex: Table_name | prop_description | prop_rule ... Dim tableName As String 'tablename extracted from first row of each column Dim filePath As String Dim slashPosition As Integer Dim pathOnly As String Dim dataSQL As String ' will contain the SQL Contents Dim separator As String Dim myRow As Integer 'Row counter Dim myCol As Integer 'Column counter ' get current excel file Path filePath = ThisWorkbook.FullName slashPosition = InStrRev(filePath, &quot;\&quot;) pathOnly = Left(filePath, slashPosition) MyFile = pathOnly + ActiveSheet.Name + &quot;_macro_generated.sql&quot; 'get column values from second row myRow = 2 myCol = 2 'set and open file for output fnum = FreeFile() Open MyFile For Output As fnum Do Until ActiveSheet.Cells(myRow, myCol) = &quot;&quot; 'Loop on rows until blank. tableName = Trim(CStr(ActiveSheet.Cells(myRow, 1))) 'get Table name from first column Do Until ActiveSheet.Cells(myRow, myCol) = &quot;&quot; 'Loop on columns until blank. property_name = Trim(CStr(ActiveSheet.Cells(1, myCol))) 'get Property name from first column property_descr = Replace(Trim(CStr(ActiveSheet.Cells(myRow, myCol))), &quot;'&quot;, &quot;''&quot;) dataSQL = &quot;EXEC sys.sp_addextendedproperty @name=N'&quot; + property_name + &quot;'&quot; dataSQL = dataSQL + &quot;, @value=N'&quot; + property_descr + &quot;'&quot; dataSQL = dataSQL + &quot;, @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE'&quot; dataSQL = dataSQL + &quot;,@level1name=N'&quot; + tableName + &quot;';&quot; myCol = myCol + 1 Loop myCol = 2 ' Return to specifiedcolumn myRow = myRow + 1 ' Move to next row Print #fnum, dataSQL Loop ' Close the file Close #fnum End Sub </pre> <h2>2- Extract table properties from SQL Sercer System tables</h2> <pre>[SQL] /* get extended properties on Tables */ SELECT A.NAME as table_name ,B.name as property_name ,B.value as property_value FROM SYSOBJECTS A INNER JOIN sys.extended_properties B on A.id = B.major_id WHERE A.type = 'U' </pre> Cognos Content store Tables Description urn:md5:f11d5baa5b1fb932f308ebfa8d3762f4 2011-03-28T22:57:00+02:00 2011-05-09T09:24:10+02:00 Jean-Baptiste Heren Décisionnel Cognos Content Store <p>Here is the list of Cognos Content store tables with Description. Those informations come from an old document from Cognos so it may not be totally up to date.</p> <table> <tr> <th>Table name </th> <th>Descrition </th> </tr> <tr> <td> <span class="caps"><span class="caps">CMSYSPROPS</span></span> </td> <td> This table has the Content Store Version. </td> </tr> <tr> <td> <span class="caps"><span class="caps">CMOBJNAMES</span></span> </td> <td> This table has the names of all the objects in the content store. </td> </tr> <tr> <td> CMOBJPROPS1 </td> <td> Users, Roles \ Group Distribution list and contact information such as Email, phone number, Fax Given name etc are stored in this table </td> </tr> <tr> <td> CMOBJPROPS2 </td> <td> Report scheduling information is stored. This table has fields like hour, day week etc </td> </tr> <tr> <td> CMOBJPROPS3 </td> <td> Stores Screen Tip and Object description provided while creating the objects are stored here </td> </tr> <tr> <td> CMOBJPROPS4 </td> <td> Stores the printer paper setting details like height and width of A3 , A4 , letter and 11X17 paper orientations </td> </tr> <tr> <td> CMOBJPROPS6 </td> <td> Has the details of the all packages which were published using the FM. </td> </tr> <tr> <td> CMOBJPROPS7 </td> <td> This table stores the <span class="caps"><span class="caps">XML</span></span> of all reports and models. This is basically to maintain the metadata about the structure of the reports and models. </td> </tr> <tr> <td> CMOBJPROPS10 </td> <td> Contact information is stored in this table. This table has columns like Contact Email and Contact. </td> </tr> <tr> <td> CMOBJPROPS11 </td> <td> This table stores the data sources configuration details like connect string, the cube location etc. </td> </tr> <tr> <td> CMOBJPROPS13 </td> <td> It stores the names of parameter passed to the range prompts </td> </tr> <tr> <td> CMOBJPROPS14 </td> <td> Has details regarding the versions, creation time etc of the objects in the content store. </td> </tr> <tr> <td> CMOBJPROPS16 </td> <td> This table provides the status of the multiple services of Cognos like LogService, MonitorService, ReportService, SystemService, JobService </td> </tr> <tr> <td> CMOBJPROPS17 </td> <td> Stores performance details of each component like “query Studio, Analysis Studio, Event Studio” etc </td> </tr> <tr> <td> CMOBJPROPS18 </td> <td> This table stores the drill path from the source to the final target report. </td> </tr> <tr> <td> CMOBJPROPS20 </td> <td> Stores details regarding which are all the reports for which prompting has been enabled. And also has the details of which are the reports which has the default report options overridden. </td> </tr> <tr> <td> CMOBJPROPS24 </td> <td> Stores the printer configuration details </td> </tr> <tr> <td> CMOBJPROPS25 </td> <td> Stores the data regarding the objects deployed, like the deployed folder, the reports, the number of folders present in the deployment archive, etc </td> </tr> <tr> <td> CMOBJPROPS26 </td> <td> This table stores the data about all the packages imported / exported in C8, with the properties selected during the process. </td> </tr> <tr> <td> CMOBJPROPS27 </td> <td> Has the details regarding the data source created in the content store using Cubes. </td> </tr> <tr> <td> CMOBJPROPS30 </td> <td> Stores the registration , service description etc details about portlets in this table </td> </tr> <tr> <td> CMOBJPROPS31 </td> <td> Has the custom logging level for each of the Cognos services, <span class="caps"><span class="caps">CMID</span></span> can be be linked to <span class="caps"><span class="caps">CMOBJNAMES</span></span> for the names of each of the services </td> </tr> <tr> <td> CMOBJPROPS32 </td> <td> Has the details of the stored procedures used as the query items in the FM model. </td> </tr> <tr> <td> CMOBJPROPS33 </td> <td> Detail related to users, user groups user roles. </td> </tr> <tr> <td> CMOBJPROPS34 </td> <td> Has the details regarding the drill through parameters of the drill through reports. The parameter assign values are present in coded format </td> </tr> <tr> <td> CMOBJPROPS36 </td> <td> Has the list of all the Models published using framework manager </td> </tr> <tr> <td> CMOBJPROPS37 </td> <td> This table has the details of the routing sets configured for server / load balancing for each package published in the content store </td> </tr> <tr> <td> CMOBJPROPS38 </td> <td> Configuration details about number of items to retrieve in studios, for a package are saved under this table. </td> </tr> <tr> <td> CMOBJPROPS39 </td> <td> Has values for properties of reports and views. <span class="caps"><span class="caps">PROPID</span></span> can be linked to <span class="caps"><span class="caps">CMPROPERTIES</span></span> for property names </td> </tr> <tr> <td> CMOBJPROPS52 </td> <td> Contains the properties for the connections </td> </tr> <tr> <td> CMOBJPROPS55 </td> <td> Has the <span class="caps"><span class="caps">URI</span></span> for icons for each entry in Cognos Connection </td> </tr> <tr> <td> <span class="caps"><span class="caps">CMLOCALES</span></span> </td> <td> Has the locale ids associated with each language supported by Cognos 8 </td> </tr> </table> Extract Cognos reports & packages list with path urn:md5:0089f16face722c3674e9a4c0b49bc5a 2011-03-28T22:33:00+02:00 2011-03-29T13:46:59+02:00 Jean-Baptiste Heren Décisionnel CognosCognos Content StoreSQL <p>When you want to make a documentation on <a href="http://blog.jbheren.com/tag/Cognos">Cognos</a> (or anything), it's hard to keep it updated...</p> <p>One of my recent projects has been to buid an automatic documentation on Cognos, showing dependencies between packages, reports and even source tables or ETL packages. Here I share with you, some <a href="http://blog.jbheren.com/tag/SQL">SQL</a> scripts extracting information from the <a href="http://blog.jbheren.com/tag/Cognos%20Content%20Store">Cognos Content Store</a>. Hope it will be helpful.</p> <pre>[SQL] /* Author: Jean-Baptiste HEREN - 2010-07-06 */ /* Descr: extract Report model XML from database */ select names.name, specs.spec from CMOBJNAMES names inner join CMOBJPROPS7 specs on names.CMID = specs.CMID where names.name LIKE '%Audit%' /* Author: Jean-Baptiste HEREN - 2010-07-06 */ /* Descr: extract packages list */ SELECT DISTINCT cmobjects.cmid, cmobjnames.name as package_name FROM cmrefnoord1 INNER JOIN cmobjects ON cmrefnoord1.refcmid = cmobjects.cmid INNER JOIN cmobjnames ON cmobjects.cmid = cmobjnames.cmid WHERE cmrefnoord1.propid = 31 AND cmobjnames.localeid IN ( '24', '100') /* Author: Jean-Baptiste HEREN - 2011-03-15 */ /* Descr: - Report names, full Paths &amp; related package name from cognoscs database */ /* CMOBJPROPS25 - Stores the data regarding the objects deployed, like the deployed folder, the reports, the number of folders present in the deployment archive, etc*/ SELECT DISTINCT rank() OVER(ORDER BY package_name,NAME,max(Path) ASC) as rank, NAME as report_name, package_name, RTRIM(max(Path)) as path, cast(storeID as nvarchar) as store_id FROM ( SELECT A.CMID, L1.mapdlocaleid, L1.locale, L1.TYPE ,L1.NAME /*, L9.NAME, L8.NAME, L7.NAME, L6.NAME , L5.NAME, L4.NAME , L3.NAME , L2.NAME*/ , LTRIM(SUBSTRING( CASE WHEN isnull(L10.NAME,'') = '/' THEN ' ' ELSE isnull(L10.NAME,'') END + CASE WHEN L10.NAME = '/' THEN '' ELSE '/' END + CASE WHEN isnull(L9.NAME,'') = '/' THEN ' ' ELSE isnull(L9.NAME,'') END + CASE WHEN L9.NAME = '/' THEN '' ELSE '/' END + CASE WHEN isnull(L8.NAME,'') = '/' THEN ' ' ELSE isnull(L8.NAME,'') END + CASE WHEN L8.NAME = '/' THEN '' ELSE '/' END + CASE WHEN isnull(L7.NAME,'') = '/' THEN ' ' ELSE isnull(L7.NAME,'') END + CASE WHEN L7.NAME = '/' THEN '' ELSE '/' END + CASE WHEN isnull(L6.NAME,'') = '/' THEN ' ' ELSE isnull(L6.NAME,'') END + CASE WHEN L6.NAME = '/' THEN '' ELSE '/' END + CASE WHEN isnull(L5.NAME,'') = '/' THEN ' ' ELSE isnull(L5.NAME,'') END + CASE WHEN L5.NAME = '/' THEN '' ELSE '/' END + CASE WHEN isnull(L4.NAME,'') = '/' THEN ' ' ELSE isnull(L4.NAME,'') END + CASE WHEN L4.NAME = '/' THEN '' ELSE '/' END + CASE WHEN isnull(L3.NAME,'') = '/' THEN ' ' ELSE isnull(L3.NAME,'') END + CASE WHEN L3.NAME = '/' THEN '' ELSE '/' END + isnull(L2.NAME ,'') + CASE WHEN L2.NAME = '/' THEN '' ELSE '/' END --+ isnull(L1.NAME ,'') , CHARINDEX('Public', isnull(L10.NAME,'') + CASE WHEN L10.NAME = '/' THEN '' ELSE '/' END + isnull(L9.NAME ,'') + CASE WHEN L9.NAME = '/' THEN '' ELSE '/' END + isnull(L8.NAME ,'') + CASE WHEN L8.NAME = '/' THEN '' ELSE '/' END + isnull(L7.NAME ,'') + CASE WHEN L7.NAME = '/' THEN '' ELSE '/' END + isnull(L6.NAME ,'') + CASE WHEN L6.NAME = '/' THEN '' ELSE '/' END + isnull(L5.NAME ,'') + CASE WHEN L5.NAME = '/' THEN '' ELSE '/' END + isnull(L4.NAME ,'') + CASE WHEN L4.NAME = '/' THEN '' ELSE '/' END + isnull(L3.NAME ,'') + CASE WHEN L3.NAME = '/' THEN '' ELSE '/' END + isnull(L2.NAME ,'') + CASE WHEN L2.NAME = '/' THEN '' ELSE '/' END --+ isnull(L1.NAME ,'') ), LEN( isnull(L10.NAME,'') + CASE WHEN L10.NAME = '/' THEN '' ELSE '/' END + isnull(L9.NAME ,'') + CASE WHEN L9.NAME = '/' THEN '' ELSE '/' END + isnull(L8.NAME ,'') + CASE WHEN L8.NAME = '/' THEN '' ELSE '/' END + isnull(L7.NAME ,'') + CASE WHEN L7.NAME = '/' THEN '' ELSE '/' END + isnull(L6.NAME ,'') + CASE WHEN L6.NAME = '/' THEN '' ELSE '/' END + isnull(L5.NAME ,'') + CASE WHEN L5.NAME = '/' THEN '' ELSE '/' END + isnull(L4.NAME ,'') + CASE WHEN L4.NAME = '/' THEN '' ELSE '/' END + isnull(L3.NAME ,'') + CASE WHEN L3.NAME = '/' THEN '' ELSE '/' END + isnull(L2.NAME ,'') + CASE WHEN L2.NAME = '/' THEN '' ELSE '/' END --+ isnull(L1.NAME ,'') )) ) as Path FROM CMOBJECTS A INNER JOIN ( SELECT cmobjnames.cmid, cmstoreids.storeid, cmobjects.pcmid, cmobjnames.name, cmobjnames.mapdlocaleid, cmobjnames.localeid, cmlocales.locale, cmclasses.name as type FROM cmobjects, cmobjnames, cmclasses, cmstoreids, cmlocales WHERE cmobjects.cmid = cmobjnames.cmid AND cmobjects.classid = cmclasses.classid AND cmobjects.cmid = cmstoreids.cmid AND cmclasses.name in('report') AND cmobjnames.localeid = cmlocales.localeid and cmlocales.locale in ('fr','en') ) L1 ON A.cmid = L1.cmid INNER JOIN ( SELECT cmobjnames.cmid, cmstoreids.storeid, cmobjects.pcmid, cmobjnames.name, cmobjnames.mapdlocaleid, cmobjnames.localeid, cmlocales.locale, cmclasses.name as type FROM cmobjects, cmobjnames, cmclasses, cmstoreids, cmlocales WHERE cmobjects.cmid = cmobjnames.cmid AND cmobjects.classid = cmclasses.classid AND cmobjects.cmid = cmstoreids.cmid AND cmobjnames.localeid = cmlocales.localeid and cmlocales.locale in ('fr','en') ) L2 ON L1.pcmid = L2.cmid INNER JOIN ( SELECT cmobjnames.cmid, cmstoreids.storeid, cmobjects.pcmid, cmobjnames.name, cmobjnames.mapdlocaleid, cmobjnames.localeid, cmlocales.locale, cmclasses.name as type FROM cmobjects, cmobjnames, cmclasses, cmstoreids, cmlocales WHERE cmobjects.cmid = cmobjnames.cmid AND cmobjects.classid = cmclasses.classid AND cmobjects.cmid = cmstoreids.cmid AND cmobjnames.localeid = cmlocales.localeid and cmlocales.locale in ('fr','en') ) L3 ON L2.pcmid = L3.cmid INNER JOIN ( SELECT cmobjnames.cmid, cmstoreids.storeid, cmobjects.pcmid, cmobjnames.name, cmobjnames.mapdlocaleid, cmobjnames.localeid, cmlocales.locale, cmclasses.name as type FROM cmobjects, cmobjnames, cmclasses, cmstoreids, cmlocales WHERE cmobjects.cmid = cmobjnames.cmid AND cmobjects.classid = cmclasses.classid AND cmobjects.cmid = cmstoreids.cmid AND cmobjnames.localeid = cmlocales.localeid and cmlocales.locale in ('fr','en') ) L4 ON L3.pcmid = L4.cmid INNER JOIN ( SELECT cmobjnames.cmid, cmstoreids.storeid, cmobjects.pcmid, cmobjnames.name, cmobjnames.mapdlocaleid, cmobjnames.localeid, cmlocales.locale, cmclasses.name as type FROM cmobjects, cmobjnames, cmclasses, cmstoreids, cmlocales WHERE cmobjects.cmid = cmobjnames.cmid AND cmobjects.classid = cmclasses.classid AND cmobjects.cmid = cmstoreids.cmid AND cmobjnames.localeid = cmlocales.localeid and cmlocales.locale in ('fr','en') ) L5 ON L4.pcmid = L5.cmid INNER JOIN ( SELECT cmobjnames.cmid, cmstoreids.storeid, cmobjects.pcmid, cmobjnames.name, cmobjnames.mapdlocaleid, cmobjnames.localeid, cmlocales.locale, cmclasses.name as type FROM cmobjects, cmobjnames, cmclasses, cmstoreids, cmlocales WHERE cmobjects.cmid = cmobjnames.cmid AND cmobjects.classid = cmclasses.classid AND cmobjects.cmid = cmstoreids.cmid AND cmobjnames.localeid = cmlocales.localeid and cmlocales.locale in ('fr','en') ) L6 ON L5.pcmid = L6.cmid INNER JOIN ( SELECT cmobjnames.cmid, cmstoreids.storeid, cmobjects.pcmid, cmobjnames.name, cmobjnames.mapdlocaleid, cmobjnames.localeid, cmlocales.locale, cmclasses.name as type FROM cmobjects, cmobjnames, cmclasses, cmstoreids, cmlocales WHERE cmobjects.cmid = cmobjnames.cmid AND cmobjects.classid = cmclasses.classid AND cmobjects.cmid = cmstoreids.cmid AND cmobjnames.localeid = cmlocales.localeid and cmlocales.locale in ('fr','en') ) L7 ON L6.pcmid = L7.cmid INNER JOIN ( SELECT cmobjnames.cmid, cmstoreids.storeid, cmobjects.pcmid, cmobjnames.name, cmobjnames.mapdlocaleid, cmobjnames.localeid, cmlocales.locale, cmclasses.name as type FROM cmobjects, cmobjnames, cmclasses, cmstoreids, cmlocales WHERE cmobjects.cmid = cmobjnames.cmid AND cmobjects.classid = cmclasses.classid AND cmobjects.cmid = cmstoreids.cmid AND cmobjnames.localeid = cmlocales.localeid and cmlocales.locale in ('fr','en') ) L8 ON L7.pcmid = L8.cmid INNER JOIN ( SELECT cmobjnames.cmid, cmstoreids.storeid, cmobjects.pcmid, cmobjnames.name, cmobjnames.mapdlocaleid, cmobjnames.localeid, cmlocales.locale, cmclasses.name as type FROM cmobjects, cmobjnames, cmclasses, cmstoreids, cmlocales WHERE cmobjects.cmid = cmobjnames.cmid AND cmobjects.classid = cmclasses.classid AND cmobjects.cmid = cmstoreids.cmid AND cmobjnames.localeid = cmlocales.localeid and cmlocales.locale in ('fr','en') ) L9 ON L8.pcmid = L9.cmid INNER JOIN ( SELECT cmobjnames.cmid, cmstoreids.storeid, cmobjects.pcmid, cmobjnames.name, cmobjnames.mapdlocaleid, cmobjnames.localeid, cmlocales.locale, cmclasses.name as type FROM cmobjects, cmobjnames, cmclasses, cmstoreids, cmlocales WHERE cmobjects.cmid = cmobjnames.cmid AND cmobjects.classid = cmclasses.classid AND cmobjects.cmid = cmstoreids.cmid AND cmobjnames.localeid = cmlocales.localeid and cmlocales.locale in ('fr','en') ) L10 ON L9.pcmid = L10.cmid WHERE CLASSID IN (10,18) -- reports &amp; packages -- AND DISABLED is NULL ) Z INNER JOIN cmstoreids on Z.CMID = cmstoreids.CMID INNER JOIN (SELECT cmrefnoord1.cmid AS pid, cmobjnames.name as package_name FROM cmrefnoord1 INNER JOIN cmobjects ON cmrefnoord1.refcmid = cmobjects.cmid INNER JOIN cmobjnames ON cmobjects.cmid = cmobjnames.cmid WHERE cmrefnoord1.propid = 31 AND cmobjnames.localeid IN ( '24', '100') ) PKG on Z.CMID = PKG.PID --WHERE Path like '%/REPORTING/%' group by NAME, package_name, storeID </pre> Repair HFS+ Volume on OSX urn:md5:e1b4e2647fe8360f4699e9cc1cbc01be 2011-02-09T00:26:00+01:00 2011-02-09T07:14:26+01:00 Jean-Baptiste Heren Linux disk repairfsckhfsplusMacOSXsnow leopard <p><img src="http://blog.jbheren.com/public/tuto/OSX/.harddrive_osx_m.jpg" alt="harddrive_osx.png" style="float:left; margin: 0 1em 1em 0;" title="harddrive_osx.png, fév. 2011" />Yesterday I had a little surprise on one of my disks (the backup one.Disk utility was unable to repair it, but here you will find some tips</p> <h2>1- read your disk with Linux</h2> <p>Boot on <a href="http://www.ubuntu.com/desktop/get-ubuntu/download" hreflang="en">Ubuntu live CD</a> and try to open your disk. It will mount read-only (default for HFS) but you will be able to grab most of your files to a network or FAT external drive. This saved my life a couple of times.</p> <h2>2- repair with fsck on OSX</h2> <p>Fsck is also available on OSX. Let's open your terminal. On the following commands, replace /dev/disk1s2 with the location of your disk's partition.</p> <h3>2.1 - run a diagnostc</h3> <pre>[script] MyMac:~ jb$ fsck -fy /dev/disk1s2 ** /dev/rdisk1s2 BAD SUPER BLOCK: MAGIC NUMBER WRONG LOOK FOR ALTERNATE SUPERBLOCKS? yes SEARCH FOR ALTERNATE SUPER-BLOCK FAILED. YOU MUST USE THE -b OPTION TO FSCK TO SPECIFY THE LOCATION OF AN ALTERNATE SUPER-BLOCK TO SUPPLY NEEDED INFORMATION; SEE fsck(8). </pre> <h3>2.2 - repair by adding the r option</h3> <p>This can take a while, it took 60min for my 1,5TB Disk.</p> <pre>[script] MyMac:~ jb$ fsck_hfs -fy /dev/disk1s2 ** /dev/rdisk1s2 Executing fsck_hfs (version diskdev_cmds-491.3~2). ** Checking Journaled HFS Plus volume. ** Checking extents overflow file. ** Checking catalog file. Invalid node structure (4, 242826) ** The volume Grozor could not be verified completely. iMac-de-la-familia:~ jb$ fsck_hfs -ypr /dev/disk1s2 Executing fsck_hfs (version diskdev_cmds-491.3~2). ** Checking Journaled HFS Plus volume. ** Checking extents overflow file. ** Checking catalog file. ** Rebuilding catalog B-tree. Invalid node structure (4, 242826) Invalid record count (4, 242827) Invalid record count (4, 242828) Invalid record count (4, 242829) Invalid record count (4, 242830) Invalid record count (4, 242831) ** Rechecking volume. ** Checking Journaled HFS Plus volume. ** Checking extents overflow file. ** Checking catalog file. Missing thread record (id = 47443244) Incorrect number of thread records (4, 21586) Incorrect number of thread records (4, 21586) ** Checking multi-linked files. Incorrect number of file hard links ** Checking catalog hierarchy. Invalid directory item count (It should be 428 instead of 440) Missing thread record (id = 47443242) Invalid directory item count (It should be 0 instead of 1) Invalid directory item count (It should be 107 instead of 440) Invalid directory item count (It should be 673621 instead of 673646) Invalid volume file count (It should be 4308261 instead of 4309339) ** Checking extended attributes file. Incorrect number of extended attributes (It should be 1823295 instead of 1823257) Incorrect number of Access Control Lists (It should be 1823272 instead of 1823234) ** Checking multi-linked directories. Incorrect number of directory hard links ** Checking volume bitmap. Volume bitmap needs minor repair for orphaned blocks ** Checking volume information. Invalid volume free block count (It should be 19453978 instead of 7705538) Volume header needs minor repair (2, 0) ** Repairing volume. ... </pre> <p>If your drive is sill not repaired :</p> <pre>[script] Invalid first link in hard link chain (id = 47694526) (It should be 49482808 instead of 49484125) ** Look for missing items in lost+found directory. ** The volume Grozor could not be repaired. </pre> <p>Then you can try to fix it again with your Disk utilities (Application/utilities) <img src="http://blog.jbheren.com/public/tuto/OSX/.utilitaire_disques_m.jpg" alt="utilitaire_disques.png" style="float:right; margin: 0 0 1em 1em;" title="utilitaire_disques.png, fév. 2011" /></p> <p>Then if you are as lucky than I was, you will be able to mount under OSX. Now it is wise to backup important files (if not already done) and run a physical test.</p> Apostrophe, le CMS naturel urn:md5:a854519c396f600a03ccdd9e0bcf6dc7 2011-01-25T10:21:00+01:00 2011-01-25T10:23:26+01:00 Jean-Baptiste Heren Veille techno CMSdéveloppement webFramework WebPHPSymfony <p><img src="http://blog.jbheren.com/public/tuto/apostrophe/.apostrophe_m.jpg" alt="apostrophe.jpg" style="float:left; margin: 0 1em 1em 0;" title="apostrophe.jpg, janv. 2011" />Apostrophe est un CMS d'un genre différent. Finies les interfaces d'administration aux structures compliquées et aux fonctions absconses. Avec Apostrophe, vous éditez le contenu directement là ou il se trouve, sur le "frontend". Ce CMS a été construit à partir du célèbre framework Symfony, et une sandbox incluant tous les éléments nécessaires est fournie par les développeurs de <a href="http://www.apostrophenow.com/" hreflang="en">P'unk Avenue</a>.</p> <p>En plus d'être un CMS, Apostrophe contient un moteur de Blog, un gestionnaire de médias, et peut être synchronisé avec des sources de contenu externe comme youtube ou dailymotion. De plus, il est extensible. Vous pourrez donc développer vos propres types de "slots".</p> <p>Je vous invite à l'essayer directement à l'adresse suivante: <a href="http://demo.apostrophenow.com/." hreflang="en">http://demo.apostrophenow.com/.</a> Pour vous connecter, utilisez les identifiants admin/demo.</p> Configure Virtual Hosts in WAMP Server (MS Windows) urn:md5:8d152cf4bc7c3fe55ed53798cdb5bfb3 2011-01-24T23:45:00+01:00 2011-01-25T10:53:15+01:00 Jean-Baptiste Heren développement Web apachedéveloppement webMysqlPHP <p><img src="http://www.wampserver.com/data/image_menu_wamp.gif" alt="image_menu_wamp.gif" style="float:left; margin: 0 1em 1em 0;" title="image_menu_wamp.gif, janv. 2011" /><a href="http://www.wampserver.com/" hreflang="en">WAMP</a> is a standalone LAMP(Linux Apache Mysql Php) installation package for windows. It is very usefull when you want to try or develop something fast on your local machine.</p> <p>In the following example, WAMP is located on d:\wamp. This is not really important here, but I have four different hosts installed :</p> <ul> <li>sf.localhost : symfony project</li> <li>mag.localhost : Magento Installation</li> <li>a.localhost : Apostrophe CMS installation</li> <li>localhost : the default WAMP home page</li> </ul> <h2>1- Edit the httpd.conf</h2> <p>Uncomment the following line to inclute the httpd-vhosts.conf file.</p> <pre>[script] # Virtual hosts Include conf/extra/httpd-vhosts.conf </pre> <h2></h2> <p>2- Define your virtual hosts with the httpd-vhosts.conf The file is located in wamp\bin\apache\Apache2.2.11\conf\extra. Here is an example defining 3 virtualhosts plus the default localhost</p> <pre>[script] # # Virtual Hosts # # If you want to maintain multiple domains/hostnames on your # machine you can setup VirtualHost containers for them. Most configurations # use only name-based virtual hosts so the server doesn't need to worry about # IP addresses. This is indicated by the asterisks in the directives below. # # Please see the documentation at # &lt;URL:http://httpd.apache.org/docs/2.2/vhosts/&gt; # for further details before you try to setup virtual hosts. # # You may use the command line option '-S' to verify your virtual host # configuration. # # Use name-based virtual hosting. # NameVirtualHost *:80 # # VirtualHost example: # Almost any Apache directive may go into a VirtualHost container. # The first VirtualHost section is used for all requests that do not # match a ServerName or ServerAlias in any &lt;VirtualHost&gt; block. # # Magento &lt;VirtualHost *:80&gt; ServerAdmin webmaster@mag.localhost DocumentRoot &quot;D:\wamp\www\magento&quot; ServerName mag.localhost ErrorLog &quot;logs/mag.localhost-error.log&quot; CustomLog &quot;logs/mag.localhost-access.log&quot; common &lt;Directory &quot;D:\wamp\www\magento&quot;&gt; Options Indexes FollowSymLinks AllowOverride all Order Deny,Allow Deny from all Allow from 127.0.0.1 &lt;/Directory&gt; &lt;/VirtualHost&gt; # localhost &lt;VirtualHost *:80&gt; ServerAdmin webmaster@localhost DocumentRoot &quot;d:\wamp\www&quot; ServerName localhost ErrorLog &quot;logs/localhost-error.log&quot; CustomLog &quot;logs/localhost-access.log&quot; common &lt;Directory &quot;d:\wamp\www&quot;&gt; Options Indexes FollowSymLinks AllowOverride all Order Deny,Allow Deny from all Allow from 127.0.0.1 &lt;/Directory&gt; &lt;/VirtualHost&gt; # Symfony &lt;VirtualHost *:80&gt; ServerAdmin webmaster@sf.localhost DocumentRoot &quot;d:/wamp/www/sf_sandbox/web/&quot; ServerName sf.localhost ServerAlias www.sf.localhost ErrorLog &quot;logs/sf.localhost-error.log&quot; CustomLog &quot;logs/dummy-host.localhost-access.log&quot; common &lt;Directory &quot;d:/wamp/www/sf_sandbox/web/&quot;&gt; Options Indexes FollowSymLinks AllowOverride all Order Deny,Allow Deny from all Allow from 127.0.0.1 &lt;/Directory&gt; Alias /sf/ &quot;d:\wamp\www\sf_sandbox\lib\vendor\symfony\data\web\sf/&quot; &lt;Directory &quot;d:\wamp\www\sf_sandbox\lib\vendor\symfony\data\web\sf/&quot;&gt; Options Indexes FollowSymLinks MultiViews AllowOverride all Order allow,deny Allow from all &lt;/Directory&gt; &lt;/VirtualHost&gt; # Apostrophe Symfony &lt;VirtualHost *:80&gt; ServerAdmin webmaster@a.localhost DocumentRoot &quot;d:/wamp/www/asandbox/web/&quot; ServerName a.localhost ServerAlias www.a.localhost ErrorLog &quot;logs/sf.localhost-error.log&quot; CustomLog &quot;logs/dummy-host.localhost-access.log&quot; common &lt;Directory &quot;d:/wamp/www/asandbox/web/&quot;&gt; Options Indexes FollowSymLinks AllowOverride all Order Deny,Allow Deny from all Allow from 127.0.0.1 &lt;/Directory&gt; Alias /sf/ &quot;d:\wamp\www\asandbox\lib\vendor\symfony\data\web\sf/&quot; &lt;Directory &quot;d:\wamp\www\asandbox\lib\vendor\symfony\data\web\sf/&quot;&gt; Options Indexes FollowSymLinks MultiViews AllowOverride all Order allow,deny Allow from all &lt;/Directory&gt; &lt;/VirtualHost&gt; </pre> <h2>3- Add your virtual hosts to the local hosts.conf</h2> <p>Edit the file located in C:\WINDOWS\system32\drivers\etc\hosts, then add your virtual hosts.</p> <pre>[script] 127.0.0.1 localhost 127.0.0.1 sf.localhost 127.0.0.1 mag.localhost 127.0.0.1 a.localhost </pre> <h2>4- Start Wamp &amp; give a try</h2> <p>After you started wamp, you can now open your navigator an give a try to your dirrefent virtual hosts. Apache will recognize automatically the address you want to access, even if everything is hosted on the same machine.</p> Analysis Services 2005 : L'erreur système suivante s'est produite : . urn:md5:ea963c23ec708d8a1a15c7a70946830e 2011-01-24T16:39:00+01:00 2011-01-25T13:41:59+01:00 Jean-Baptiste Heren Décisionnel Analysis ServicesSQL ServerSQL Server 2005 <p>Voici une astuce pour SSAS sous SQL Server 2005. Si vous rencontrez l'erreur&nbsp;:</p> <pre>[script] L'erreur système suivante s'est produite : . </pre> <p>Cette erreur est liée à la présence au niveau de l'onglet Membership des rôles Analysis Services, de membres n'existant plus dans Active Directory.</p> <p>Il suffit donc nettoyer vos rôles :)</p> Installer JasperServer sur Linux Debian urn:md5:0216bd919fd11a4ba3897f249d0f36fc 2011-01-15T12:15:00+01:00 2011-01-17T11:46:27+01:00 Jean-Baptiste Heren Décisionnel Business IntelligenceConsultant décisionneldebianJasperlinux <p>JasperServer est la solution open source de BI &amp; reporting la plus aboutie à ce jour. Cette solution comprend l'ensemble des outils nécessaire à la mise en place d'une solution décisionnelle professionnelle.</p> <p>Nous allons voir ici quelles sont les étapes pour installer jasper server manuellement. Ceci est utile en particulier si vous disposez déjà d'un mysql et/ou d'un tomcat installés sur votre machine.</p> <h2>1- Téléchargement du paquet "JasperServer WAR install"</h2> <p>Ce paquet contient le portail Jasper, mysql et l'outil de développement de rapports. rendez-vous chez <a href="http://jasperforge.org/projects/jasperserver" hreflang="en">jasperForge</a> ou directement sur <a href="http://sourceforge.net/projects/jasperserver/files/JasperServer/" hreflang="en">sourceforge</a>.</p> <p>Connectez vous en tant qu'administrateur (root)</p> <pre>[script] # unzip ./jasperserver-ce-3.7.1.bin.zip # cd jasperserver-ce-3.7.1.bin/ # ls apache-ant jasperserver.war samples buildomatic license.txt scripts docs releaseNotes.txt Third-Party-Notices.pdf </pre> <h2>2- Installation du serveur d'application Web</h2> <p>Ici nous installerons Tomcat5, il est également possible de réaliser l'installation avec JBoss, par exemple.</p> <pre>[script] # apt-get install sun-java6-jdk tomcat5.5 tomcat5.5-admin tomcat5.5-webapps </pre> <p>Si l'installation s'est bien déroulée, une connexion du navigateur web à l'adresse http://localhost:8180/ devrait vous afficher ceci&nbsp;: <a href="http://blog.jbheren.com/public/Decisionnel/jasperserver/01_-_tomcat_home.png" title="01_-_tomcat_home.png"><img src="http://blog.jbheren.com/public/Decisionnel/jasperserver/.01_-_tomcat_home_m.jpg" alt="01_-_tomcat_home.png" title="01_-_tomcat_home.png, janv. 2011" /></a></p> <p>Il nous faut maintenant configurer un compte admin pour tomcat</p> <pre>[script] # vim /var/lib/tomcat5.5/conf/tomcat-users.xml </pre> <p>Modifiez le mot de passe par défaut de tomcat et ajoutez les rôles admin &amp; manager.</p> <pre>[xml] &lt;?xml version='1.0' encoding='utf-8'?&gt; &lt;tomcat-users&gt; &lt;role rolename=&quot;tomcat&quot;/&gt; &lt;role rolename=&quot;manager&quot;/&gt; &lt;role rolename=&quot;admin&quot;/&gt; &lt;user username=&quot;tomcat&quot; password=&quot;tomcat&quot; roles=&quot;tomcat,admin,manager&quot;/&gt; &lt;/tomcat-users&gt; </pre> <p>Modifier les paramètres de la VM pour jasperserver. En effet, les paramètres par défaut ne sont pas suffisants...</p> <pre>[script] # vim /usr/share/tomcat5.5/bin/setclasspath.sh </pre> <p>Puis on ajoute la variable JAVA_OPTS, juste aprés le JAVA_ENDORSED_DIRS.</p> <pre>[script] # Set the default -Djava.endorsed.dirs argument JAVA_ENDORSED_DIRS=&quot;$BASEDIR&quot;/common/endorsed # JBH - Parameters for JasperServer to work fine export JAVA_OPTS=&quot;$JAVA_OPTS -Xms128m -Xmx512m -XX:PermSize=32m -XX:MaxPermSize=128m -Xss2m -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled&quot; </pre> <p>Copier le connecteur jdbc mysql depuis le dossier d'installation</p> <pre>[scripts] cp scripts/drivers/mysql/jdbc/mysql-connector-java-5.1.10.jar /usr/share/tomcat5.5/common/lib/ </pre> <p>Redémarrer le server afin de prendre en compte nos modifications</p> <pre>[script] # /etc/init.d/tomcat5.5 restart Stopping Tomcat servlet engine: tomcat5.5. Starting Tomcat servlet engine: tomcat5.5. </pre> <p>Nous pouvons maintenant nous connecter au manager Tomcat en utilisant les login/pass de l'utilisateur tomcat. Pour cela, rendez-vous à l'adresse http://localhost:8180/manager/html <a href="http://blog.jbheren.com/public/Decisionnel/jasperserver/02_-_tomcat_manager.png" title="02_-_tomcat_manager.png"><img src="http://blog.jbheren.com/public/Decisionnel/jasperserver/.02_-_tomcat_manager_m.jpg" alt="02_-_tomcat_manager.png" title="02_-_tomcat_manager.png, janv. 2011" /></a></p> <h2>3- préparation de mysql avec buildomatic</h2> <pre>[script] # cd buildomatic # cp sample_conf/inst-mysql_master.properties default_master.properties # /etc/init.d/tomcat stop # vim default_master.properties </pre> <p>Changes configuration values to&nbsp;:</p> <pre>[script] # application server type (default is tomcat6) appServerType = tomcat5 # Tomcat app server root dir appServerDir = /var/lib/tomcat5.5/ # database type dbType=mysql # database location and connection settings dbHost=localhost dbUsername=root dbPassword=password #set your own password </pre> <p>Nous allons maintenant regénérer les paramètres de buildomatic.</p> <pre>[script] ./js-ant clean-config ./js-ant gen-config </pre> <p>Nous allons maintenant exécuter les tâches de création de la base jasperserver</p> <pre>[script] debianlamp:/home/jb/jasper/jasperserver-ce-3.7.1-bin/buildomatic# ./js-ant create-js-db Buildfile: build.xml create-js-db: [echo] create database, js.dbName = jasperserver [sql] Executing commands [sql] 1 rows affected [sql] 1 of 1 SQL statements executed successfully BUILD SUCCESSFUL Total time: 3 seconds </pre> <p>Les commandes suivantes créent le paramêtrage par défaut (users)</p> <pre>[script] # ./js-ant init-js-db-ce # ./js-ant import-minimal-ce </pre> <p>En option, la création et le chargement des bases de démonstration</p> <pre>[script] # ./js-ant create-sugarcrm-db # ./js-ant create-foodmart-db # ./js-ant load-sugarcrm-db # ./js-ant load-foodmart-db # ./js-ant update-foodmart-db # ./js-ant import-sample-data-ce </pre> <p>Puis le déploiement vers tomcat (le serveur doit être inactif).</p> <pre>[script] # ./js-ant deploy-webapp-ce Buildfile: build.xml init-source-paths: [echo] [echo] Property values (in dev.xml: init-source-paths): [echo] js-path = ${js-base-path} [echo] js-pro-path = ${js-pro-base-path} [echo] repo-path = ${repo-path} [echo] set-ce-webapp-name: [copy] Copying 1 file to /home/jb/jasper/jasperserver-ce-3.7.1-bin/buildomatic/build_conf/default [copy] Copying 1 file to /home/jb/jasper/jasperserver-ce-3.7.1-bin/buildomatic/build_conf/default/webapp/WEB-INF deploy-jdbc-jar: [copy] Copying 1 file to /var/lib/tomcat5.5/common/lib deploy-webapp: [echo] [echo] Property values (in install.xml: deploy-webapp): [echo] jsEdition = ce [echo] warFileDistSourceDir = /home/jb/jasper/jasperserver-ce-3.7.1-bin/buildomatic/../jasperserver.war [echo] warTargetDir = /var/lib/tomcat5.5/webapps/jasperserver [echo] webAppName = jasperserver [echo] webAppNameCE = jasperserver [echo] webAppNamePro = jasperserver-pro [echo] webAppNameSrc = jasperserver [echo] webAppNameDel = jasperserver [echo] warTargetDirDel = /var/lib/tomcat5.5/webapps/jasperserver [echo] [copy] Copying 1013 resources to /var/lib/tomcat5.5/webapps/jasperserver [copy] Copying 4 files to /var/lib/tomcat5.5/webapps/jasperserver [delete] Deleting directory /var/lib/tomcat5.5/work/Catalina/localhost/jasperserver deploy-webapp-ce: BUILD SUCCESSFUL Total time: 25 seconds </pre> <h3>Réglages de Tomcat</h3> <p>Lien symbolique vers la config de jasperserver dans /etc</p> <pre>[script] cd /etc/tomcat5.5/Catalina/localhost ln -s /usr/share/tomcat5.5/webapps/jasperserver/META-INF/context.xml ./jasperserver.xml </pre> <p>Ajout des policies pour jasperserver</p> <pre>[script] # vi /etc/tomcat5.5/policy.d/04webapps.policy </pre> <p>On ajoute la partie suivante dans la section <em>grant codeBase "file:${catalina.home}/bin/tomcat-juli.jar" {</em></p> <pre>[script] permission java.io.FilePermission &quot;/usr/share/tomcat5.5/webapps/jasperserver/WEB-INF/classes/logging.properties&quot;, &quot;read&quot;; // Il faut editer ensuite le fichier ///[script] # vi /etc/tomcat5.5/policy.d/50user.policy </pre> <p>Ajouter la définition suivante&nbsp;:</p> <pre>[script] grant codeBase &quot;file:/usr/share/tomcat5.5/webapps/jasperserver/-&quot; { permission java.security.AllPermission; }; </pre> <p>Mise en place des logs dans le dossier /var/log/tomcat5.5/</p> <pre>[scripts] vim /var/lib/tomcat5.5/webapps/jasperserver/WEB-INF/log4j.properties </pre> <pre>[sript] ... log4j.appender.fileout.File=/var/log/tomcat5.5/jasperserver.log ... log4j.appender.jasperanalysis.File=/var/log/tomcat5.5/jasperanalysis.log </pre> <h2>4- Démarrage de JasperServer</h2> <p>Nous pouvons maintenant démarrer tomcat</p> <pre>[script] # /etc/init.d/tomcat5.5 start </pre> <p>Puis nous connecter à jasperserver à l'adresse http://localhost:8180/jasperserver/, si tout s'est bien passé, vous devriez voir la fenêtre de connexion. <a href="http://blog.jbheren.com/public/Decisionnel/jasperserver/03_-_jasperserver_Home.png" title="03_-_jasperserver_Home.png"><img src="http://blog.jbheren.com/public/Decisionnel/jasperserver/.03_-_jasperserver_Home_m.jpg" alt="03_-_jasperserver_Home.png" title="03_-_jasperserver_Home.png, janv. 2011" /></a></p> <p>les login par défaut de l'administrateur sont jasperadmin/jasperadmin.</p> <h2>Problèmes éventuels</h2> <p>Si l'application n'a pas démarré, vous pouvez consulter, en autres la log jasperserver configurée plus haut:</p> <pre>[script] cat /var/log/tomcat5.5/jasperserver.log </pre> <h3>Problèmes de sécurité dans les logs Cantala.</h3> <p>Sous Debian, TOMCAT peut poser un problème de sécurité, même aprés l'ajout des policies plus haut, il est possible qu'un problème subsiste. Si c'est le cas, vous pouvez désactiver le JSM (Java Security Manager) en modifiant la valeur TOMCAT5_SECURITY dans le fichier suivant&nbsp;:</p> <pre>[script] # vim /etc/default/tomcat5.5 </pre> <p>Modifiez la valeur du TOMCAT5_SECURITY comme suit&nbsp;:</p> <pre>[script] # Use the Java security manager? (yes/no, default: yes) # WARNING: Do not disable the security manager unless you understand # the consequences! # NOTE: java-gcj-compat-dev currently doesn't support a security # manager. TOMCAT5_SECURITY=no </pre> Peoplesoft Component interface HOWTO urn:md5:359cde0d2e5974a67d75845f6035eb22 2011-01-13T06:12:00+01:00 2011-01-21T22:02:48+01:00 Jean-Baptiste Heren Peoplesoft Application designerComponent InterfacePeoplecodepeoplesoft <p>Here is a tutorial explaining how you can create a function containing one Component INterface, and make use of it from any peolplecode.</p> <p>Following example takes the PO Receipt Component to make automatic receipts from a barcode screen.</p> <h2>1- Create a new Component Interface with Application designer</h2> <p>In application Designer, Select File-&gt;New-&gt;Component Interface</p> <p><a href="http://blog.jbheren.com/public/peoplecode/component_interface/02_-_new_component_interface.png" title="02_-_new_component_interface.png"><img src="http://blog.jbheren.com/public/peoplecode/component_interface/.02_-_new_component_interface_m.jpg" alt="02_-_new_component_interface.png" title="02_-_new_component_interface.png, janv. 2011" /></a></p> <p>Select The Component you want to access to</p> <p><a href="http://blog.jbheren.com/public/peoplecode/component_interface/03_-_select_component.png" title="03_-_select_component.png"><img src="http://blog.jbheren.com/public/peoplecode/component_interface/.03_-_select_component_m.jpg" alt="03_-_select_component.png" title="03_-_select_component.png, janv. 2011" /></a></p> <p>Answer YES to following question</p> <p><a href="http://blog.jbheren.com/public/peoplecode/component_interface/04_-_set_default_properties.png" title="04_-_set_default_properties.png"><img src="http://blog.jbheren.com/public/peoplecode/component_interface/.04_-_set_default_properties_m.jpg" alt="04_-_set_default_properties.png" title="04_-_set_default_properties.png, janv. 2011" /></a></p> <p>Now your componet has been created, you can just save IT</p> <p><a href="http://blog.jbheren.com/public/peoplecode/component_interface/05_-_component_is_created.png" title="05_-_component_is_created.png"><img src="http://blog.jbheren.com/public/peoplecode/component_interface/.05_-_component_is_created_m.jpg" alt="05_-_component_is_created.png" title="05_-_component_is_created.png, janv. 2011" /></a> <a href="http://blog.jbheren.com/public/peoplecode/component_interface/06_-_component_interface_save_as.png" title="06_-_component_interface_save_as.png"><img src="http://blog.jbheren.com/public/peoplecode/component_interface/.06_-_component_interface_save_as_m.jpg" alt="06_-_component_interface_save_as.png" title="06_-_component_interface_save_as.png, janv. 2011" /></a></p> <h2>2- Write Peoplecode for you CI</h2> <h3>2.1- Drag and drop the Component Interface to the Peoplecode text window. Il will create a template to adapt:</h3> <pre></pre> <pre>[vb] Local File &amp;fileLog; Local ApiObject &amp;oSession, &amp;oMYCINAMEPoRecv; Function errorHandler() Local ApiObject &amp;oPSMessageCollection, &amp;oPSMessage; Local number &amp;i; Local String &amp;sErrMsgSetNum, &amp;sErrMsgNum, &amp;sErrMsgText, &amp;sErrType; &amp;oPSMessageCollection = &amp;oSession.PSMessages; For &amp;i = 1 To &amp;oPSMessageCollection.Count &amp;oPSMessage = &amp;oPSMessageCollection.Item(&amp;i); &amp;sErrMsgSetNum = &amp;oPSMessage.MessageSetNumber; &amp;sErrMsgNum = &amp;oPSMessage.MessageNumber; &amp;sErrMsgText = &amp;oPSMessage.Text; &amp;fileLog.WriteLine(&amp;sErrType | &quot; (&quot; | &amp;sErrMsgSetNum | &quot;,&quot; | &amp;sErrMsgNum | &quot;) - &quot; | &amp;sErrMsgText); End-For; rem ***** Delete the Messages from the collection *****; &amp;oPSMessageCollection.DeleteAll(); End-Function; try rem ***** Set the Log File *****; &amp;fileLog = GetFile(&quot;C:\temp\MY_CI_NAME.log&quot;, &quot;w&quot;, &quot;a&quot;, %FilePath_Absolute); &amp;fileLog.WriteLine(&quot;Begin&quot;); rem ***** Get current PeopleSoft Session *****; &amp;oSession = %Session; rem ***** Set the PeopleSoft Session Error Message Mode *****; rem ***** 0 - None *****; rem ***** 1 - PSMessage Collection only (default) *****; rem ***** 2 - Message Box only *****; rem ***** 3 - Both collection and message box *****; &amp;oSession.PSMessagesMode = 1; rem ***** Get the Component Interface *****; &amp;oMYCINAMEPoRecv = &amp;oSession.GetCompIntfc(CompIntfc.MY_CI_NAME_RECV); If &amp;oMYCINAMEPoRecv = Null Then errorHandler(); throw CreateException(0, 0, &quot;GetCompIntfc failed&quot;); End-If; rem ***** Set the Component Interface Mode *****; &amp;oMYCINAMEPoRecv.InteractiveMode = False; &amp;oMYCINAMEPoRecv.GetHistoryItems = True; &amp;oMYCINAMEPoRecv.EditHistoryItems = False; rem ***** Set Component Interface Get/Create Keys *****; rem ***** Execute Get *****; If Not &amp;oMYCINAMEPoRecv.Get() Then rem ***** No rows exist for the specified keys.*****; errorHandler(); throw CreateException(0, 0, &quot;Get failed&quot;); End-If; rem ***** Begin: Get/Set Component Interface Properties *****; rem ***** Get/Set Level 0 Field Properties *****; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.INV_LOT_ID = &quot; | &amp;oMYCINAMEPoRecv.INV_LOT_ID); rem &amp;oMYCINAMEPoRecv.INV_LOT_ID = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.INV_ITEM_ID = &quot; | &amp;oMYCINAMEPoRecv.INV_ITEM_ID); rem &amp;oMYCINAMEPoRecv.INV_ITEM_ID = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.SERIAL_ID = &quot; | &amp;oMYCINAMEPoRecv.SERIAL_ID); rem &amp;oMYCINAMEPoRecv.SERIAL_ID = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.STORAGE_AREA = &quot; | &amp;oMYCINAMEPoRecv.STORAGE_AREA); rem &amp;oMYCINAMEPoRecv.STORAGE_AREA = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.STOR_LEVEL_1 = &quot; | &amp;oMYCINAMEPoRecv.STOR_LEVEL_1); rem &amp;oMYCINAMEPoRecv.STOR_LEVEL_1 = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.STOR_LEVEL_2 = &quot; | &amp;oMYCINAMEPoRecv.STOR_LEVEL_2); rem &amp;oMYCINAMEPoRecv.STOR_LEVEL_2 = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.STOR_LEVEL_3 = &quot; | &amp;oMYCINAMEPoRecv.STOR_LEVEL_3); rem &amp;oMYCINAMEPoRecv.STOR_LEVEL_3 = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.STOR_LEVEL_4 = &quot; | &amp;oMYCINAMEPoRecv.STOR_LEVEL_4); rem &amp;oMYCINAMEPoRecv.STOR_LEVEL_4 = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.CONTAINER_ID = &quot; | &amp;oMYCINAMEPoRecv.CONTAINER_ID); rem &amp;oMYCINAMEPoRecv.CONTAINER_ID = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.UNIT_OF_MEASURE = &quot; | &amp;oMYCINAMEPoRecv.UNIT_OF_MEASURE); rem &amp;oMYCINAMEPoRecv.UNIT_OF_MEASURE = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.RECEIVER_ID = &quot; | &amp;oMYCINAMEPoRecv.RECEIVER_ID); rem &amp;oMYCINAMEPoRecv.RECEIVER_ID = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.QTY = &quot; | &amp;oMYCINAMEPoRecv.QTY); rem &amp;oMYCINAMEPoRecv.QTY = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.SCHED_NBR = &quot; | &amp;oMYCINAMEPoRecv.SCHED_NBR); rem &amp;oMYCINAMEPoRecv.SCHED_NBR = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.SETID = &quot; | &amp;oMYCINAMEPoRecv.SETID); rem &amp;oMYCINAMEPoRecv.SETID = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.SHIPTO_ID = &quot; | &amp;oMYCINAMEPoRecv.SHIPTO_ID); rem &amp;oMYCINAMEPoRecv.SHIPTO_ID = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.VENDOR_ID = &quot; | &amp;oMYCINAMEPoRecv.VENDOR_ID); rem &amp;oMYCINAMEPoRecv.VENDOR_ID = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.SHIPMENT_NO = &quot; | &amp;oMYCINAMEPoRecv.SHIPMENT_NO); rem &amp;oMYCINAMEPoRecv.SHIPMENT_NO = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.CARRIER_ID = &quot; | &amp;oMYCINAMEPoRecv.CARRIER_ID); rem &amp;oMYCINAMEPoRecv.CARRIER_ID = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.BILL_OF_LADING = &quot; | &amp;oMYCINAMEPoRecv.BILL_OF_LADING); rem &amp;oMYCINAMEPoRecv.BILL_OF_LADING = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.BUSINESS_UNIT_PO = &quot; | &amp;oMYCINAMEPoRecv.BUSINESS_UNIT_PO); rem &amp;oMYCINAMEPoRecv.BUSINESS_UNIT_PO = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.PO_ID = &quot; | &amp;oMYCINAMEPoRecv.PO_ID); rem &amp;oMYCINAMEPoRecv.PO_ID = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.LINE_NBR = &quot; | &amp;oMYCINAMEPoRecv.LINE_NBR); rem &amp;oMYCINAMEPoRecv.LINE_NBR = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.BUSINESS_UNIT_IN = &quot; | &amp;oMYCINAMEPoRecv.BUSINESS_UNIT_IN); rem &amp;oMYCINAMEPoRecv.BUSINESS_UNIT_IN = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.VENDOR_LOT_ID = &quot; | &amp;oMYCINAMEPoRecv.VENDOR_LOT_ID); rem &amp;oMYCINAMEPoRecv.VENDOR_LOT_ID = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.TAG_NUMBER = &quot; | &amp;oMYCINAMEPoRecv.TAG_NUMBER); rem &amp;oMYCINAMEPoRecv.TAG_NUMBER = [*]; &amp;fileLog.WriteLine(&quot;&amp;oMYCINAMEPoRecv.TRANSACTION_CODE = &quot; | &amp;oMYCINAMEPoRecv.TRANSACTION_CODE); rem &amp;oMYCINAMEPoRecv.TRANSACTION_CODE = [*]; rem ***** End: Get/Set Component Interface Properties *****; rem ***** Execute Save *****; rem If Not &amp;oMYCINAMEPoRecv.Save() Then; rem errorHandler(); rem throw CreateException(0, 0, &quot;Save failed&quot;); rem End-If; rem ***** Execute Cancel *****; rem If Not &amp;oMYCINAMEPoRecv.Cancel() Then; rem errorHandler(); rem throw CreateException(0, 0, &quot;Cancel failed&quot;); rem End-If; catch exception &amp;ex rem Handle the exception; &amp;fileLog.WriteLine(&amp;ex.ToString()); end-try; &amp;fileLog.WriteLine(&quot;End&quot;); &amp;fileLog.Close(); </pre> <h3>2.2- Make changes so that you can include the CI code in a single function</h3> <p>This way, your CI will be easyer to use from any application, with a single function call.</p> <h4>Change the errorHandler function to get File &amp; Session as a parameter:</h4> <pre>[vb] Function errorHandler(&amp;fileLog As File, &amp;oSession As ApiObject) Local ApiObject &amp;oPSMessageCollection, &amp;oPSMessage; Local number &amp;i; Local string &amp;sErrMsgSetNum, &amp;sErrMsgNum, &amp;sErrMsgText, &amp;sErrType; &amp;oPSMessageCollection = &amp;oSession.PSMessages; For &amp;i = 1 To &amp;oPSMessageCollection.Count &amp;oPSMessage = &amp;oPSMessageCollection.Item(&amp;i); &amp;sErrMsgSetNum = &amp;oPSMessage.MessageSetNumber; &amp;sErrMsgNum = &amp;oPSMessage.MessageNumber; &amp;sErrMsgText = &amp;oPSMessage.Text; &amp;fileLog.WriteLine(&amp;sErrType | &quot; (&quot; | &amp;sErrMsgSetNum | &quot;,&quot; | &amp;sErrMsgNum | &quot;) - &quot; | &amp;sErrMsgText); End-For; rem ***** Delete the Messages from the collection *****; &amp;oPSMessageCollection.DeleteAll(); End-Function; </pre> <h4>Create Functions containing Your CI operations, so that it will be easier to integrate in any peoplecode program.</h4> <pre>[vb] // Function returns a rowset from MY_BCODE_TBL corresponding to &amp;barcode parameter Function getBarcodeRecord(&amp;barcode As string) Returns Record Local Rowset &amp;RwsBarcode; Local Record &amp;REcBarcode; &amp;RwsBarcode = CreateRowset(Record.MY_BCODE_TBL); &amp;RwsBarcode.Fill(&quot;WHERE RECV_CARD_ID = :1&quot;, &amp;barcode); &amp;REcBarcode = CreateRecord(Record.MY_BCODE_TBL); &amp;REcBarcode = &amp;RwsBarcode(1).GetRecord(1); Return &amp;REcBarcode; End-Function; // This Function is scheduling a job Function RunJobRecv(&amp;barcode As string) Returns boolean Local boolean &amp;success = False; Local ProcessRequest &amp;prcsrqst; Local JavaObject &amp;Obj; Local Record &amp;RecRECVLOAD; Local Record &amp;RecRECVPUSH; Local Record &amp;RecINPSSTGE; // Select data using barcode ID - start; Local Record &amp;REcBarcode; &amp;REcBarcode = getBarcodeRecord(&amp;barcode); // Select data using barcode ID - end; &amp;jobname = &quot;MYRECVJOB&quot;; // Create Data In Needed Run Control Parameters; // 01 - RECVLOAD; &amp;RecRECVLOAD = CreateRecord(Record.RUN_CNTL_RECVLD); &amp;RecRECVLOAD.OPRID.Value = %UserId; &amp;RecRECVLOAD.RUN_CNTL_ID.Value = &amp;jobname; &amp;RecRECVLOAD.RECVLOAD_OPT.Value = &quot;2&quot;; &amp;RecRECVLOAD.BUSINESS_UNIT.Value = &amp;REcBarcode.BUSINESS_UNIT_IN.Value; &amp;RecRECVLOAD.WHERE_CLAUSE.Value = &quot;BUSINESS_UNIT = '&quot; | &amp;RecRECVLOAD.BUSINESS_UNIT.Value | &quot;'&quot;; If Not &amp;RecRECVLOAD.Insert() Then &amp;RecRECVLOAD.Update(); End-If; // 02 - RUN_PO_RECEIPT; &amp;RecRECVPUSH = CreateRecord(Record.RECV_RUN_CNTL); &amp;RecRECVPUSH.OPRID.Value = %UserId; &amp;RecRECVPUSH.RUN_CNTL_ID.Value = &amp;jobname; &amp;RecRECVPUSH.RECEIVER_ID.Value = &quot;&quot;; &amp;RecRECVPUSH.BUSINESS_UNIT.Value = &amp;REcBarcode.BUSINESS_UNIT_IN.Value; If Not &amp;RecRECVPUSH.Insert() Then &amp;RecRECVPUSH.Update(); End-If; REM Schedule the Job; &amp;prcsrqst = CreateProcessRequest(&quot;PSJob&quot;, &amp;jobname); &amp;prcsrqst.RunControlID = &amp;jobname; &amp;prcsrqst.JobName = &amp;jobname; &amp;prcsrqst.Schedule(); If &amp;prcsrqst.Status = 0 Then /* Schedule succeeded. */ &amp;success = True; Else /* Process (job) not scheduled, do error processing */ &amp;success = False; End-If; /* &amp;Obj = CreateJavaObject(&quot;java.lang.Thread&quot;); &amp;Obj.start(); &amp;RunStatus = &quot;0&quot;; While &amp;RunStatus &lt;&gt; &quot;9&quot; And &amp;RunStatus &lt;&gt; &quot;3&quot; And &amp;RunStatus &lt;&gt; &quot;1&quot; And &amp;RunStatus &lt;&gt; &quot;10&quot; REM Directly use the Java sleep() Method for 5 seconds; &amp;Obj.sleep(5000); SQLExec(&quot;SELECT RUNSTATUS FROM PSPRCSRQST WHERE PRCSINSTANCE = :1&quot;, &amp;prcsrqst.ProcessInstance, &amp;RunStatus); REM MessageBox(0, &quot;&quot;, 0, 0, &quot;Sleep(), Runstatus = %1&quot;, &amp;RunStatus); End-While; &amp;Obj.stop(); rem WriteLog(&quot;Process MYRECVJOB is Finished&quot;); If &amp;prcsrqst.Status = 10 Or &amp;prcsrqst.Status = 3 Then REM Process your errors; &amp;success = False; Else REM Process your success; &amp;success = True; End-If; */ Return &amp;success; End-Function; // Adds data to a log table Function LogBarcode(&amp;barcode As string, &amp;qty As number, &amp;transaction_code As string) Returns boolean Local Record &amp;RecLog; &amp;RecLog = CreateRecord(Record.PH_RECV_BCD_LOG); &amp;RecLog.RECV_CARD_ID.Value = &amp;barcode; &amp;RecLog.QTY.Value = &amp;qty; &amp;RecLog.TRANSACTION_CODE.Value = &amp;transaction_code; &amp;RecLog.DT_TIMESTAMP.Value = %Datetime; &amp;RecLog.OPRID.Value = %UserId; Return &amp;RecLog.Insert(); End-Function; // ErrorHandler Function Function errorHandler(&amp;fileLog As File, &amp;oSession As ApiObject) Local ApiObject &amp;oPSMessageCollection, &amp;oPSMessage; Local number &amp;i; Local string &amp;sErrMsgSetNum, &amp;sErrMsgNum, &amp;sErrMsgText, &amp;sErrType; &amp;oPSMessageCollection = &amp;oSession.PSMessages; For &amp;i = 1 To &amp;oPSMessageCollection.Count &amp;oPSMessage = &amp;oPSMessageCollection.Item(&amp;i); &amp;sErrMsgSetNum = &amp;oPSMessage.MessageSetNumber; &amp;sErrMsgNum = &amp;oPSMessage.MessageNumber; &amp;sErrMsgText = &amp;oPSMessage.Text; &amp;fileLog.WriteLine(&amp;sErrType | &quot; (&quot; | &amp;sErrMsgSetNum | &quot;,&quot; | &amp;sErrMsgNum | &quot;) - &quot; | &amp;sErrMsgText); End-For; rem ***** Delete the Messages from the collection *****; &amp;oPSMessageCollection.DeleteAll(); End-Function; /* Jean-Baptiste HEREN This function Gets Barcode and Qty from the barcode entry screen- Transaction 103; - Then it Uses a Component Interface to simulate the manual entry on; The Data Exchange &gt; Create Transactions &gt; Receiving &gt; Purchasing Receiving;*/ Function WriteReceipt(&amp;barcode As string, &amp;qty As number) Returns boolean Local File &amp;fileLog; Local ApiObject &amp;oSession, &amp;oMYCINAMEPoRecv; // Jean-Baptiste HEREN - Select data using barcode ID - start; Local Record &amp;REcBarcode; &amp;REcBarcode = getBarcodeRecord(&amp;barcode); // Jean-Baptiste HEREN - Select data using barcode ID - end; try rem ***** Set the Log File *****; If %UserId = &quot;jean-baptiste.heren&quot; Then &amp;fileLog = GetFile(&quot;\\MyMachine\temp\CI\MY_CI_NAME_RECV_WriteReceipt.log&quot;, &quot;w&quot;, &quot;a&quot;, %FilePath_Absolute); Else &amp;fileLog = GetFile(&quot;MY_CI_NAME_RECV.log&quot;, &quot;w&quot;, &quot;a&quot;, %FilePath_Relative); End-If; &amp;fileLog.WriteLine(&quot;Begin&quot;); rem ***** Get current PeopleSoft Session *****; &amp;oSession = %Session; rem ***** Set the PeopleSoft Session Error Message Mode *****; rem ***** 0 - None *****; rem ***** 1 - PSMessage Collection only (default) *****; rem ***** 2 - Message Box only *****; rem ***** 3 - Both collection and message box *****; &amp;oSession.PSMessagesMode = 1; rem ***** Get the Component Interface *****; &amp;oMYCINAMEPoRecv = &amp;oSession.GetCompIntfc(CompIntfc.MY_CI_NAME_RECV); If &amp;oMYCINAMEPoRecv = Null Then errorHandler(&amp;fileLog, &amp;oSession); throw CreateException(0, 0, &quot;GetCompIntfc failed&quot;); End-If; rem ***** Set the Component Interface Mode *****; &amp;oMYCINAMEPoRecv.InteractiveMode = True; &amp;oMYCINAMEPoRecv.GetHistoryItems = True; &amp;oMYCINAMEPoRecv.EditHistoryItems = False; rem ***** Set Component Interface Get/Create Keys *****; rem ***** Execute Get *****; If Not &amp;oMYCINAMEPoRecv.Get() Then rem ***** No rows exist for the specified keys.*****; errorHandler(&amp;fileLog, &amp;oSession); throw CreateException(0, 0, &quot;Get failed&quot;); End-If; rem ***** Begin: Get/Set Component Interface Properties *****; rem ***** Get/Set Level 0 Field Properties *****; // Jean-Baptiste HEREN - Write the session related to creation of a new reception line; &amp;transaction_code = &quot;0103&quot;; &amp;oMYCINAMEPoRecv.TRANSACTION_CODE = &amp;transaction_code; // Jean-Baptiste HEREN - Fill with the barcode ID data; &amp;oMYCINAMEPoRecv.SETID = &amp;REcBarcode.SETID.Value; &amp;oMYCINAMEPoRecv.SHIPTO_ID = &amp;REcBarcode.SHIPTO_ID.Value; &amp;oMYCINAMEPoRecv.VENDOR_ID = &amp;REcBarcode.VENDOR_ID.Value; &amp;oMYCINAMEPoRecv.BUSINESS_UNIT_IN = &amp;REcBarcode.BUSINESS_UNIT_IN.Value; &amp;oMYCINAMEPoRecv.CARRIER_ID = &amp;REcBarcode.CARRIER_ID.Value; &amp;oMYCINAMEPoRecv.BILL_OF_LADING = &amp;REcBarcode.BILL_OF_LADING.Value; &amp;oMYCINAMEPoRecv.BUSINESS_UNIT_PO = &amp;REcBarcode.BUSINESS_UNIT_PO.Value; &amp;oMYCINAMEPoRecv.PO_ID = &amp;REcBarcode.PO_ID.Value; &amp;oMYCINAMEPoRecv.LINE_NBR = &amp;REcBarcode.LINE_NBR.Value; &amp;oMYCINAMEPoRecv.UNIT_OF_MEASURE = &amp;REcBarcode.UNIT_OF_MEASURE.Value; REM Still use Quantyty from Barcode screen; &amp;oMYCINAMEPoRecv.QTY = &amp;qty; rem ***** End: Get/Set Component Interface Properties *****; rem ***** Execute Save *****; If Not &amp;oMYCINAMEPoRecv.Save() Then; errorHandler(&amp;fileLog, &amp;oSession); &amp;success = False; throw CreateException(0, 0, &quot;Save failed&quot;); Else &amp;success = True; If Not LogBarcode(&amp;barcode, &amp;qty, &amp;transaction_code) Then &amp;fileLog.WriteLine(&quot;LogBarcode Failed&quot;); End-If; End-If; rem ***** Execute Cancel *****; rem If Not &amp;oMYCINAMEPoRecv.Cancel() Then; rem errorHandler(&amp;fileLog, &amp;oSession); rem throw CreateException(0, 0, &quot;Cancel failed&quot;); rem End-If; catch Exception &amp;ex rem Handle the exception; &amp;fileLog.WriteLine(&amp;ex.ToString()); end-try; &amp;fileLog.WriteLine(&quot;End&quot;); &amp;fileLog.Close(); Return &amp;success; End-Function; /* Jean-Baptiste HEREN This function Closes the Receipt session - Transaction 105; - It Uses a Component Interface to simulate the manual entry on; The Data Exchange &gt; Create Transactions &gt; Receiving &gt; Purchasing Receiving;*/ Function CloseReceipt(&amp;barcode) Returns boolean Local File &amp;fileLog; Local ApiObject &amp;oSession, &amp;oMYCINAMEPoRecv; // Jean-Baptiste HEREN - Select data using barcode ID - start; Local Record &amp;REcBarcode; &amp;REcBarcode = getBarcodeRecord(&amp;barcode); // Jean-Baptiste HEREN - Select data using barcode ID - end; try rem ***** Set the Log File *****; If %UserId = &quot;jean-baptiste.heren&quot; Then &amp;fileLog = GetFile(&quot;\\MyMachine\temp\CI\MY_CI_NAME_RECV_CloseReceipt.log&quot;, &quot;w&quot;, &quot;a&quot;, %FilePath_Absolute); Else &amp;fileLog = GetFile(&quot;MY_CI_NAME_RECV.log&quot;, &quot;w&quot;, &quot;a&quot;, %FilePath_Relative); End-If; &amp;fileLog.WriteLine(&quot;Begin&quot;); rem ***** Get current PeopleSoft Session *****; &amp;oSession = %Session; rem ***** Set the PeopleSoft Session Error Message Mode *****; rem ***** 0 - None *****; rem ***** 1 - PSMessage Collection only (default) *****; rem ***** 2 - Message Box only *****; rem ***** 3 - Both collection and message box *****; &amp;oSession.PSMessagesMode = 1; rem ***** Get the Component Interface *****; &amp;oMYCINAMEPoRecv = &amp;oSession.GetCompIntfc(CompIntfc.MY_CI_NAME_RECV); If &amp;oMYCINAMEPoRecv = Null Then errorHandler(&amp;fileLog, &amp;oSession); throw CreateException(0, 0, &quot;GetCompIntfc failed&quot;); End-If; rem ***** Set the Component Interface Mode *****; &amp;oMYCINAMEPoRecv.InteractiveMode = True; &amp;oMYCINAMEPoRecv.GetHistoryItems = True; &amp;oMYCINAMEPoRecv.EditHistoryItems = False; rem ***** Set Component Interface Get/Create Keys *****; rem ***** Execute Get *****; If Not &amp;oMYCINAMEPoRecv.Get() Then rem ***** No rows exist for the specified keys.*****; errorHandler(&amp;fileLog, &amp;oSession); throw CreateException(0, 0, &quot;Get failed&quot;); End-If; rem ***** Begin: Get/Set Component Interface Properties *****; rem ***** Get/Set Level 0 Field Properties *****; // Jean-Baptiste HEREN - Write the session related to creation of a new reception line; &amp;qty = 0; &amp;transaction_code = &quot;0105&quot;; &amp;oMYCINAMEPoRecv.TRANSACTION_CODE = &amp;transaction_code; REM JBH - Fill with the barcode ID data.value; &amp;oMYCINAMEPoRecv.SETID = &amp;REcBarcode.SETID.Value; &amp;oMYCINAMEPoRecv.SHIPTO_ID = &amp;REcBarcode.SHIPTO_ID.Value; REM &amp;oMYCINAMEPoRecv.VENDOR_ID = &amp;REcBarcode.VENDOR_ID.Value; REM &amp;oMYCINAMEPoRecv.BUSINESS_UNIT_IN = &amp;REcBarcode.BUSINESS_UNIT_IN.value; &amp;oMYCINAMEPoRecv.CARRIER_ID = &amp;REcBarcode.CARRIER_ID.Value; &amp;oMYCINAMEPoRecv.BILL_OF_LADING = &amp;REcBarcode.BILL_OF_LADING.Value; REM &amp;oMYCINAMEPoRecv.BUSINESS_UNIT_PO = &amp;REcBarcode.BUSINESS_UNIT_PO.value; REM &amp;oMYCINAMEPoRecv.PO_ID = &amp;REcBarcode.PO_ID.value; REM &amp;oMYCINAMEPoRecv.LINE_NBR = &amp;REcBarcode.LINE_NBR.value; REM &amp;oMYCINAMEPoRecv.UNIT_OF_MEASURE = &amp;REcBarcode.UNIT_OF_MEASURE.value; REM Still use Quantyty from Barcode screen; REM &amp;oMYCINAMEPoRecv.QTY = &amp;qty; rem ***** End: Get/Set Component Interface Properties *****; rem ***** Execute Save *****; // Jean-Baptiste HEREN - Usually, you want you CI to save your component at end, so uncomment the SAVE part If Not &amp;oMYCINAMEPoRecv.Save() Then; errorHandler(&amp;fileLog, &amp;oSession); &amp;success = False; throw CreateException(0, 0, &quot;Save failed&quot;); Else &amp;success = True; If Not LogBarcode(&amp;barcode, &amp;qty, &amp;transaction_code) Then &amp;fileLog.WriteLine(&quot;LogBarcode Failed&quot;); End-If; End-If; rem ***** Execute Cancel *****; rem If Not &amp;oMYCINAMEPoRecv.Cancel() Then; rem errorHandler(&amp;fileLog, &amp;oSession); rem throw CreateException(0, 0, &quot;Cancel failed&quot;); rem End-If; catch Exception &amp;ex rem Handle the exception; &amp;fileLog.WriteLine(&amp;ex.ToString()); end-try; &amp;fileLog.WriteLine(&quot;End&quot;); &amp;fileLog.Close(); Return &amp;success; End-Function; </pre> <h2>3- Write a program witch is using your CI</h2> <p>This kind of code is usually called from a Fast entry screen or External Interface</p> <pre>[vb] // JBH - Declare Custom Functions Using Component Interface; Declare Function WriteReceipt PeopleCode MY_RECV_TABLE.RECV_CARD_ID FieldFormula; Declare Function CloseReceipt PeopleCode MY_RECV_TABLE.RECV_CARD_ID FieldFormula; REM Run the Component Interface; If All(MY_RECV_TABLE.RECV_CARD_ID.Value) And All(MY_RECV_TABLE.QTY.Value) Then MY_RECV_TABLE.RECV_CARD_ID.Value = RTrim(MY_RECV_TABLE.RECV_CARD_ID.Value); REM Check That This Barcode has not already been used; SQLExec(&quot;SELECT 1 FROM PS_PH_RECV_BCD_LOG WHERE RECV_CARD_ID = :1&quot;, MY_RECV_TABLE.RECV_CARD_ID.Value, &amp;result); If &amp;result &lt;&gt; 1 Then // Here we call our Component Interface If Not WriteReceipt(MY_RECV_TABLE.RECV_CARD_ID.Value, MY_RECV_TABLE.QTY.Value) Then WinMessage(&quot;Reception Failed!&quot;); Else SetCursorPos(%Page, MY_RECV_TABLE.RECV_CARD_ID, CurrentRowNumber()); REM Save The succesfully recorded barcode; MY_RECV_TABLE.RECV_CARD_ID_OK.Value = MY_RECV_TABLE.RECV_CARD_ID.Value; REM Clean Screen; MY_RECV_TABLE.RECV_CARD_ID.Value = &quot;&quot;; MY_RECV_TABLE.QTY.Value = 0; End-If; Else WinMessage(&quot;Card ID has already been scanned !&quot;); SetCursorPos(%Page, MY_RECV_TABLE.RECV_CARD_ID, CurrentRowNumber()); REM Clean Screen; MY_RECV_TABLE.RECV_CARD_ID.Value = &quot;&quot;; MY_RECV_TABLE.QTY.Value = 0; End-If; End-If; </pre> désactiver le timeout avec sfGUardSecurityUser dans Symfony urn:md5:9f869fc2f968652dc9f1b51dd751fcb7 2011-01-12T21:55:00+01:00 2011-01-13T10:11:41+01:00 Jean-Baptiste Heren développement Web <p>Voici comment désactiver le timeout des sessions Symony, utilisant une classe myUser dérivée de sfGuardSecurityUser.</p> <h2>Modifier la durée maximale de session dans php.ini</h2> <pre>[ini] session.gc_maxlifetime = 86400 </pre> <h2>Modifier la classe apps/votre_app/lib/myUser.class.php</h2> <pre>[php] class myUser extends sfGuardSecurityUser { // on surcharge le constructeur afin de fixer la valeur du timeout. public function initialize(sfEventDispatcher $dispatcher, sfStorage $storage, $options = array()) { // timeout est fixé à false. On peut également fixer une valeur en secondes. $options['timeout'] = false; parent::initialize($dispatcher, $storage, $options); } } </pre> <p>Merci à Blue Horn pour son <a href="http://bluehorn.co.nz/2010/03/26/how-to-make-symfony-session-to-never-timeout/" hreflang="en">précieux post</a>, ainsi que le <a href="https://groups.google.com/group/symfony-fr/browse_thread/thread/ff3809d1cb655ff4?hl=fr" hreflang="fr">groupe de discussion</a> Symfony :)</p> Graphic box en SQR urn:md5:c99134ae31e14de57e650cce8e3b2be0 2010-12-07T11:31:00+01:00 2011-01-06T15:14:58+01:00 Jean-Baptiste Heren Peoplesoft peoplesoftsqr <h2>Voici comment imprimer une boite (un cadre) avec SQR Report.</h2> <pre> !* Graphic Box !* GRAPHIC (a, b, c) BOX d e f !* a = line !* b = colonn !* c = width (largeur) !* d = high (hauteur) !* e = Thickness (épaisseur du trait) !* f = Background opacity (Opacité du fond) (Grisé) </pre> <p>Exemple de boite avec Cadre &amp; Grisée</p> <pre>[sql] graphic (#num_ligne,#col_gauche,#largeur_cellule) box #hauteur_cellule #epaisseur_trait #opacite_fond </pre> Cognos Report Studio : position d'un membre dans une hierarchie urn:md5:f35f2a485b57edac5673c6e8a6f74927 2010-11-03T18:02:00+01:00 2011-12-02T16:04:58+01:00 Jean-Baptiste Heren Décisionnel Cognoscognos functionReport Studio <p>L'expression suivante renvoie niveau de profondeur du membre spécifié dans une hiérarchie.</p> <pre>[script] ordinal (level(currentMember([My_Package].[My_Dimension].[My_Hierarchy]))) </pre>