WebSphere Commerce – Management Center: Nuevo tool
por Rúnar Sverrisson, 3/26/2020, 12:47:08 PMEmpezaremos dando una rápida visión general de lo que es el Centro de Gestión de la WCS y cómo funciona antes de pasar al tema principal de este artículo: Explicar con un ejemplo cómo una nueva herramienta personalizada puede ser añadida al Centro de Gestión. Todo el código relevante para la herramienta se puede encontrar en GitHub.
Descripción general del Centro de Gestión de WebSphere
El Centro de Gestión de IBM para WebSphere Commerce, o simplemente Centro de Gestión es una colección de herramientas que apoyan la gestión de la tienda, la comercialización y las tareas de marketing para el usuario empresarial. Viene con varias herramientas listas para usar:
- Herramienta de catálogos
- Herramienta de promoción
- Herramienta de marketing
- Herramienta de activos
- Herramienta de cuotas
- Herramienta de gestión de la tienda
- Filtro de catálogo y herramienta de precios
- Herramienta de gestión del espacio de trabajo
- Compositor de Comercio
Vea los detalles sobre las herramientas.
Ciertos aspectos de estas herramientas pueden ser personalizados, pero no entraremos en eso aquí. Antes de sumergirnos en la creación de una nueva herramienta consideremos brevemente cómo funciona el Centro de Gestión. En el Centro de Conocimientos de IBM hay varios artículos que discuten los detalles técnicos del marco del Centro de Gestión.
No nos adentraremos aquí, sino que daremos una visión general simplificada de cómo funciona una herramienta y luego iremos a través de un ejemplo para crear una nueva herramienta.
En esencia, una herramienta del Centro de Gestión no es más que una colección de archivos XML. En estos archivos XML (o sólo un único archivo XML) definimos diferentes objetos que nuestra herramienta utilizará.
Hay varios tipos de objetos diferentes que sirven para distintos propósitos. Además, se pueden definir servicios en los objetos que pueden ser asignados a un servicio REST o a un comando. La información que se mostrará en el área de trabajo principal de la consola del centro de gestión será el resultado de una llamada de servicio.
El servicio regresará con una respuesta XML, que será mapeada al objeto apropiado y posteriormente mostrada en consecuencia.
Creación de una herramienta personalizada
Queremos crear una herramienta personalizada que pueda integrarse con un servidor de Jenkins. La herramienta debería ser capaz de mostrar una lista de trabajos de Jenkins y ejecutar la construcción de trabajos.
La idea es crear un comando personalizado que se comunique con Jenkins. Este comando se ejecutará desde el Centro de Gestión y devolverá la respuesta de Jenkins de manera que el Centro de Gestión pueda entender y mostrar en el área de trabajo principal de la consola del Centro de Gestión.
Los archivos XML que definen las herramientas del Centro de Gestión viven en el proyecto LOBTools: LOBTools/WebContent/WEB-INF/src/xml.
Las herramientas estándar listas para usar se encuentran en la subcarpeta de comercio. Colocaremos la nueva herramienta personalizada en una nueva subcarpeta llamada "orienteado/integración".
Para simplificar, mantendremos toda la definición de nuestra herramienta en un solo archivo XML. La definición de una herramienta puede ser dividida en muchos archivos XML diferentes, como se puede ver al explorar las herramientas estándar.
Cuando la complejidad de la herramienta aumenta y es necesario definir más objetos, es aconsejable dividir la definición como lo hacen las herramientas estándar.
Definiciones de objetos
El componente fundamental de una herramienta del Centro de Gestión es el BusinessObjectEditor. Soporta varias de las funcionalidades de la consola de Management Center.
Dentro del elemento BusinessObjectEditor necesitamos varias cosas:
- ObjectFilterType: Filtra los objetos que son visibles en la vista del Explorador. Sólo queremos que los objetos de tipo JenkinsTop sean visibles en el Explorer, así que los filtramos. Si quisiéramos otros tipos de objetos también, podríamos añadirlos al filtro.
- Definición de ObjetoTop: El objeto raíz que define el árbol de navegación en la vista del Explorador. El elemento Xml define la estructura del árbol que queremos crear. Sólo queremos tener un nodo del tipo JenkinsTop.
- OrganizationalObjectDefinition: Un objeto que es usado por el TopObjectDefinition para crear el árbol de navegación. Aquí definimos el objeto JenkinsTop al que hicimos referencia anteriormente. En este objeto definimos un GetChildrenService que obtendrá la lista de trabajos de Jenkins. Para listar estos objetos en el área de trabajo principal necesitamos definir una NavigationListDefinition que le dirá al Centro de Administración cómo visualizar los objetos. La definición de la lista depende de los objetos creados fuera del BusinessObjectEditor.
- PrimaryObjectDefinition: Este es el objeto que lleva la cuenta de los datos con los que estamos trabajando. Una instancia de este objeto representará un trabajo de Jenkins. No definimos el objeto aquí, sino que hacemos referencia a una definición base.
<BusinessObjectEditor definitionName="cmc/orienteed/integration/IntegrationTool" explorerFilterTypes="Jenkins" displayName="Integration Tool" showStorePreview="false" showStoreSelection="false" showUtilitiesView="false"> <ObjectTypeFilter displayName="Jenkins" filterType="Jenkins" objectTypes="JenkinsTop"/> <TopObjectDefinition> <Xml name="template"> <object objectType="JenkinsTop"/> </Xml> </TopObjectDefinition> <OrganizationalObjectDefinition displayName="Jenkins" objectType="JenkinsTop"> <GetChildrenService url="/cmc/integration/jenkins/jobList"> <ServiceParam name="storeId"/> </GetChildrenService> <NavigationListDefinition definitionName="cmc/orienteed/integration/JenkinsChildList" displayName="Jenkins Job List" listDefinition="cmc/orienteed/integration/JenkinsListEditor" listTitle="Job List"/> </OrganizationalObjectDefinition> <PrimaryObjectDefinition baseDefinition="cmc/orienteed/integration/JenkinsPrimaryObjectDefinition" creatable="true"/> </BusinessObjectEditor>
En los dos últimos puntos de la lista anterior, hemos hecho referencia a otras definiciones de objetos que se definen fuera del BusinessObjectEditor:
- Definición de ObjetoPrimario: Esta es la definición base del objeto primario que queremos definir. Definimos los dos servicios que necesitamos y los parámetros que debemos pasarles. Los servicios nos permitirán refrescar un objeto y construir el correspondiente trabajo de Jenkins. El RefreshService se ejecuta cuando se pulsa el botón de refresco (mientras el objeto está seleccionado). El CustomService se ejecuta cuando se hace clic en el botón de construcción personalizada de Jenkins. Ambos botones están en la barra de herramientas del Centro de Administración. Para mostrar el icono de construcción personalizada de Jenkins, definimos un elemento de imagen que apunta a la ubicación de la imagen.
- ChildListEditor y ObjectGrid: Estos dos objetos se utilizan para definir la vista de lista que creamos para mostrar la lista de trabajos de Jenkins en el área de trabajo principal. El ChildListEditor define el tipo de objeto que la lista espera, mientras que el objeto ObjectGrid define la estructura de la lista actual (como las columnas y los datos a mostrar).
<PrimaryObjectDefinition definitionName="cmc/orienteed/integration/JenkinsPrimaryObjectDefinition" objectType="Jenkins" idProperty="integrationId" displayNameProperty="jenkinsName" propertiesDefinition="cmc/orienteed/integration/JenkinsProperties" initializeObjectStoreId="false"> <RefreshService url="/cmc/integration/jenkins/refresh"> <ServiceParam name="jobName" propertyName="jobName"/> <ServiceParam name="storeId"/> </RefreshService> <CustomService url="/cmc/integration/jenkins/build" displayName="Build job" toolbarIcon="jenkinsBuild"> <ServiceParam name="jobName" propertyName="jobName"/> <ServiceParam name="storeId"/> </CustomService> </PrimaryObjectDefinition> <Image name="jenkinsBuild" src="/images/orienteed/integration/resources/jenkins_build.png"/> <ChildListEditor definitionName="cmc/orienteed/integration/JenkinsListEditor" listDefinition="cmc/orienteed/integration/JenkinsGrid" objectTypes="Jenkins"/> <ObjectGrid definitionName="cmc/orienteed/integration/JenkinsGrid"> <GridText editable="false" name="color" propertyName="color" text="Color" width="80"/> <GridText editable="false" name="jobName" propertyName="jobName" text="Job Name" width="350"/> <GridText editable="false" name="lastBuild" propertyName="lastBuild" text="Last Build" width="350"/> <GridText editable="false" name="lastDuration" propertyName="lastDuration" text="Last Duration" width="350"/> <GridText editable="false" name="lastResult" propertyName="lastResult" text="Last Result" width="350"/> </ObjectGrid>
El último objeto que definimos para la herramienta es un objeto de propiedades para el objeto primario. Ya hemos referenciado este objeto en la Definición de ObjetoPrimario.
- ObjetoPropiedades: Este objeto define el objeto de propiedades que enlazamos con nuestro objeto primario. Define qué propiedades tendrá el objeto de trabajo Jenkins.
<ObjectProperties definitionName="cmc/orienteed/integration/JenkinsProperties"> <PropertyPane> <PropertyGroup groupTitle="General Job Properties" open="true"> <PropertyViewLongText promptText="Color" propertyName="color" required="true"/> <PropertyViewLongText promptText="Job Name" propertyName="jobName" required="true"/> <PropertyViewLongText promptText="URL" propertyName="integrationId" required="true"/> </PropertyGroup> <PropertyGroup groupTitle="Last Build Information" open="false"> <PropertyViewLongText promptText="Last Build" propertyName="lastBuild" required="false"/> <PropertyViewLongText promptText="Last Duration" propertyName="lastDuration" required="false"/> <PropertyViewLongText promptText="Last Result" propertyName="lastResult" required="false"/> </PropertyGroup> <PropertyGroup groupTitle="Last Build Console Log"> <PropertyViewLongText promptText="Last Console Log" propertyName="lastConsoleLog" required="false"/> </PropertyGroup> </PropertyPane> </ObjectProperties>
Definiciones de servicio
Para que la herramienta sea funcional necesitamos definir los servicios que hemos declarado en la definición XML anterior. Hemos definido tres servicios, uno en la Definición de Objeto Organizacional y dos en la Definición de Objeto Primario. Respectivamente, esos son:
- GetChildrenService: Este servicio obtiene la lista de trabajos del servidor Jenkins ejecutando un comando personalizado. Se activa cuando se selecciona el nodo Jenkins en la vista del Explorador, o cuando se actualiza la lista. El comando personalizado consultará al servidor Jenkins para una lista de trabajos. La respuesta será analizada por el Centro de Administración y creará los objetos primarios correspondientes.
- RefreshService: Este servicio se ejecuta cuando un objeto Jenkins es seleccionado y se hace clic en el botón de actualización. Funciona básicamente de la misma manera que el servicio GetChildrenService, excepto que sólo pide información sobre el trabajo específico que se selecciona.
- Servicio personalizado: Este servicio se activa al hacer clic en un botón personalizado de la barra de herramientas. Envía una solicitud al servidor de Jenkins para construir el trabajo seleccionado. El servidor de Jenkins no responde con ninguna información que el Centro de Administración necesite analizar, sólo un estado de si la solicitud de construcción fue creada con éxito o no.
El Centro de Gestión utiliza el marco de Spring para gestionar las llamadas de servicio. Tenemos que agregar frijoles al archivo de configuración /LOBTools/WebContent/WEB-INF/spring-extension.xml para los servicios que queremos definir. Necesitamos dos bean, ya que el GetChildrenService y el RefreshService usarán el mismo bean.
<bean id="/integration/jenkins/jobList" class="com.ibm.commerce.foundation.internal.client.lobtools.controllers.ControllerCommandController"> <property name="commandInterface" value="com.orienteed.commerce.integration.commands.IntegrationJenkinsCmd" /> <property name="defaultParameters"> <props> <prop key="function">joblist</prop> </props> </property> <property name="contextParameters"> <props> <prop key="storeId">storeId</prop> </props> </property> <property name="successView" value="/jsp/orienteed/integration/JenkinsJobList.jsp" /> </bean>
Nótese que al declarar los servicios (en la definición de la herramienta), necesitamos referirnos al frijol que invocará y la identificación del bean debe ser precedida por '/cmc'.
Especificamos los parámetros que se pasarán al comando. Podemos pasar tanto parámetros estáticos que se definen en el XML, como dinámicos que se especifican en la declaración del servicio. Utilizamos la propiedad defaultParameters para pasar los parámetros estáticos y los contextParameters de los dinámicos.
Especificamos el comando que queremos ejecutar y el postprocesamiento (si lo hay) que se hará después de que el comando se haya ejecutado. Para el frijol que obtendrá la información de Jenkins, necesitamos analizar la respuesta de Jenkins a los objetos del Centro de Administración. Hacemos eso definiendo una vista de éxito. Este es un archivo jsp que mapeará la respuesta XML de Jenkins al objeto primario de Jenkins.
La última pieza que falta antes de que nuestra nueva herramienta personalizada sea completamente funcional, es implementar el comando personalizado que usarán los frijoles. Crearemos un solo comando para que ambos frijoles usen y distingan la funcionalidad pasando diferentes parámetros al comando. No entraremos en detalles aquí sobre cómo crear un comando personalizado en WebSphere Commerce, pero observamos que todo el código relacionado con esta herramienta se puede encontrar en GitHub.
Conclusión
Hemos pasado por el proceso de añadir una nueva herramienta personalizada al Centro de Gestión y hemos explicado lo que se necesita para ponerlo en marcha. Concluiremos este artículo con algunos consejos y trucos que pueden ayudar a desarrollar personalizaciones para el Centro de administración:
Ejecutar el servidor de pruebas en modo de depuración, para que ciertos cambios de código puedan ser intercambiados en caliente sin necesidad de reiniciar.
Los cambios en los archivos de configuración XML pueden realizarse cerrando el Centro de Administración y volviéndolo a abrir después de limpiar los cachés en el navegador. No es necesario volver a publicarlo.
Empieza de forma sencilla! Consigue una herramienta simple (como la que se implementa aquí) para trabajar y trata de entender la estructura de la herramienta. Luego pasa a agregarle complejidad a la herramienta. Las herramientas estándar completas son muy complejas y es difícil tener una visión general de cómo funcionan, ya que la definición de cada herramienta se divide en muchos archivos XML diferentes.
Al abrir el Centro de Administración, agregue &logger.display=true al URL para agregar una herramienta de registro al Centro de Administración. Abra la herramienta de registro y active los registros necesarios. Para el registro del lado del servidor, considere agregar com.ibm.commerce.lobtools.*=all: com.ibm.commerce.foundation.*=all al rastreo. Tenga en cuenta que esto puede ralentizar considerablemente al Centro de Administración.
Puede ser útil editar archivos XML restringidos mientras se depura un problema en el desarrollo. Sólo recuerda revertir cualquier cambio en los archivos XML restringidos.
Por ejemplo, en commerce/shell/foundation/restricted/Service.xml, nos pareció útil editar la función handleResponse y añadir un registro adicional para ver exactamente qué XML estaba recibiendo.
Por último, pero no por ello menos importante, indagar en el Centro de Conocimientos de IBM y obtener una comprensión fundamental de la arquitectura del Centro de Gestión y cómo se estructura una herramienta.
Línks útiles
GitHub: https://github.com/orienteed/wcs-to-jenkins
Descripción de out-of-the-box tools: https://www.ibm.com/support/knowledgecenter/en/SSZLC2_8.0.0/com.ibm.commerce.management-center.doc/concepts/ctfcmc.htm)
Management Center framework: