Cómo mostrar los archivos adjuntos en los informes BIRT para IBM Maximo Application Suite (MAS 9)

Ver Bolisetti

April 29, 2026

En nuestro blog anterior, explicamos cómo mostrar las imágenes adjuntas por los técnicos de campo directamente en los informes BIRT en IBM Maximo 7.6. Este enfoque consistía en leer los archivos de imagen directamente desde el sistema de archivos del servidor mediante una ruta de archivo local almacenada en Nombre de URL campo de la docinfo objeto.

Con el cambio a IBM Maximo Application Suite (MAS 9), ese método ya no funciona. MARZO 9 es una plataforma nativa de la nube y los archivos adjuntos ya no se almacenan en un sistema de archivos local, sino en Almacenamiento de objetos en la nube (COS), que es compatible con S3. El Nombre de URL El campo ahora contiene una referencia COS (por ejemplo, cos:doclinks/your-file.jpg) en lugar de una ruta local, por lo que el enfoque anterior de File () falla por completo.

Este blog detalla el enfoque actualizado para obtener y renderizar esas imágenes de S3/COS en sus informes BIRT en MAS 9.

Por qué el viejo enfoque fracasa en MAS 9

En Maximo 7.6, el valor de URLName apuntaba directamente a un archivo en el disco, por ejemplo:

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


El script simplemente leía ese archivo con java.io.File y pasaba los bytes al elemento de imagen dinámica BIRT, algo sencillo para una implementación local.

En MARZO 9, el mismo campo ahora contiene una URI COS como:

cos:doclinks/image.jpg 


No hay ningún archivo local que leer. La imagen se encuentra en un bucket de S3 y debe autenticarse con las credenciales de AWS y descargar el objeto durante el tiempo de ejecución del informe. El diseño del informe BIRT en sí mismo (imagen dinámica en una celda de la tabla) sigue siendo exactamente el mismo. Solo es necesario cambiar los guiones.

La solución MAS 9: obtención de imágenes desde S3/COS

La solución incluye dos áreas de secuencias de comandos en el diseñador de informes BIRT:

  • Inicializar el script - se ejecuta una vez cuando se inicia el informe; configura el cliente S3 mediante las propiedades del sistema Maximo.
  • Guión OnCreate - se ejecuta para cada fila de la imagen; obtiene la imagen de S3, la procesa y envía los bytes al elemento de imagen dinámica.

Los pasos de diseño del informe (crear un conjunto de datos a partir de docinfo, vincularlo a una tabla, insertar un elemento de imagen dinámica) siguen siendo los mismos que se describen en el blog original. Si aún no ha completado esos pasos, consulte los pasos 1 a 3 del guía original primero.

Implementación paso a paso

Paso 1: Crear el conjunto de datos

Al igual que antes, cree un conjunto de datos que obtenga el Nombre de URL de la docinfo objeto, filtrado según sus criterios (por ejemplo, pregunta de inspección específica o tipo de documento). El Nombre de URL La columna es lo que usarán los scripts para localizar la imagen en S3.

Paso 2: Enlazar el conjunto de datos e insertar una imagen dinámica

Crea tu tabla, vincúlala al conjunto de datos y coloca un elemento de imagen dentro de la celda correspondiente. Establezca el tipo de fuente de la imagen en «Imagen dinámica» — esto no ha cambiado con respecto a Maximo 7.6.

Paso 3: Añadir el script de inicialización

En el informe Inicializar sección de script, añada lo siguiente. Se ejecuta una vez al iniciar el informe, lee las credenciales de COS de las propiedades del sistema Maximo y crea un cliente S3 compartido:


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(); 

 


Nota: Las credenciales (mxe.cosaccesskey, mxe.cossecretkey, mxe.cossysbucket) se leen directamente desde las propiedades del sistema de Maximo, por lo que no es necesario codificar valores confidenciales en el informe.

Paso 4: Añadir el script onCreate

En el elemento Dynamic Image OnCreate script, añada lo siguiente. Esto se activa para cada fila, analiza la URI del COS, descarga la imagen, gestiona la conversión de formato, aplica la compresión JPEG y establece las dimensiones de la pantalla:

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(); 
    } 
} 

Paso 5: Vista previa e implementación

Obtenga una vista previa del informe en BIRT Designer para confirmar que las imágenes se representan correctamente. Una vez verificado, importe el informe a MAS y pruébelo generando un PDF comparándolo con una orden de trabajo o inspección que contenga fotos adjuntas.

Diferencias clave: Maximo 7.6 vs MAS 9

La migración de Maximo 7.6 a MARZO 9 introduce un cambio fundamental en la forma en que se almacenan los archivos adjuntos y se accede a ellos. Al pasar de un enfoque basado en archivos locales a una recuperación basada en S3/COS, los scripts que utilizan las imágenes dinámicas en los informes del BIRT deben actualizarse en consecuencia.

Con el script Initialize que gestiona la autenticación de S3 y el script OnCreate que gestiona la descarga de objetos y el procesamiento de imágenes, puede seguir entregando informes enriquecidos y mejorados con imágenes en MAS 9 con la misma eficacia que en 7.6.

Unlock the Ultimate Guide to IBM Maximo Application Suite (MAS)

Discover everything you need to know to modernize your asset management strategy.

Inside, you’ll learn:

  • What’s new in IBM Maximo Application Suite 9.0
  • Key differences between Maximo 7.6 and MAS
  • How AppPoints and OpenShift change the game
  • Industry use cases across energy, manufacturing, and transportation
  • Step-by-step guidance for upgrading and migration readiness
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