Blog Pro de Jean-Baptiste HERENNotes d'un consultant Freelance en Informatique2015-11-03T21:34:19+01:00JB HERENurn:md5:e39389b5ec134d99645112fce3d957dfDotclearActiver le mode modem sur Iphone 3G avec free mobile sous OSXurn:md5:d74fff12219c3bf1c82061c6a4d099662012-02-23T21:51:00+01:002012-05-11T14:38:46+02:00Jean-Baptiste HerenVeille technoiPhoneMacOSX <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 :</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 !</p>Cognos Report : Display a different measure in row for the aggregated columnurn:md5:6ccc97632f467975c6b7413cdfb5c47f2012-01-30T19:43:00+01:002012-01-30T20:34:34+01:00Jean-Baptiste HerenDécisionnelBusiness 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]) > 1) then(1) else (0)
</pre>
<p><strong>Conditional</strong> Expression:</p>
<pre>[script]
if(count(distinct [year]) > 1) then([PackName].[Measures].[M1]) else ([PackName].[Measures].[M2])
</pre>Matériel Open Source & Introduction à RepRapurn:md5:68dd2f717faebce6cb7e494aac33d6c42011-12-02T13:58:00+01:002012-02-24T16:48:38+01:00Jean-Baptiste HerenDIYDIYfablabopen 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 ?
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 :</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 !</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 :</p>
<ul>
<li><a href="http://www.thingiverse.com/" hreflang="en">thingiverse.com</a> : 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> : 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&item=230700566122&ssPageName=STRK:MEWAX:IT&_trksid=p3984.m1423.l2649#ht_550wt_1413" hreflang="fr" title="Kit Reprap printed parts">ebay.fr</a> : 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 : <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 lineurn:md5:095889337a165f98a9556881fb9ade072011-06-27T20:55:00+02:002011-12-02T11:07:36+01:00Jean-Baptiste HerenVeille technobatchChilkat FTPcommand lineftpvbswindowswinSCP<p>Here is a little trick we used on a recent project.</p>
<p>We needed to automatize :</p>
<ol>
<li>(local <-- remote) download files from an ftp server specified folder</li>
<li>(remote --> 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 & 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 < 4 ) Then
WScript.Echo( vbCrLf &" usage: cscript move.vbs source_local_full_path local_ftp_path remote_ftp_path move_to_path connection_name")
WScript.Echo( vbCrLf &" example: " &vbCrLf &" cscript move.vbs D:\FTPROOT\IN\LOCAL IN/FOO OUT/FOO DONE MYACCOUNT")
WScript.Echo( vbCrLf &" " &vbCrLf &" 1 - Gets files from OUT/FOO -> IN/FOO using the recorded MYACCOUNT WINSCP connection")
WScript.Echo( vbCrLf &" " &vbCrLf &" 2 - moves files names found in D:\FTPROOT\IN\LOCAL, on remote from OUT/FOO -> OUT/FOO/DONE")
WScript.Quit
End If
' -------------------------------------------
'| MAIN |
' -------------------------------------------
' Set Winscp com path
winscp = "C:\Program Files\WinSCP\winscp.com"
commandTxt = "" ' Empty current command
Set fso = CreateObject("Scripting.FileSystemObject")
' 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 = "" Then
Wscript.Echo "No Folder parameter was passed"
Wscript.Quit
Else
Wscript.Echo "Runing For " & localPath & " , " & localFolder & " , " & remoteFolder & " , " & moveSubFolder & " on connection " & connexionName
End If
' Open ftp command
Set oShell = CreateObject("wscript.shell")
'Set oExec = oShell.Exec("ftpgenerix.bat")
Set oExec = oShell.Exec(winscp)
' Build the list of Commands to be ran by FTP command.
' login
oExec.StdIn.Writeline "option batch abort"
WScript.Sleep 100
oExec.StdIn.Writeline "open " & connexionName
WScript.Sleep 100
' 00 - Set Current Folders
oExec.StdIn.Writeline("cd " & remoteFolder)
WScript.Sleep 100
oExec.StdIn.Writeline("lcd " & localFolder)
WScript.Sleep 100
' 01 - DOWNLOAD
oExec.StdIn.Writeline("get *.*")
Wscript.Echo "Getting All files from " & remoteFolder & " to " & 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 = "rename " & file.Name & " " & moveSubFolder & "/" & file.Name
oExec.StdIn.Writeline(commandTxt)
Wscript.Echo commandTxt
WScript.Sleep 100
Next
' Finish session
oExec.StdIn.Writeline "exit"
Wscript.Echo "exit"
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 & 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 < 4 ) Then
WScript.Echo( vbCrLf &" usage: cscript moveocx.vbs source_local_full_path local_ftp_path remote_ftp_path move_to_path user pass host")
WScript.Echo( vbCrLf &" example: " &vbCrLf &" cscript moveocx.vbs D:\FTPROOT\IN\LOCAL IN/FOO OUT/FOO DONE MYLOGIN MYPASS MYHOST")
WScript.Echo( vbCrLf &" " &vbCrLf &" 1 - Gets files from OUT/FOO -> IN/FOO using the recorded MYLOGIN connection")
WScript.Echo( vbCrLf &" " &vbCrLf &" 2 - moves files names found in D:\FTPROOT\IN\LOCAL, on remote from OUT/FOO -> OUT/FOO/DONE")
WScript.Quit
End If
' -------------------------------------------
'| MAIN |
' -------------------------------------------
' Set Basic path
commandTxt = "" ' Empty current command
' instanciate chilkat FTP Component
Set fso = CreateObject("Scripting.FileSystemObject")
' 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 = "" Then
Wscript.Echo "No Folder parameter was passed"
Wscript.Quit
Else
Wscript.Echo "Runing For " & localPath & " , " & localFolder & " , " & remoteFolder & " , " & moveSubFolder & " on connection " & host
End If
' JBH - Open ftp command
'Set ftpo = CreateObject("InetCtls.Inet.1") 'Msinet.ocx
Set ftpo = CreateObject("ChilkatFTP.ChilkatFTP.1")
ftpo.Username = user
ftpo.Password = password
ftpo.Hostname = host
ftpo.Password = pass
ftpo.Passive = true
Wscript.Echo "Connecting..."
if (ftpo.Connect()) <> 1 Then
Wscript.Echo "Failed Connection : " & ftpo.LastErrorText
ftpo.Disconnect()
Wscript.Quit
else
' 00 - Set Remote Folder
Wscript.Echo "00 - Set remote folder to " & remoteFolder
If (ftpo.ChangeRemoteDir( remoteFolder )) <> 1 Then
Wscript.Echo "Failed setting remote dir : " & ftpo.LastErrorText
ftpo.Disconnect()
Wscript.Quit
End If
' 01 - DOWNLOAD
Wscript.Echo "01 - Getting All files from " & remoteFolder & " to " & localFolder
ok = ftpo.MGetFiles("*.*", localPath)
If (ok) <> 1 Then
Wscript.Echo " Download returned "& ok &" : " & 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 " Move files present in " & localPath & " to remote folder " & remoteFolder & "/" & moveSubFolder
For each file In Files
Wscript.Echo " Rename " & file.Name & " to " & moveSubFolder & "/" & file.Name
ok = ftpo.RenameRemoteFile(file.Name, moveSubFolder & "/" & file.Name)
If (ok) <> 1 Then
Wscript.Echo " Rename Returned unexpected value (" & ok & ") " & ftpo.LastErrorText
'ftpo.Disconnect()
'Wscript.Quit
End If
Next
' Finish session
WScript.Echo "Closing"
ftpo.Disconnect()
WScript.Echo "Done!"
End if
</pre>Convert virtual drive from virtualbox to vmwareurn:md5:56e6f94f6456c20b4e5820e481930c132011-06-21T23:03:00+02:002011-06-22T09:23:05+02:00Jean-Baptiste HerenLinuxcloud 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 "/Users/jb/VirtualBox VMs/myvirtualdrive"
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 <uuid>|<filename> <outputfile>
[--format VDI|VMDK|VHD|RAW|<other>]
[--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 portalurn:md5:dfe98200e5cd1aba7b5a61190d1de8902011-05-26T11:50:00+02:002011-12-02T15:52:54+01:00Jean-Baptiste HerenPeoplesoft <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')), ' > ')), ' > ') 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 anotherurn:md5:07d53922a2168685fa5806e759b000d52011-04-06T15:45:00+02:002011-05-09T09:25:21+02:00Jean-Baptiste HerenDécisionnelCognosReport 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]->:[YK].[[First dimension]].[First hierarchy]].[First Level]].&[00004]]]
-- to Destination Hierarchy
[Second package].[Second dimension].[Second hierarchy].[Second Level]->:[YK].[[Second dimension]].[Second hierarchy]].[Second Level]].&[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 xslturn:md5:88da78e37f99ab7b588f608cb2ed9ca92011-03-30T06:56:00+02:002011-04-07T15:16:44+02:00Jean-Baptiste HerenDécisionnelcognos 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]
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h1>Query Subjects</h1>
<table border="1">
<tr>
<td><h2>refObj</h2></td>
<td><h2>Source Type</h2></td>
<td><h2>Namespace</h2></td>
<td><h2>Folder</h2></td>
<td><h2>Query Subject</h2></td>
<td><h2>dataSource</h2></td>
<td><h2>sql</h2></td>
</tr>
<xsl:for-each select="//querySubject[@status = 'valid']">
<tr>
<td><p>[<xsl:value-of select="../../name"/>].[<xsl:value-of select="name"/>]</p></td>
<td><p><xsl:value-of select="definition/dbQuery/tableType"/></p></td>
<td><p><xsl:value-of select="../../name"/></p></td>
<td><p><xsl:value-of select="../name"/></p></td>
<td><p><xsl:value-of select="name"/></p></td>
<td><p><xsl:value-of select="definition/dbQuery/sources/dataSourceRef"/></p></td>
<td><p><xsl:value-of select="definition/dbQuery/sql"/></p></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template></xsl:stylesheet>
</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]
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="modelspecs.xsl"?>
<project>
</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]
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:strip-space elements="*"/><xsl:output method="text"/><xsl:template match="/">refObj;Source type
<xsl:for-each select="//namespace">
<xsl:if test="string-length(property[@name = 'dynamicContent']) != 0">[<xsl:value-of select="name"/>];Cube
</xsl:if>
</xsl:for-each>
</xsl:template></xsl:stylesheet>
</pre>
<p>- Query Subjects & SQL : This example outputs simple xml file to be used as a XML source in SSIS.</p>
<pre>[XML]
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" cdata-section-elements="sql"/>
<xsl:template match="/">
<xsl:element name="root">
<xsl:for-each select="//querySubject[@status = 'valid']">
<xsl:element name="querySubjects">
<xsl:element name="refObj">[<xsl:value-of select="../../name"/>].[<xsl:value-of select="name"/>]</xsl:element>
<xsl:element name="sourceType"><xsl:value-of select="definition/dbQuery/tableType"/></xsl:element>
<xsl:element name="namespace"><xsl:value-of select="../../name"/></xsl:element>
<xsl:element name="folder"><xsl:value-of select="../name"/></xsl:element>
<xsl:element name="querySubject"><xsl:value-of select="name"/></xsl:element>
<xsl:element name="dataSource"><xsl:value-of select="definition/dbQuery/sources/dataSourceRef"/></xsl:element>
<xsl:element name="sql"><xsl:value-of disable-output-escaping="yes" select="definition/dbQuery/sql"/></xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template></xsl:stylesheet>
</pre>
<p>- Query Subjects & Query items detail : This example outputs simple xml file to be used as a XML source in SSIS.</p>
<pre>[XML]
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" cdata-section-elements="sql"/>
<xsl:template match="/">
<xsl:element name="root">
<xsl:for-each select="//querySubject[@status = 'valid']/queryItem">
<xsl:element name="QueryItems">
<xsl:element name="refObj">[<xsl:value-of select="../../../name"/>].[<xsl:value-of select="../name"/>].[<xsl:value-of select="name"/>]</xsl:element>
<xsl:element name="parentRefObj">[<xsl:value-of select="../../../name"/>].[<xsl:value-of select="../name"/>]</xsl:element>
<xsl:element name="QueryItem"><xsl:value-of select="name"/></xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template></xsl:stylesheet>
</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]
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" cdata-section-elements="sql"/>
<xsl:template match="/">
<xsl:element name="root">
<xsl:for-each select="//securityView/definition/set/refobj">
<xsl:element name="packages">
<xsl:element name="packageName"><xsl:value-of select="../../../name"/></xsl:element>
<xsl:element name="contentRefObj"><xsl:value-of select="."/></xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template></xsl:stylesheet>
</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]
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" cdata-section-elements="sql"/>
<xsl:template match="/">
<xsl:element name="root">
<xsl:for-each select="//dimension[@status = 'valid']">
<xsl:element name="dimensions">
<xsl:element name="namespace"><xsl:value-of select="../name"/></xsl:element>
<xsl:element name="dimension"><xsl:value-of select="name"/></xsl:element>
<xsl:element name="modelQuery"><xsl:value-of select="definition/modelQuery/sql"/></xsl:element>
<xsl:for-each select="hierarchy">
<xsl:element name="hierarchy">
<xsl:element name="name"><xsl:value-of select="name"/></xsl:element>
<xsl:for-each select=".//refobj">
<xsl:element name="refobject"><xsl:value-of select="."/></xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template></xsl:stylesheet>
</pre>
<p>Command line xsl transformation is possible using the xslproc program :</p>
<pre>[script]
xsltproc mysxmltocsv.xsl model.xml > doc.csv
or
xsltproc mysxmltoxml.xsl model.xml > 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:c93bd7c9259f6303069b285bf0dc2c622011-03-28T23:02:00+02:002011-03-29T13:46:40+02:00Jean-Baptiste HerenDécisionnelBusiness 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, "\")
pathOnly = Left(filePath, slashPosition)
MyFile = pathOnly + ActiveSheet.Name + "_macro_generated.sql"
'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) = "" 'Loop on rows until blank.
tableName = Trim(CStr(ActiveSheet.Cells(myRow, 1))) 'get Table name from first column
Do Until ActiveSheet.Cells(myRow, myCol) = "" '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))), "'", "''")
dataSQL = "EXEC sys.sp_addextendedproperty @name=N'" + property_name + "'"
dataSQL = dataSQL + ", @value=N'" + property_descr + "'"
dataSQL = dataSQL + ", @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE'"
dataSQL = dataSQL + ",@level1name=N'" + tableName + "';"
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 Descriptionurn:md5:f11d5baa5b1fb932f308ebfa8d3762f42011-03-28T22:57:00+02:002011-05-09T09:24:10+02:00Jean-Baptiste HerenDécisionnelCognos 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 pathurn:md5:0089f16face722c3674e9a4c0b49bc5a2011-03-28T22:33:00+02:002011-03-29T13:46:59+02:00Jean-Baptiste HerenDécisionnelCognosCognos 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 & 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 & 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 OSXurn:md5:e1b4e2647fe8360f4699e9cc1cbc01be2011-02-09T00:26:00+01:002011-02-09T07:14:26+01:00Jean-Baptiste HerenLinuxdisk 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 naturelurn:md5:a854519c396f600a03ccdd9e0bcf6dc72011-01-25T10:21:00+01:002011-01-25T10:23:26+01:00Jean-Baptiste HerenVeille technoCMSdé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:8d152cf4bc7c3fe55ed53798cdb5bfb32011-01-24T23:45:00+01:002011-01-25T10:53:15+01:00Jean-Baptiste Herendéveloppement Webapachedé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
# <URL:http://httpd.apache.org/docs/2.2/vhosts/>
# 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 <VirtualHost> block.
#
# Magento
<VirtualHost *:80>
ServerAdmin webmaster@mag.localhost
DocumentRoot "D:\wamp\www\magento"
ServerName mag.localhost
ErrorLog "logs/mag.localhost-error.log"
CustomLog "logs/mag.localhost-access.log" common
<Directory "D:\wamp\www\magento">
Options Indexes FollowSymLinks
AllowOverride all
Order Deny,Allow
Deny from all
Allow from 127.0.0.1
</Directory>
</VirtualHost>
# localhost
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot "d:\wamp\www"
ServerName localhost
ErrorLog "logs/localhost-error.log"
CustomLog "logs/localhost-access.log" common
<Directory "d:\wamp\www">
Options Indexes FollowSymLinks
AllowOverride all
Order Deny,Allow
Deny from all
Allow from 127.0.0.1
</Directory>
</VirtualHost>
# Symfony
<VirtualHost *:80>
ServerAdmin webmaster@sf.localhost
DocumentRoot "d:/wamp/www/sf_sandbox/web/"
ServerName sf.localhost
ServerAlias www.sf.localhost
ErrorLog "logs/sf.localhost-error.log"
CustomLog "logs/dummy-host.localhost-access.log" common
<Directory "d:/wamp/www/sf_sandbox/web/">
Options Indexes FollowSymLinks
AllowOverride all
Order Deny,Allow
Deny from all
Allow from 127.0.0.1
</Directory>
Alias /sf/ "d:\wamp\www\sf_sandbox\lib\vendor\symfony\data\web\sf/"
<Directory "d:\wamp\www\sf_sandbox\lib\vendor\symfony\data\web\sf/">
Options Indexes FollowSymLinks MultiViews
AllowOverride all
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
# Apostrophe Symfony
<VirtualHost *:80>
ServerAdmin webmaster@a.localhost
DocumentRoot "d:/wamp/www/asandbox/web/"
ServerName a.localhost
ServerAlias www.a.localhost
ErrorLog "logs/sf.localhost-error.log"
CustomLog "logs/dummy-host.localhost-access.log" common
<Directory "d:/wamp/www/asandbox/web/">
Options Indexes FollowSymLinks
AllowOverride all
Order Deny,Allow
Deny from all
Allow from 127.0.0.1
</Directory>
Alias /sf/ "d:\wamp\www\asandbox\lib\vendor\symfony\data\web\sf/"
<Directory "d:\wamp\www\asandbox\lib\vendor\symfony\data\web\sf/">
Options Indexes FollowSymLinks MultiViews
AllowOverride all
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
</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 & 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:ea963c23ec708d8a1a15c7a70946830e2011-01-24T16:39:00+01:002011-01-25T13:41:59+01:00Jean-Baptiste HerenDécisionnelAnalysis ServicesSQL ServerSQL Server 2005 <p>Voici une astuce pour SSAS sous SQL Server 2005. Si vous rencontrez l'erreur :</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 Debianurn:md5:0216bd919fd11a4ba3897f249d0f36fc2011-01-15T12:15:00+01:002011-01-17T11:46:27+01:00Jean-Baptiste HerenDécisionnelBusiness IntelligenceConsultant décisionneldebianJasperlinux <p>JasperServer est la solution open source de BI & 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 :
<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 & manager.</p>
<pre>[xml]
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
<role rolename="tomcat"/>
<role rolename="manager"/>
<role rolename="admin"/>
<user username="tomcat" password="tomcat" roles="tomcat,admin,manager"/>
</tomcat-users>
</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="$BASEDIR"/common/endorsed
# JBH - Parameters for JasperServer to work fine
export JAVA_OPTS="$JAVA_OPTS -Xms128m -Xmx512m -XX:PermSize=32m -XX:MaxPermSize=128m -Xss2m -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled"
</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 :</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 "/usr/share/tomcat5.5/webapps/jasperserver/WEB-INF/classes/logging.properties", "read";
//
Il faut editer ensuite le fichier
///[script]
# vi /etc/tomcat5.5/policy.d/50user.policy
</pre>
<p>Ajouter la définition suivante :</p>
<pre>[script]
grant codeBase "file:/usr/share/tomcat5.5/webapps/jasperserver/-" {
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 :</p>
<pre>[script]
# vim /etc/default/tomcat5.5
</pre>
<p>Modifiez la valeur du TOMCAT5_SECURITY comme suit :</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 HOWTOurn:md5:359cde0d2e5974a67d75845f6035eb222011-01-13T06:12:00+01:002011-01-21T22:02:48+01:00Jean-Baptiste HerenPeoplesoftApplication 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->New->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 &fileLog;
Local ApiObject &oSession, &oMYCINAMEPoRecv;
Function errorHandler()
Local ApiObject &oPSMessageCollection, &oPSMessage;
Local number &i;
Local String &sErrMsgSetNum, &sErrMsgNum, &sErrMsgText, &sErrType;
&oPSMessageCollection = &oSession.PSMessages;
For &i = 1 To &oPSMessageCollection.Count
&oPSMessage = &oPSMessageCollection.Item(&i);
&sErrMsgSetNum = &oPSMessage.MessageSetNumber;
&sErrMsgNum = &oPSMessage.MessageNumber;
&sErrMsgText = &oPSMessage.Text;
&fileLog.WriteLine(&sErrType | " (" | &sErrMsgSetNum | "," | &sErrMsgNum | ") - " | &sErrMsgText);
End-For;
rem ***** Delete the Messages from the collection *****;
&oPSMessageCollection.DeleteAll();
End-Function;
try
rem ***** Set the Log File *****;
&fileLog = GetFile("C:\temp\MY_CI_NAME.log", "w", "a", %FilePath_Absolute);
&fileLog.WriteLine("Begin");
rem ***** Get current PeopleSoft Session *****;
&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 *****;
&oSession.PSMessagesMode = 1;
rem ***** Get the Component Interface *****;
&oMYCINAMEPoRecv = &oSession.GetCompIntfc(CompIntfc.MY_CI_NAME_RECV);
If &oMYCINAMEPoRecv = Null Then
errorHandler();
throw CreateException(0, 0, "GetCompIntfc failed");
End-If;
rem ***** Set the Component Interface Mode *****;
&oMYCINAMEPoRecv.InteractiveMode = False;
&oMYCINAMEPoRecv.GetHistoryItems = True;
&oMYCINAMEPoRecv.EditHistoryItems = False;
rem ***** Set Component Interface Get/Create Keys *****;
rem ***** Execute Get *****;
If Not &oMYCINAMEPoRecv.Get() Then
rem ***** No rows exist for the specified keys.*****;
errorHandler();
throw CreateException(0, 0, "Get failed");
End-If;
rem ***** Begin: Get/Set Component Interface Properties *****;
rem ***** Get/Set Level 0 Field Properties *****;
&fileLog.WriteLine("&oMYCINAMEPoRecv.INV_LOT_ID = " | &oMYCINAMEPoRecv.INV_LOT_ID);
rem &oMYCINAMEPoRecv.INV_LOT_ID = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.INV_ITEM_ID = " | &oMYCINAMEPoRecv.INV_ITEM_ID);
rem &oMYCINAMEPoRecv.INV_ITEM_ID = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.SERIAL_ID = " | &oMYCINAMEPoRecv.SERIAL_ID);
rem &oMYCINAMEPoRecv.SERIAL_ID = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.STORAGE_AREA = " | &oMYCINAMEPoRecv.STORAGE_AREA);
rem &oMYCINAMEPoRecv.STORAGE_AREA = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.STOR_LEVEL_1 = " | &oMYCINAMEPoRecv.STOR_LEVEL_1);
rem &oMYCINAMEPoRecv.STOR_LEVEL_1 = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.STOR_LEVEL_2 = " | &oMYCINAMEPoRecv.STOR_LEVEL_2);
rem &oMYCINAMEPoRecv.STOR_LEVEL_2 = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.STOR_LEVEL_3 = " | &oMYCINAMEPoRecv.STOR_LEVEL_3);
rem &oMYCINAMEPoRecv.STOR_LEVEL_3 = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.STOR_LEVEL_4 = " | &oMYCINAMEPoRecv.STOR_LEVEL_4);
rem &oMYCINAMEPoRecv.STOR_LEVEL_4 = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.CONTAINER_ID = " | &oMYCINAMEPoRecv.CONTAINER_ID);
rem &oMYCINAMEPoRecv.CONTAINER_ID = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.UNIT_OF_MEASURE = " | &oMYCINAMEPoRecv.UNIT_OF_MEASURE);
rem &oMYCINAMEPoRecv.UNIT_OF_MEASURE = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.RECEIVER_ID = " | &oMYCINAMEPoRecv.RECEIVER_ID);
rem &oMYCINAMEPoRecv.RECEIVER_ID = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.QTY = " | &oMYCINAMEPoRecv.QTY);
rem &oMYCINAMEPoRecv.QTY = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.SCHED_NBR = " | &oMYCINAMEPoRecv.SCHED_NBR);
rem &oMYCINAMEPoRecv.SCHED_NBR = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.SETID = " | &oMYCINAMEPoRecv.SETID);
rem &oMYCINAMEPoRecv.SETID = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.SHIPTO_ID = " | &oMYCINAMEPoRecv.SHIPTO_ID);
rem &oMYCINAMEPoRecv.SHIPTO_ID = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.VENDOR_ID = " | &oMYCINAMEPoRecv.VENDOR_ID);
rem &oMYCINAMEPoRecv.VENDOR_ID = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.SHIPMENT_NO = " | &oMYCINAMEPoRecv.SHIPMENT_NO);
rem &oMYCINAMEPoRecv.SHIPMENT_NO = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.CARRIER_ID = " | &oMYCINAMEPoRecv.CARRIER_ID);
rem &oMYCINAMEPoRecv.CARRIER_ID = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.BILL_OF_LADING = " | &oMYCINAMEPoRecv.BILL_OF_LADING);
rem &oMYCINAMEPoRecv.BILL_OF_LADING = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.BUSINESS_UNIT_PO = " | &oMYCINAMEPoRecv.BUSINESS_UNIT_PO);
rem &oMYCINAMEPoRecv.BUSINESS_UNIT_PO = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.PO_ID = " | &oMYCINAMEPoRecv.PO_ID);
rem &oMYCINAMEPoRecv.PO_ID = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.LINE_NBR = " | &oMYCINAMEPoRecv.LINE_NBR);
rem &oMYCINAMEPoRecv.LINE_NBR = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.BUSINESS_UNIT_IN = " | &oMYCINAMEPoRecv.BUSINESS_UNIT_IN);
rem &oMYCINAMEPoRecv.BUSINESS_UNIT_IN = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.VENDOR_LOT_ID = " | &oMYCINAMEPoRecv.VENDOR_LOT_ID);
rem &oMYCINAMEPoRecv.VENDOR_LOT_ID = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.TAG_NUMBER = " | &oMYCINAMEPoRecv.TAG_NUMBER);
rem &oMYCINAMEPoRecv.TAG_NUMBER = [*];
&fileLog.WriteLine("&oMYCINAMEPoRecv.TRANSACTION_CODE = " | &oMYCINAMEPoRecv.TRANSACTION_CODE);
rem &oMYCINAMEPoRecv.TRANSACTION_CODE = [*];
rem ***** End: Get/Set Component Interface Properties *****;
rem ***** Execute Save *****;
rem If Not &oMYCINAMEPoRecv.Save() Then;
rem errorHandler();
rem throw CreateException(0, 0, "Save failed");
rem End-If;
rem ***** Execute Cancel *****;
rem If Not &oMYCINAMEPoRecv.Cancel() Then;
rem errorHandler();
rem throw CreateException(0, 0, "Cancel failed");
rem End-If;
catch exception &ex
rem Handle the exception;
&fileLog.WriteLine(&ex.ToString());
end-try;
&fileLog.WriteLine("End");
&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 & Session as a parameter:</h4>
<pre>[vb]
Function errorHandler(&fileLog As File, &oSession As ApiObject)
Local ApiObject &oPSMessageCollection, &oPSMessage;
Local number &i;
Local string &sErrMsgSetNum, &sErrMsgNum, &sErrMsgText, &sErrType;
&oPSMessageCollection = &oSession.PSMessages;
For &i = 1 To &oPSMessageCollection.Count
&oPSMessage = &oPSMessageCollection.Item(&i);
&sErrMsgSetNum = &oPSMessage.MessageSetNumber;
&sErrMsgNum = &oPSMessage.MessageNumber;
&sErrMsgText = &oPSMessage.Text;
&fileLog.WriteLine(&sErrType | " (" | &sErrMsgSetNum | "," | &sErrMsgNum | ") - " | &sErrMsgText);
End-For;
rem ***** Delete the Messages from the collection *****;
&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 &barcode parameter
Function getBarcodeRecord(&barcode As string) Returns Record
Local Rowset &RwsBarcode;
Local Record &REcBarcode;
&RwsBarcode = CreateRowset(Record.MY_BCODE_TBL);
&RwsBarcode.Fill("WHERE RECV_CARD_ID = :1", &barcode);
&REcBarcode = CreateRecord(Record.MY_BCODE_TBL);
&REcBarcode = &RwsBarcode(1).GetRecord(1);
Return &REcBarcode;
End-Function;
// This Function is scheduling a job
Function RunJobRecv(&barcode As string) Returns boolean
Local boolean &success = False;
Local ProcessRequest &prcsrqst;
Local JavaObject &Obj;
Local Record &RecRECVLOAD;
Local Record &RecRECVPUSH;
Local Record &RecINPSSTGE;
// Select data using barcode ID - start;
Local Record &REcBarcode;
&REcBarcode = getBarcodeRecord(&barcode);
// Select data using barcode ID - end;
&jobname = "MYRECVJOB";
// Create Data In Needed Run Control Parameters;
// 01 - RECVLOAD;
&RecRECVLOAD = CreateRecord(Record.RUN_CNTL_RECVLD);
&RecRECVLOAD.OPRID.Value = %UserId;
&RecRECVLOAD.RUN_CNTL_ID.Value = &jobname;
&RecRECVLOAD.RECVLOAD_OPT.Value = "2";
&RecRECVLOAD.BUSINESS_UNIT.Value = &REcBarcode.BUSINESS_UNIT_IN.Value;
&RecRECVLOAD.WHERE_CLAUSE.Value = "BUSINESS_UNIT = '" | &RecRECVLOAD.BUSINESS_UNIT.Value | "'";
If Not &RecRECVLOAD.Insert() Then
&RecRECVLOAD.Update();
End-If;
// 02 - RUN_PO_RECEIPT;
&RecRECVPUSH = CreateRecord(Record.RECV_RUN_CNTL);
&RecRECVPUSH.OPRID.Value = %UserId;
&RecRECVPUSH.RUN_CNTL_ID.Value = &jobname;
&RecRECVPUSH.RECEIVER_ID.Value = "";
&RecRECVPUSH.BUSINESS_UNIT.Value = &REcBarcode.BUSINESS_UNIT_IN.Value;
If Not &RecRECVPUSH.Insert() Then
&RecRECVPUSH.Update();
End-If;
REM Schedule the Job;
&prcsrqst = CreateProcessRequest("PSJob", &jobname);
&prcsrqst.RunControlID = &jobname;
&prcsrqst.JobName = &jobname;
&prcsrqst.Schedule();
If &prcsrqst.Status = 0 Then
/* Schedule succeeded. */
&success = True;
Else
/* Process (job) not scheduled, do error processing */
&success = False;
End-If;
/*
&Obj = CreateJavaObject("java.lang.Thread");
&Obj.start();
&RunStatus = "0";
While &RunStatus <> "9" And
&RunStatus <> "3" And
&RunStatus <> "1" And
&RunStatus <> "10"
REM Directly use the Java sleep() Method for 5 seconds;
&Obj.sleep(5000);
SQLExec("SELECT RUNSTATUS FROM PSPRCSRQST WHERE PRCSINSTANCE = :1", &prcsrqst.ProcessInstance, &RunStatus);
REM MessageBox(0, "", 0, 0, "Sleep(), Runstatus = %1", &RunStatus);
End-While;
&Obj.stop();
rem WriteLog("Process MYRECVJOB is Finished");
If &prcsrqst.Status = 10 Or
&prcsrqst.Status = 3 Then
REM Process your errors;
&success = False;
Else
REM Process your success;
&success = True;
End-If;
*/
Return &success;
End-Function;
// Adds data to a log table
Function LogBarcode(&barcode As string, &qty As number, &transaction_code As string) Returns boolean
Local Record &RecLog;
&RecLog = CreateRecord(Record.PH_RECV_BCD_LOG);
&RecLog.RECV_CARD_ID.Value = &barcode;
&RecLog.QTY.Value = &qty;
&RecLog.TRANSACTION_CODE.Value = &transaction_code;
&RecLog.DT_TIMESTAMP.Value = %Datetime;
&RecLog.OPRID.Value = %UserId;
Return &RecLog.Insert();
End-Function;
// ErrorHandler Function
Function errorHandler(&fileLog As File, &oSession As ApiObject)
Local ApiObject &oPSMessageCollection, &oPSMessage;
Local number &i;
Local string &sErrMsgSetNum, &sErrMsgNum, &sErrMsgText, &sErrType;
&oPSMessageCollection = &oSession.PSMessages;
For &i = 1 To &oPSMessageCollection.Count
&oPSMessage = &oPSMessageCollection.Item(&i);
&sErrMsgSetNum = &oPSMessage.MessageSetNumber;
&sErrMsgNum = &oPSMessage.MessageNumber;
&sErrMsgText = &oPSMessage.Text;
&fileLog.WriteLine(&sErrType | " (" | &sErrMsgSetNum | "," | &sErrMsgNum | ") - " | &sErrMsgText);
End-For;
rem ***** Delete the Messages from the collection *****;
&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 > Create Transactions > Receiving > Purchasing Receiving;*/
Function WriteReceipt(&barcode As string, &qty As number) Returns boolean
Local File &fileLog;
Local ApiObject &oSession, &oMYCINAMEPoRecv;
// Jean-Baptiste HEREN - Select data using barcode ID - start;
Local Record &REcBarcode;
&REcBarcode = getBarcodeRecord(&barcode);
// Jean-Baptiste HEREN - Select data using barcode ID - end;
try
rem ***** Set the Log File *****;
If %UserId = "jean-baptiste.heren" Then
&fileLog = GetFile("\\MyMachine\temp\CI\MY_CI_NAME_RECV_WriteReceipt.log", "w", "a", %FilePath_Absolute);
Else
&fileLog = GetFile("MY_CI_NAME_RECV.log", "w", "a", %FilePath_Relative);
End-If;
&fileLog.WriteLine("Begin");
rem ***** Get current PeopleSoft Session *****;
&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 *****;
&oSession.PSMessagesMode = 1;
rem ***** Get the Component Interface *****;
&oMYCINAMEPoRecv = &oSession.GetCompIntfc(CompIntfc.MY_CI_NAME_RECV);
If &oMYCINAMEPoRecv = Null Then
errorHandler(&fileLog, &oSession);
throw CreateException(0, 0, "GetCompIntfc failed");
End-If;
rem ***** Set the Component Interface Mode *****;
&oMYCINAMEPoRecv.InteractiveMode = True;
&oMYCINAMEPoRecv.GetHistoryItems = True;
&oMYCINAMEPoRecv.EditHistoryItems = False;
rem ***** Set Component Interface Get/Create Keys *****;
rem ***** Execute Get *****;
If Not &oMYCINAMEPoRecv.Get() Then
rem ***** No rows exist for the specified keys.*****;
errorHandler(&fileLog, &oSession);
throw CreateException(0, 0, "Get failed");
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;
&transaction_code = "0103";
&oMYCINAMEPoRecv.TRANSACTION_CODE = &transaction_code;
// Jean-Baptiste HEREN - Fill with the barcode ID data;
&oMYCINAMEPoRecv.SETID = &REcBarcode.SETID.Value;
&oMYCINAMEPoRecv.SHIPTO_ID = &REcBarcode.SHIPTO_ID.Value;
&oMYCINAMEPoRecv.VENDOR_ID = &REcBarcode.VENDOR_ID.Value;
&oMYCINAMEPoRecv.BUSINESS_UNIT_IN = &REcBarcode.BUSINESS_UNIT_IN.Value;
&oMYCINAMEPoRecv.CARRIER_ID = &REcBarcode.CARRIER_ID.Value;
&oMYCINAMEPoRecv.BILL_OF_LADING = &REcBarcode.BILL_OF_LADING.Value;
&oMYCINAMEPoRecv.BUSINESS_UNIT_PO = &REcBarcode.BUSINESS_UNIT_PO.Value;
&oMYCINAMEPoRecv.PO_ID = &REcBarcode.PO_ID.Value;
&oMYCINAMEPoRecv.LINE_NBR = &REcBarcode.LINE_NBR.Value;
&oMYCINAMEPoRecv.UNIT_OF_MEASURE = &REcBarcode.UNIT_OF_MEASURE.Value;
REM Still use Quantyty from Barcode screen;
&oMYCINAMEPoRecv.QTY = &qty;
rem ***** End: Get/Set Component Interface Properties *****;
rem ***** Execute Save *****;
If Not &oMYCINAMEPoRecv.Save() Then;
errorHandler(&fileLog, &oSession);
&success = False;
throw CreateException(0, 0, "Save failed");
Else
&success = True;
If Not LogBarcode(&barcode, &qty, &transaction_code) Then
&fileLog.WriteLine("LogBarcode Failed");
End-If;
End-If;
rem ***** Execute Cancel *****;
rem If Not &oMYCINAMEPoRecv.Cancel() Then;
rem errorHandler(&fileLog, &oSession);
rem throw CreateException(0, 0, "Cancel failed");
rem End-If;
catch Exception &ex
rem Handle the exception;
&fileLog.WriteLine(&ex.ToString());
end-try;
&fileLog.WriteLine("End");
&fileLog.Close();
Return &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 > Create Transactions > Receiving > Purchasing Receiving;*/
Function CloseReceipt(&barcode) Returns boolean
Local File &fileLog;
Local ApiObject &oSession, &oMYCINAMEPoRecv;
// Jean-Baptiste HEREN - Select data using barcode ID - start;
Local Record &REcBarcode;
&REcBarcode = getBarcodeRecord(&barcode);
// Jean-Baptiste HEREN - Select data using barcode ID - end;
try
rem ***** Set the Log File *****;
If %UserId = "jean-baptiste.heren" Then
&fileLog = GetFile("\\MyMachine\temp\CI\MY_CI_NAME_RECV_CloseReceipt.log", "w", "a", %FilePath_Absolute);
Else
&fileLog = GetFile("MY_CI_NAME_RECV.log", "w", "a", %FilePath_Relative);
End-If;
&fileLog.WriteLine("Begin");
rem ***** Get current PeopleSoft Session *****;
&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 *****;
&oSession.PSMessagesMode = 1;
rem ***** Get the Component Interface *****;
&oMYCINAMEPoRecv = &oSession.GetCompIntfc(CompIntfc.MY_CI_NAME_RECV);
If &oMYCINAMEPoRecv = Null Then
errorHandler(&fileLog, &oSession);
throw CreateException(0, 0, "GetCompIntfc failed");
End-If;
rem ***** Set the Component Interface Mode *****;
&oMYCINAMEPoRecv.InteractiveMode = True;
&oMYCINAMEPoRecv.GetHistoryItems = True;
&oMYCINAMEPoRecv.EditHistoryItems = False;
rem ***** Set Component Interface Get/Create Keys *****;
rem ***** Execute Get *****;
If Not &oMYCINAMEPoRecv.Get() Then
rem ***** No rows exist for the specified keys.*****;
errorHandler(&fileLog, &oSession);
throw CreateException(0, 0, "Get failed");
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;
&qty = 0;
&transaction_code = "0105";
&oMYCINAMEPoRecv.TRANSACTION_CODE = &transaction_code;
REM JBH - Fill with the barcode ID data.value;
&oMYCINAMEPoRecv.SETID = &REcBarcode.SETID.Value;
&oMYCINAMEPoRecv.SHIPTO_ID = &REcBarcode.SHIPTO_ID.Value;
REM &oMYCINAMEPoRecv.VENDOR_ID = &REcBarcode.VENDOR_ID.Value;
REM &oMYCINAMEPoRecv.BUSINESS_UNIT_IN = &REcBarcode.BUSINESS_UNIT_IN.value;
&oMYCINAMEPoRecv.CARRIER_ID = &REcBarcode.CARRIER_ID.Value;
&oMYCINAMEPoRecv.BILL_OF_LADING = &REcBarcode.BILL_OF_LADING.Value;
REM &oMYCINAMEPoRecv.BUSINESS_UNIT_PO = &REcBarcode.BUSINESS_UNIT_PO.value;
REM &oMYCINAMEPoRecv.PO_ID = &REcBarcode.PO_ID.value;
REM &oMYCINAMEPoRecv.LINE_NBR = &REcBarcode.LINE_NBR.value;
REM &oMYCINAMEPoRecv.UNIT_OF_MEASURE = &REcBarcode.UNIT_OF_MEASURE.value;
REM Still use Quantyty from Barcode screen;
REM &oMYCINAMEPoRecv.QTY = &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 &oMYCINAMEPoRecv.Save() Then;
errorHandler(&fileLog, &oSession);
&success = False;
throw CreateException(0, 0, "Save failed");
Else
&success = True;
If Not LogBarcode(&barcode, &qty, &transaction_code) Then
&fileLog.WriteLine("LogBarcode Failed");
End-If;
End-If;
rem ***** Execute Cancel *****;
rem If Not &oMYCINAMEPoRecv.Cancel() Then;
rem errorHandler(&fileLog, &oSession);
rem throw CreateException(0, 0, "Cancel failed");
rem End-If;
catch Exception &ex
rem Handle the exception;
&fileLog.WriteLine(&ex.ToString());
end-try;
&fileLog.WriteLine("End");
&fileLog.Close();
Return &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("SELECT 1 FROM PS_PH_RECV_BCD_LOG WHERE RECV_CARD_ID = :1", MY_RECV_TABLE.RECV_CARD_ID.Value, &result);
If &result <> 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("Reception Failed!");
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 = "";
MY_RECV_TABLE.QTY.Value = 0;
End-If;
Else
WinMessage("Card ID has already been scanned !");
SetCursorPos(%Page, MY_RECV_TABLE.RECV_CARD_ID, CurrentRowNumber());
REM Clean Screen;
MY_RECV_TABLE.RECV_CARD_ID.Value = "";
MY_RECV_TABLE.QTY.Value = 0;
End-If;
End-If;
</pre>désactiver le timeout avec sfGUardSecurityUser dans Symfonyurn:md5:9f869fc2f968652dc9f1b51dd751fcb72011-01-12T21:55:00+01:002011-01-13T10:11:41+01:00Jean-Baptiste Herendé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 SQRurn:md5:c99134ae31e14de57e650cce8e3b2be02010-12-07T11:31:00+01:002011-01-06T15:14:58+01:00Jean-Baptiste HerenPeoplesoftpeoplesoftsqr<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 & 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 hierarchieurn:md5:f35f2a485b57edac5673c6e8a6f749272010-11-03T18:02:00+01:002011-12-02T16:04:58+01:00Jean-Baptiste HerenDécisionnelCognoscognos 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>