¿Cómo generar archivos de configuración Spring XMP mediante programación?

Planteamiento del problema

Como todos sabemos, en una aplicación Spring proporcionamos información de configuración a través de ‘ApplicationContext’. Spring Framework proporciona varias clases que implementan esta interfaz y nos ayudan a usar la información de configuración en las aplicaciones, y ClassPathXmlApplicationContext es una de ellas. Por lo general, en este caso, todas las definiciones de beans se configuran en un solo archivo xml independiente, comúnmente denominado ‘application-context.xml’.
En estructuras de proyectos más grandes, la mejor práctica es mantener varios archivos de configuración de resortes para facilitar el mantenimiento y la modularidad. En ese caso, lo mejor que puede hacer es organizar todos los archivos de configuración de Spring Bean en un solo archivo XML e importar todos los archivos dentro de él. Además, en el contexto de la aplicación, cargamos este único archivo xml.

Ahora, ¿qué sucede si la cantidad de archivos de configuración que se crearán es demasiado grande? Digamos, por ejemplo, ¿cerca de 100 o más?
¡Eso sí que es un trabajo monótono y lento! Es hora de encontrar un camino para automatizar este proceso.
Pensemos en un escenario en el que tenemos todos los datos necesarios en una fuente externa, por ejemplo, una hoja de Excel. Ahora necesitamos leer los datos de la hoja y generar cerca de 100 archivos de configuración de primavera de forma espontánea.

Cómo automatizar este proceso: JAXB al rescate.

JAXB tiene un compilador vinculante. El compilador de vinculación de esquemas JAXB XJC transforma, o vincula, un esquema XML de origen a un conjunto de clases de contenido JAXB en el lenguaje de programación Java.

  1. Busque el esquema xml al que se debe hacer referencia en el xml que se va a generar: http://www.springframework.org/schema/beans/spring-beans-3.0.xsd.
  2. Presione esta URL en el navegador para obtener el xsd. Ahora guárdelo en algún lugar (como spring.xsd).
  3. Descargue el paquete jaxbri y configure la variable de ruta del entorno. En el caso de proyectos maven, incluya dependencias para jaxb-ri y jaxb-core.
  4. Ejecute el comando xjc.exe spring.xsd, desde la carpeta donde se encuentra spring.xsd.
    Esto generaría las clases asociadas al xsd.

¿Qué se debe hacer si se produce el error «La propiedad ya está definida» al ejecutar el comando?

Es probable que obtenga una excepción que diga «La propiedad ya está definida», como se muestra en la siguiente captura de pantalla. Si es así, el problema se puede resolver creando un archivo de vinculación para anular las propiedades para las que se lanzó la excepción.
excepción

Carpeta de encuadernación
spring25

Use el siguiente comando para analizar el esquema y generar las clases:

xjc -b spring25.xjb -verbose -xmlschema
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

Clases generadas
org

Ahora cree una instancia de Bean y ordénela. Esto generaría un archivo xml con la salida requerida.

Código de muestra
Nota: la clase de prueba se crea en org\springframework\schema\beans.

package org.springframework.schema.beans;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URISyntaxException;
import java.util.ArrayList;
  
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.namespace.QName;
  
import org.springframework.util.CollectionUtils;
  
import com.hrb.leap.bean.SpringConfigGenerator;
  
public class Test 
{
    public static void main(String[] args) throws JAXBException 
    {
        ObjectFactory factory = new ObjectFactory();
        JAXBContext context = JAXBContext.newInstance("org.springframework.schema.beans");
          
        /*
        * Create the root element 'Beans'
        * Set the required schema properties
        */
        Beans rootElement = factory.createBeans();
        rootElement.getOtherAttributes().put(new QName
        ("xmlns:xsi"), "http://www.w3.org/2001/XMLSchema-instance");
        rootElement.getOtherAttributes().put(new QName
        ("xsi:schemaLocation"), 
        "http://www.springframework.org/schema/beans spring-beans-3.2.xsd");
          
        /*
        * How to import resources
        * How to define list of reference beans
        */
        java.util.List<String> resources = new ArrayList<>();
        resources.add("ResourceOne");
        resources.add("ResourceTwo");
        resources.add("ResourceThree");
          
        resources.forEach(resourceName -> 
        {
            Import importResource = new Import();
            importResource.setResource(resourceName+".xml");
            rootElement.getImportOrAliasOrBean().add(importResource);
        });
          
        Bean bean = factory.createBean();
        bean.setId("id");
        bean.setClazz("java.util.ArrayList");
        if (!CollectionUtils.isEmpty(resources)) 
        {
            ConstructorArg constructorArgs = factory.createConstructorArg();
            org.springframework.schema.beans.List listOfResources =
                    new org.springframework.schema.beans.List();
              
            resources.forEach(referenceFormName -> 
            {
                Ref refBean = new Ref();
                refBean.setBean(referenceFormName);
                listOfResources.getBeanOrRefOrIdref().add(refBean);
            });
            constructorArgs.setList(listOfResources);
            bean.getMetaOrConstructorArgOrProperty().add(constructorArgs);
        }
        rootElement.getImportOrAliasOrBean().add(bean);
          
        /*
        * Sample bean definition to show how to store
        list of values as a property
        */
            Bean simpleBean = factory.createBean();
            simpleBean.setId("SimpleBean");
            simpleBean.setClazz("com.packagename.ClassName");
              
            PropertyType firstProperty= factory.createPropertyType();
            firstProperty.setName("listOfValuesDemo");
              
            java.util.List<String> listOfValues = new ArrayList<>();
            listOfValues.add("ValueOne");
            listOfValues.add("ValueTwo");
            listOfValues.add("ValueThree");
              
            org.springframework.schema.beans.List listToStoreValues 
                                = new org.springframework.schema.beans.List();
            listOfValues.forEach(name ->
            {
                Value value = factory.createValue();
                value.getContent().add(name);
                listToStoreValues.getBeanOrRefOrIdref().add(value);
            });
              
            firstProperty.setList(listToStoreValues);
              
            //Add the property to the bean.
            simpleBean.getMetaOrConstructorArgOrProperty().add
                            (factory.createProperty(firstProperty));
              
            // Add the bean under the root element 'beans'
            rootElement.getImportOrAliasOrBean().add(simpleBean);
              
            Marshaller marshaller = context.createMarshaller();
            marshaller.setProperty("jaxb.formatted.output",Boolean.TRUE);
            createXmlConfiguration(marshaller , "output", rootElement);
    }
      
    /*
    * Method create the xml under the 'src/main/resources' 
    folder in the project.
    */
    public static void createXmlConfiguration (Marshaller marshaller ,
                                String fileName, Beans rootElement) 
                                {
        try
        {
            java.net.URL url = SpringConfigGenerator.class.getResource("/");
            File fullPathToSubfolder = new File(url.toURI()).getAbsoluteFile();
            String projectFolder = 
                        fullPathToSubfolder.getAbsolutePath().split("target")[0];
              
            // TODO - Destination folder to be configured
            File outputFile = new File(projectFolder 
                            + "src/main/resources/" + "/"+fileName+".xml");
          
            if (!outputFile.exists()) 
            {
                outputFile.createNewFile();
            }
            OutputStream os = new FileOutputStream(outputFile);
            marshaller.marshal(rootElement, os);
        } 
          
        catch (URISyntaxException uriException) 
        {
              
        } 
          
        catch (IOException ioException) 
        {
              
        } 
          
        catch (JAXBException jaxbException) 
        {
              
        }
          
    }
}

Salida
Salida

Siga los pasos a continuación para ver la salida de muestra:

  1. Presione la URL del esquema en el navegador para obtener el xsd. Ahora guárdelo en alguna ubicación (por ejemplo: – spring.xsd).
  2. Descargue el paquete jaxbri y configure la variable de ruta del entorno.
  3. Establezca classpath de las bibliotecas jaxb y la ruta actual (punto) como ejemplo (haga este símbolo del sistema o ecualizador en IDE)
    set classpath=C:\folder_name\jaxb-ri\lib;.;
  4. Después de extraer el comando adjunto a una carpeta, ejecute debajo del comando (desde la carpeta extraída en cmd), compile la clase ‘Prueba’.
    javac org\springframework\schema\beans\Test.java
  5. Finalmente ejecute el programa.
    java org.springframework.schema.beans.Test

    Nota: – La salida se imprimirá en la consola, si ‘createXmlConfiguration(marshaller, «output», rootElement);’ se reemplaza por ‘marshaller.marshal(rootElement, System.out);’

Ventajas

  1.  El esfuerzo se reduce considerablemente. Una sola persona puede tardar un mínimo de 20-25 días en configurar cerca de 85 archivos (considerando 9 horas/día), serían 225 horas. La herramienta anterior tardaría menos de 3 segundos en hacerlo.
  2. Si hay que realizar cambios menores de configuración en el futuro, podemos tomar el archivo específico solo y hacer las correcciones.

Enfoque alternativo
Si el número de archivos de configuración es muy inferior, podemos intentar cargar el contexto con todas las definiciones de bean sobre la marcha, sin generar los archivos xml físicos. Esto se puede lograr cargando el contexto de primavera mediante programación y ejecutando la aplicación cuando sea necesario.

inconvenientes

  1.  Alto consumo de memoria
  2. Rendimiento bajo
  3. Un error menor en la fuente de datos tendría un gran impacto.
  4. Arriesgado de ejecutar en un entorno de producción, sobre la marcha.
  5. No es un enfoque recomendado, si la fuente de datos permanece casi intacta
  6. Será difícil de solucionar.

Este artículo es una contribución de Sridevi Sarath (desarrollador sénior de software en UST Global) . Si le gusta GeeksforGeeks y le gustaría contribuir, también puede escribir un artículo usando contribuya.geeksforgeeks.org o envíe su artículo por correo a contribuya@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.

Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *