In unserem vorheriger Blog, wir haben erklärt, wie Bilder, die von Außendiensttechnikern angehängt wurden, direkt in BIRT-Berichten in IBM Maximo 7.6 angezeigt werden. Dieser Ansatz funktionierte, indem Bilddateien direkt aus dem Dateisystem des Servers gelesen wurden. Dabei wurde ein lokaler Dateipfad verwendet, der im URL-Name Feld der docinfo Objekt.

Mit der Umstellung auf IBM Maximo Application Suite (MAS 9) funktioniert diese Methode nicht mehr. KARTEN 9 ist eine Cloud-native Plattform, und Anlagen werden nicht mehr auf einem lokalen Dateisystem gespeichert, sondern in Cloud-Objektspeicher (COS), das S3-kompatibel ist. Das URL-Name Das Feld enthält jetzt eine COS-Referenz (z. B. cos:doclinks/your-file.jpg) statt eines lokalen Pfads, sodass der alte File () -Ansatz völlig fehlschlägt.

In diesem Blog wird der aktualisierte Ansatz zum Abrufen und Rendern dieser Bilder von S3/COS in Ihren BIRT-Berichten auf MAS 9 beschrieben.

Warum der alte Ansatz auf MAS 9 nicht funktioniert

In Maximo 7.6 zeigte der URLName-Wert direkt auf eine Datei auf der Festplatte, zum Beispiel:

/opt/IBM/SMP/maximo/doclinks/Attachments/image.jpg 


Das Skript las diese Datei einfach mit java.io.File und übergab die Bytes an das dynamische BIRT-Image-Element — einfach für eine lokale Bereitstellung.

In KARTEN 9, dasselbe Feld enthält jetzt eine COS-URI wie:

cos:doclinks/image.jpg 


Es gibt keine lokale Datei zum Lesen. Das Image befindet sich in einem S3-Bucket, und Sie müssen sich mit AWS-Anmeldeinformationen authentifizieren und das Objekt zur Laufzeit des Berichts herunterladen. Das BIRT-Berichtslayout selbst (dynamisches Bild in einer Tabellenzelle) bleibt exakt gleich. Nur die Skripts müssen geändert werden.

Die MAS 9-Lösung: Bilder von S3/COS abrufen

Die Lösung umfasst zwei Skriptbereiche im BIRT-Berichtsdesigner:

  • Skript initialisieren - wird einmal ausgeführt, wenn der Bericht gestartet wird; richtet den S3-Client mithilfe der Maximo-Systemeigenschaften ein.
  • OnCreate-Skript - wird für jede Bildzeile ausgeführt; ruft das Bild von S3 ab, verarbeitet es und gibt die Bytes an das dynamische Bildelement weiter.

Die Schritte zum Berichtslayout (Erstellen eines Datensatzes aus docinfo, an eine Tabelle binden, ein dynamisches Bildelement einfügen) bleiben die gleichen wie im Original-Blog beschrieben. Wenn Sie diese Schritte noch nicht abgeschlossen haben, lesen Sie die Schritte 1—3 der originale Anleitung zuerst.

Schrittweise Implementierung

Schritt 1: Das DataSet erstellen

Erstellen Sie wie zuvor einen Datensatz, der die URL-Name aus dem docinfo Objekt, gefiltert nach Ihren Kriterien (z. B. bestimmte Prüffrage oder Dokumenttyp). Das URL-Name column ist das, was die Skripte verwenden, um das Bild in S3 zu finden.

Schritt 2: Binden Sie den Datensatz und fügen Sie ein dynamisches Bild ein

Konstruieren Sie Ihre Tabelle, binden Sie sie an den Datensatz und platzieren Sie ein Bildelement in der entsprechenden Zelle. Stellen Sie den Bildquellentyp auf ein „Dynamisches Bild“ — das ist unverändert gegenüber Maximo 7.6.

Schritt 3: Initialisierungsskript hinzufügen

In dem Bericht Initialisieren Skriptabschnitt, fügen Sie Folgendes hinzu. Dies wird einmal beim Start des Berichts ausgeführt, liest die COS-Anmeldeinformationen aus den Maximo-Systemeigenschaften und erstellt einen gemeinsam genutzten S3-Client:


importPackage(Packages.com.ibm.tivoli.maximo.report.script); 
importPackage(Packages.com.amazonaws.auth); 
importPackage(Packages.com.amazonaws.services.s3); 
importPackage(Packages.com.amazonaws.services.s3.model); 
importPackage(Packages.psdi.server); 

var accessKey = MXServer.getMXServer().getProperty("mxe.cosaccesskey"); 
var secretKey = MXServer.getMXServer().getProperty("mxe.cossecretkey"); 
var bucketName = MXServer.getMXServer().getProperty("mxe.cossysbucket"); 

// Set up AWS credentials and S3 client 
var credentials = new BasicAWSCredentials(accessKey, secretKey); 
var s3Client = new AmazonS3Client(credentials); 

mxReportScriptContext = MXReportScriptContext.initialize(reportContext); 
mxReportScriptContext.setDefaultLogLevel("DEBUG"); 
mxReportScriptContext.setDefaultLogFile("servicereport.log"); 
scriptLogger = mxReportScriptContext.getReportScriptLogger(); 

 


Hinweis: Die Anmeldeinformationen (mxe.cosaccesskey, mxe.cossecretkey, mxe.cossysbucket) werden direkt aus den Systemeigenschaften von Maximo gelesen, sodass sensible Werte im Bericht nicht fest codiert werden müssen.

Schritt 4: Fügen Sie das OnCreate-Skript hinzu

In den dynamischen Bildelementen Beim Erstellen Skript, füge Folgendes hinzu. Es wird für jede Zeile ausgelöst, analysiert die COS-URI, lädt das Bild herunter, übernimmt die Formatkonvertierung, wendet die JPEG-Komprimierung an und legt die Anzeigemaße fest:

importPackage(Packages.javax.imageio); 
importPackage(Packages.javax.imageio.stream); 
importPackage(Packages.java.io); 
importPackage(Packages.java.lang); 
importPackage(Packages.java.awt.image); 
importPackage(Packages.java.awt); 
importPackage(Packages.java.net); 
importPackage(Packages.com.amazonaws.auth); 
importPackage(Packages.com.amazonaws.services.s3); 
importPackage(Packages.com.amazonaws.services.s3.model); 

