package com.banesco.common.infraestructure.helpers; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Objects; import java.util.logging.Level; import java.util.logging.Logger; import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBElement; import jakarta.xml.bind.JAXBException; import jakarta.xml.bind.Marshaller; public class XmlHelper { private static final Logger logger = Logger.getLogger(XmlHelper.class.getName()); /** * Imprime el contenido XML de un objeto JAXBElement en el log. * Utiliza JAXB para serializar el objeto a XML y lo formatea para una mejor legibilidad. * * @param element El JAXBElement que contiene el objeto a serializar a XML. * @param traceId requestID. * @throws JAXBException Si ocurre un error durante la serialización JAXB. */ public static void printXml(JAXBElement element, String traceId) throws JAXBException { // Verifica si el elemento es nulo para evitar NullPointerException Objects.requireNonNull(element, "El JAXBElement no puede ser nulo."); // Obtiene el tipo declarado del elemento para crear el contexto JAXB. // Esto asegura que JAXB conozca la clase raíz del objeto que se va a serializar. Class declaredType = element.getDeclaredType(); // Crea una instancia de JAXBContext para el tipo declarado. // JAXBContext es costoso de crear, en aplicaciones de alto rendimiento // se suele cachear o reutilizar. Para este caso de log, es aceptable crearlo aquí. JAXBContext ctx = JAXBContext.newInstance(declaredType); // Crea un Marshaller, que es responsable de convertir objetos Java a XML. Marshaller marshaller = ctx.createMarshaller(); // Configura la propiedad para que el XML de salida esté formateado (indentado). // Esto hace que el XML sea mucho más legible en los logs. marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); // Configura la propiedad para que el XML no incluya la declaración XML (). // Esto puede ser útil si solo quieres el contenido XML puro en el log, // pero a menudo es mejor dejarlo si quieres un XML completo y válido. // marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE); // Usa ByteArrayOutputStream para capturar la salida XML en memoria. // Esto es necesario porque Marshaller escribe en un OutputStream, // y necesitamos obtener el String resultante para el log. try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { // Realiza la serialización del JAXBElement al OutputStream. marshaller.marshal(element, outputStream); // Convierte el contenido del ByteArrayOutputStream a un String. // Es crucial especificar la codificación (UTF-8 es lo más común) // para asegurar que los caracteres se interpreten correctamente. String xmlString = outputStream.toString(StandardCharsets.UTF_8.name()); // Loggea el XML generado. logger.log(Level.INFO, traceId + " - XML del servicio SOAP:\n{0}", xmlString); } catch (IOException e) { // Manejo de excepción si hay un problema con el ByteArrayOutputStream (poco probable en este caso). logger.log(Level.SEVERE, "Error al procesar el OutputStream para el XML", e); } } }