if (row["urlName"] != null) { 
    var fullUrl = String(row["urlName"]); 
    var prefix = "cos:doclinks/"; 
    var cleanFileName = fullUrl; 
    var fileName = ""; 
    var fileExtension = ""; 

    if (fullUrl != null) { 
        if (fullUrl.startsWith(prefix)) { 
            cleanFileName = fullUrl.substring(prefix.length); 
        } 
        var lastSlashIndex = cleanFileName.lastIndexOf("/"); 
        fileName = (lastSlashIndex >= 0) 
            ? cleanFileName.substring(lastSlashIndex + 1) : cleanFileName; 
        var lastDotIndex = fileName.lastIndexOf("."); 
        if (lastDotIndex >= 0 && lastDotIndex < fileName.length - 1) { 
            fileExtension = String(fileName.substring(lastDotIndex + 1).toLowerCase()); 
        } 
    } 

    var s3Object = null; var inputStream = null; 
    var img = null; var bas = null; 
    var ios = null; var writer = null; 

    try { 
        s3Object = s3Client.getObject(new GetObjectRequest(bucketName, cleanFileName)); 
        inputStream = s3Object.getObjectContent(); 
        img = ImageIO.read(inputStream); 

        if (img == null) { 
            throw new Error("Failed to read image from S3: " + fileName); 
        } 

        // Convert to RGB if needed 
        if (img.getType() !== BufferedImage.TYPE_INT_RGB) { 
            var rgbImage = new BufferedImage( 
                img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB); 
            var g = rgbImage.createGraphics(); 
            g.drawImage(img, 0, 0, Color.WHITE, null); 
            g.dispose(); 
            img = rgbImage; 
        } 

        bas = new ByteArrayOutputStream(); 
        var format = (["jpeg","jpg","png","bmp"].indexOf(fileExtension) >= 0) 
            ? fileExtension : "jpeg"; 

        if (format === "jpeg" || format === "jpg") { 
            var writers = ImageIO.getImageWritersByFormatName("jpeg"); 
            if (!writers.hasNext()) throw new Error("No JPEG writer available"); 
            writer = writers.next(); 
            ios = ImageIO.createImageOutputStream(bas); 
            writer.setOutput(ios); 
            var param = writer.getDefaultWriteParam(); 
            if (param.canWriteCompressed()) { 
                param.setCompressionMode( 
                    javax.imageio.ImageWriteParam.MODE_EXPLICIT); 
                param.setCompressionQuality(0.3); 
            } 
            writer.write(null, 
                new javax.imageio.IIOImage(img, null, null), param); 
        } else { 
            if (!ImageIO.write(img, format, bas)) { 
                throw new Error("Failed to write image: " + format); 
            } 
        } 

        this.data = bas.toByteArray(); 

        var picWidth = img.getWidth(); 
        if (picWidth > 300) { 
            var aspectRatio = img.getHeight() / picWidth; 
            this.width = '300px'; 
            this.height = Math.round(300 * aspectRatio) + 'px'; 
        } else { 
            this.width = null; this.height = null; 
        } 

    } catch (e) { 
        throw new Error("Error processing '" + fileName + "': " + e.message); 
    } finally { 
        if (writer != null) writer.dispose(); 
        if (ios != null) ios.close(); 
        if (bas != null) bas.close(); 
        if (inputStream != null) inputStream.close(); 
        if (s3Object != null) s3Object.close(); 
    } 
} 

Schritt 5: Vorschau und Bereitstellung

Zeigen Sie eine Vorschau des Berichts im BIRT Designer an, um zu überprüfen, ob die Bilder korrekt gerendert werden. Importieren Sie den Bericht nach der Überprüfung in MAS und testen Sie ihn, indem Sie anhand eines Arbeitsauftrags oder einer Inspektion eine PDF-Datei mit Fotoanhängen erstellen.

Hauptunterschiede: Maximo 7.6 gegen MAS 9

Die Migration von Maximo 7.6 zu KARTEN 9 führt eine grundlegende Änderung in der Art und Weise ein, wie Anlagen gespeichert und abgerufen werden. Durch den Übergang von einem lokalen dateibasierten Ansatz zum S3/COS-basierten Abruf müssen die Skripte, die dynamische Bilder in BIRT-Berichten unterstützen, entsprechend aktualisiert werden.

Da das Initialize Script die S3-Authentifizierung verarbeitet und das OnCreate Script den Objektdownload und die Bildverarbeitung verwaltet, können Sie in MAS 9 weiterhin umfangreiche, bildoptimierte Berichte erstellen, die genauso effektiv sind wie in 7.6.

Entdecken Sie den ultimativen Leitfaden zur IBM Maximo Application Suite (MAS)

Erfahren Sie alles, was Sie wissen müssen, um Ihre Vermögensverwaltungsstrategie zu modernisieren.

Darin erfährst du:

  • Was ist neu in IBM Maximo Application Suite 9.0
  • Hauptunterschiede zwischen Maximo 7.6 und MAS
  • Wie AppPoints und OpenShift das Spiel verändern
  • Branchenanwendungsfälle in den Bereichen Energie, Fertigung und Transport
  • Schrittweise Anleitung für das Upgrade und die Bereitschaft zur Migration
Cover of 'The Ultimate Guide to MAS Maximo Application Suite' by Naviam featuring a man in a yellow construction helmet and safety vest holding a tablet.
×

ActiveG, BPD Zenith, EAM Swiss, InterPro Solutions, Lexco, Peacock Engineering, Projetech, Sharptree, and ZNAPZ have united under one brand: Naviam.

You’ll be redirected to the most relevant page at Naviam.io in a few seconds — or you can go now.

Read Press Release