Wiki source code of Libertya REST API - Manual para desarrolladores
Last modified by admin on 2026/07/18 17:44
Show last authors
| author | version | line-number | content |
|---|---|---|---|
| 1 | = Libertya REST API {{id name="libertya-rest-api" /}}= | ||
| 2 | |||
| 3 | == Manual para desarrolladores {{id name="manual-para-desarrolladores" /}}== | ||
| 4 | |||
| 5 | = Indiced {{id name="indiced" /}}= | ||
| 6 | |||
| 7 | {{toc/}} | ||
| 8 | |||
| 9 | = Introducción {{id name="introducción" /}}= | ||
| 10 | |||
| 11 | El presente documento detalla los pasos para desarrollar y ampliar Libertya REST API, la cual fue desarrollada bajo [[Spring Boot>>https://spring.io/projects/spring-boot]] en conjunto con [[Swagger OpenAPI>>https://swagger.io/specification/]]. | ||
| 12 | |||
| 13 | = Fuentes {{id name="fuentes" /}}= | ||
| 14 | |||
| 15 | Los fuentes de LY REST API se alojan en el siguiente repositorio de github: | ||
| 16 | |||
| 17 | *. https://github.com/Disytel-Consulting-SA/lyrestapi | ||
| 18 | |||
| 19 | = Entorno de desarrollo {{id name="entorno-de-desarrollo" /}}= | ||
| 20 | |||
| 21 | Si bien pueden utilizarse otros entornos, el desarrollo de LY REST API se realizó utilizando **Intellij IDEA**. | ||
| 22 | |||
| 23 | El proyecto se apoya en las librerías **OXP.jar** y **OXPXLib.jar** según la definición de **build.grade**, con lo cual es necesario contar con la variable de entorno **OXP_HOME** definida previo inicio del IDE a fin de que encuentre dichas librerías para la compilación del proyecto. | ||
| 24 | |||
| 25 | def OXPLIBS = System.getenv(“OXP_HOME”)\\implementation files(“~$OXPLIBS/lib/OXP.jar”)\\implementation files(“~$OXPLIBS/lib/OXPXLib.jar”) | ||
| 26 | |||
| 27 | El proyecto requiere además **Java 8**. | ||
| 28 | |||
| 29 | = Generalidades para el desarrollo {{id name="generalidades-para-el-desarrollo" /}}= | ||
| 30 | |||
| 31 | == Definición de la API {{id name="definición-de-la-api" /}}== | ||
| 32 | |||
| 33 | === Definición principal {{id name="definición-principal" /}}=== | ||
| 34 | |||
| 35 | El archivo **src/main/resources/ly-rest-api.yaml** es el punto de inicio para la ampliacion de operaciones. En dicho archivo se definen los paths a los distintos archivos que contienen los end-points: | ||
| 36 | |||
| 37 | **paths**:\\/v1.0/products:\\~$ref: ./paths/products.yaml\\/v1.0/products/{id}:\\~$ref: ./paths/products_id.yaml\\/v1.0/bpartners:\\~$ref: ./paths/bpartners.yaml\\/v1.0/bpartners/{id}:\\~$ref: ./paths/bpartners_id.yaml\\/v1.0/invoices:\\~$ref: ./paths/invoices.yaml\\/v1.0/invoices/{id}:\\~$ref: ./paths/invoices_id.yaml\\/v1.0/invoices/{id}/process:\\~$ref: ./paths/invoices_id_process.yaml | ||
| 38 | |||
| 39 | En general, para un tipo de entidad tendremos 2 entradas, por ejemplo: | ||
| 40 | |||
| 41 | *. **/v1.0/products:** | ||
| 42 | **. products.yaml\\ | ||
| 43 | *. **/v1.0/products/{id}:** | ||
| 44 | **. producs_id.yaml | ||
| 45 | |||
| 46 | La primera entrada se encuentra relacionada con operaciones que no requieren indicar el identificador, como por ejemplo creación de una nueva entrada o bien listados. La segunda entrada sí requiere un identificador y se utiliza para operaciones como modificación, eliminación o recuperación de una entidad en particular. | ||
| 47 | |||
| 48 | **NOTA**: Existirá una tercera entrada en ciertos casos, para procesamiento de entidades de tipo documento (pedidos, facturas, remitos, etc.), por ejemplo: | ||
| 49 | |||
| 50 | *. **/v1.0/invoices/{id}/process:** | ||
| 51 | **. ~$ref: ./paths/invoices_id_process.yaml | ||
| 52 | |||
| 53 | === Definición de end-points {{id name="definición-de-end-points" /}}=== | ||
| 54 | |||
| 55 | Los archivos **src/main/resources/paths/*.yaml** contienen los endpoints para cada una de las entidades sobre las cuales operar, por ejemplo **bpartners.yaml** / **bpartners_id.yaml**: | ||
| 56 | |||
| 57 | **get**:\\tags:\\- “bpartner”\\summary: Recupera una entidad comercial en particular\\parameters:\\- name: id\\in: path\\description: ID de la entidad comercial\\required: true\\schema:\\type: integer\\description: Recupera la informacion de una entidad comercial en particular\\operationId: retrieveBPartner\\responses:\\“200”:\\description: OK\\content:\\application/json:\\schema:\\~$ref: ‘../model/bpartner.yaml#/components/schemas/BPartner’\\… | ||
| 58 | |||
| 59 | === Definición de schemas {{id name="definición-de-schemas" /}}=== | ||
| 60 | |||
| 61 | Los archivos **src/main/resources/model/*.yaml** contienen los schemas referenciados en los end-points y son autogenerados mediante un script (se detalla luego) basándose en los metadatos de **AD_Table**, **AD_Column**. | ||
| 62 | |||
| 63 | components:\\schemas:\\**BPartner**:\\type: object\\properties:\\ad_client_id:\\type: integer\\ad_componentobjectuid:\\type: string\\… | ||
| 64 | |||
| 65 | |||
| 66 | {{code}} | ||
| 67 | value: | ||
| 68 | type: string | ||
| 69 | {{/code}} | ||
| 70 | |||
| 71 | **NOTA**: Dentro de **src/main/resources/model** existen también los archivos ***_doc.yaml** (por ejemplo **invoice_doc.yaml** o **order_doc.yaml**), los cuales no son autogenerados. Estos archivos representan una estructura más amplia que una entidad, o sea un documento que abarca varias entidades. Por ejemplo una factura abarcará sus líneas y sus impuestos: | ||
| 72 | |||
| 73 | components:\\schemas:\\**InvoiceDocument**:\\type: object\\properties:\\**header**:\\~$ref: ‘../model/invoice.yaml#/components/schemas/Invoice’\\**lines**:\\type: array\\items:\\~$ref: ‘../model/invoiceline.yaml#/components/schemas/InvoiceLine’\\**taxes**:\\type: array\\items:\\~$ref: ‘../model/invoicetax.yaml#/components/schemas/InvoiceTax’ | ||
| 74 | |||
| 75 | Notar que la definición de **invoice_doc.yaml** se apoya en los archivos yaml de modelo autogenerados. | ||
| 76 | |||
| 77 | Adicionalmente, en **src/main/resources/patrh** existen los archivos ***_doc_process.yaml** para el procesado de estos documentos (completar, anular, revertir, cerrar, etc.). | ||
| 78 | |||
| 79 | put:\\tags:\\- “invoice”\\summary: Procesa una factura\\operationId: **processInvoice**\\parameters:\\- in: path\\name: **id**\\description: ID de la factura a procesar\\required: true\\schema:\\type: integer\\- in: query\\name: **action**\\required: true\\description: Accion a aplicar (completar, revertir, etc.)\\schema:\\type: string\\… | ||
| 80 | |||
| 81 | === Script generdor de schemas {{id name="script-generdor-de-schemas" /}}=== | ||
| 82 | |||
| 83 | El script **utils/genSchema.sh** es el encargado de (re)generar los archivos **yaml** descriptores del modelo ubicados en **src/main/resources/model**. | ||
| 84 | |||
| 85 | Es posible ampliar el apartado **#Scripts de generacion** con la/s nueva/s tabla/s que se requieran, por ejemplo: | ||
| 86 | |||
| 87 | generateSchema Currency C_Currency currency.yaml | ||
| 88 | |||
| 89 | En donde **Currency** es el nombre del schema a generar, **C_Currency** es el nombre de la tabla sobre la cual obtener la estructura a generar y **currency.yaml** es el nombre del archivo destino a crear. | ||
| 90 | |||
| 91 | Adicionalmente, es posible limitar las propiedades a incluir en el schema, indicando una lista de columnas relevantes a considerar (además de las obligatorias según **ismandatory** en **ad_column** para dichas columnas), e ignorar el resto. Para ésto debe incorporarse un cuarto argumento en la invocación con las columnas en cuestión: | ||
| 92 | |||
| 93 | generateSchema Currency C_Currency currency.yaml “(‘description’, ‘iseuro’, ‘wsfecode’)” | ||
| 94 | |||
| 95 | De no especificar la lista de columnas, **todas** las columnas serán consideradas, excepto las de tipo binarias (ver **genSchema.sql** para más detalles). | ||
| 96 | |||
| 97 | **IMPORTANTE**: Debe especificarse además los datos de la conexion a la base de datos en el apartado **# DB Connection**. | ||
| 98 | |||
| 99 | == Generación de clases mediante Swagger CodeGen {{id name="generación-de-clases-mediante-swagger-codegen" /}}== | ||
| 100 | |||
| 101 | El script **utils/genClasses.sh** es el encargado de generar las interfaces del package **org.libertya.api.stub.iface** (por ejemplo //org.libertya.api.stub.iface.ProductApi//) y las clases de modelo del package **org.libertya.api.stub.model** (por ejemplo //org.libertya.api.stub.model.Product//) a partir de las definiciones previamente especificadas en los archivos yaml (los definidos manualmente más los autogenerados con el script **genSchema.sh**). | ||
| 102 | |||
| 103 | Para facilitar el workflow de desarrollo, el script **genClasses.sh** directamente ejecuta **genSchema.sh** como primera actividad. | ||
| 104 | |||
| 105 | == Implementación de clases {{id name="implementación-de-clases" /}}== | ||
| 106 | |||
| 107 | Las clases a implementar para operaciones de tipo CRUD o procesamiento de documentos son básicamente 2 (o 3 si la entidad es un documento): | ||
| 108 | |||
| 109 | *. El repository, por ejemplo **org.libertya.api.repository.InvoiceRepository**\\ | ||
| 110 | *. El repository, por ejemplo **org.libertya.api.repository.InvoiceService** (si la entidad es un documento o si se requiere lógica adicional)\\ | ||
| 111 | *. El controller, por ejemplo **org.libertya.api.controller.InvoiceController** | ||
| 112 | |||
| 113 | Se debe implementar la interfaz generada a fin de implementar los Controllers correspondientes, los cuales recibirán y retornaran los tipos definidos en el modelo. Por ejemplo la clase **BPartnerController** implementa **BpartnerApi**, y en los distintos métodos se envía/reciben clases de tipo **org.libertya.api.stub.model.BPartner** (clase autogenerada). | ||
| 114 | |||
| 115 | = Ejemplo {{id name="ejemplo" /}}= | ||
| 116 | |||
| 117 | A modo de ejemplo se detalla el paso a paso para dar soporte a la gestión de remitos (InOuts), abarcando: | ||
| 118 | |||
| 119 | *. Creación\\ | ||
| 120 | *. Eliminación\\ | ||
| 121 | *. Modificación\\ | ||
| 122 | *. Recuperación\\ | ||
| 123 | *. Procesado | ||
| 124 | |||
| 125 | == Ampliación de paths principales {{id name="ampliación-de-paths-principales" /}}== | ||
| 126 | |||
| 127 | El primer paso es incluir a los nuevos paths relacionados con la gestión de remitos en el archivo **ly-rest-api.yaml**: | ||
| 128 | |||
| 129 | /v1.0/inouts:\\~$ref: ./paths/inouts.yaml\\/v1.0/inouts/{id}:\\~$ref: ./paths/inouts_id.yaml\\/v1.0/inouts/{id}/process:\\~$ref: ./paths/inouts_id_process.yaml | ||
| 130 | |||
| 131 | == Ampliación de endpoints {{id name="ampliación-de-endpoints" /}}== | ||
| 132 | |||
| 133 | Se deben incorporar los 2 o 3 archivos (si la entidad tiene lógica de documentos como es el caso de remitos) de definicion de operaciones: | ||
| 134 | |||
| 135 | *. **src/main/resources/paths/inouts.yaml** | ||
| 136 | **. Para listar o crear remitos (no requieren un id como parte del path)\\ | ||
| 137 | *. **src/main/resources/paths/inouts_id.yaml** | ||
| 138 | **. Para recuperar un remito o bien para modificar o eliminar un remito (requiere su id como parte del path)\\ | ||
| 139 | *. **src/main/resources/paths/inouts_id_process.yaml** | ||
| 140 | **. Para completar, anular, cerrar, etc. un remito (requiere su id como parte del path) | ||
| 141 | |||
| 142 | Por ejemplo, para **inouts.yaml** el end-point **GET** es el siguiente (ver contenidos completos en el proyecto): | ||
| 143 | |||
| 144 | get:\\tags:\\- “inout”\\summary: Retrieve inouts\\description: Retorna una lista de remitos\\operationId: getAllInOuts\\… | ||
| 145 | |||
| 146 | **Es importante respetar los tags en todos los casos dentro de las operaciones de los 3 archivos**, a fin de que cada entidad sea luego generada bajo su interfaz exclusiva correspondiente. | ||
| 147 | |||
| 148 | Las definiciones de estos archivos son similares, con lo cual pueden ser basados en otros ya creados, por ejemplo **orders.yaml**, **orders_id.yaml**, **orders_id_process.yaml**. Cabe destacar que ante el desarrollo inicial para una entidad dada, estos archivos referenciarán a schemas todavía no existentes dentro del directorio **src/main/resources/model**. La generación de estos archivos de detalla en el apartado a continuación. | ||
| 149 | |||
| 150 | == Ampliación del schema (autogenerado) {{id name="ampliación-del-schema-autogenerado" /}}== | ||
| 151 | |||
| 152 | Se debe incluir el modelo **InOut** en la nómina de esquemas basado en la información de **M_InOut**. De manera similar para **M_InOutLine**. En el archivo **genSchema.sh**, en el apartado **#Script de generacion** incorporar: | ||
| 153 | |||
| 154 | generateSchema InOut M_InOut inout.yaml\\generateSchema InOutLine M_InOutLine inoutline.yaml | ||
| 155 | |||
| 156 | Si se ejecuta **genSchema.sh** veremos que se crean los archivos **src/main/resources/model/inout.yaml** y **src/main/resources/model/inoutline.yaml** correspondientes: | ||
| 157 | |||
| 158 | components:\\schemas:\\InOut:\\type: object\\properties:\\ad_client_id:\\type: integer\\ad_org_id:\\type: integer | ||
| 159 | |||
| 160 | == Ampliación del schema (manual) {{id name="ampliación-del-schema-manual" /}}== | ||
| 161 | |||
| 162 | Para entidades de tipo documento, se debe crear manualmente el descriptor de schema **src/main/resources/model/inout_doc.yaml** el cual abarca la cabecera y las lineas: | ||
| 163 | |||
| 164 | components:\\schemas:\\**InOutDocument**:\\type: object\\properties:\\**header**:\\~$ref: ‘../model/inout.yaml#/components/schemas/InOut’\\**lines**:\\type: array\\items:\\~$ref: ‘../model/inoutline.yaml#/components/schemas/InOutLine’ | ||
| 165 | |||
| 166 | == Generación de clases {{id name="generación-de-clases" /}}== | ||
| 167 | |||
| 168 | Ejecutar **genClasses.sh**, el cual generará tanto las clases de modelo como la interfaz de la API para la entidad correspondiente: | ||
| 169 | |||
| 170 | *. Modelo | ||
| 171 | **. **org.libertya.api.stub.model.InOut**\\ | ||
| 172 | **. **org.libertya.api.stub.model.InOutLine**\\ | ||
| 173 | *. API | ||
| 174 | **. **org.libertya.api.stub.iface.InOutApi** | ||
| 175 | |||
| 176 | == Implementación de repository {{id name="implementación-de-repository" /}}== | ||
| 177 | |||
| 178 | Se debe implementar el repository correspondiente para los remitos, llamado **InOutRepository**. Todos los repositories deben extender de la clase **AbstractRepository**, la cual tiene las facilidades en común para todas las subclases. | ||
| 179 | |||
| 180 | Toda la lógica para la gestión de entidades y mapeo a PO radica en **AbstractRepository**. Por consiguiente, la clase **InOutRepository** es muy sencilla, solo es necesario indicar que es un **@Repository** e incorporar un constructor indicando el nombre de la tabla y el método para la instanciación de objetos de dicho tipo. | ||
| 181 | |||
| 182 | @Repository\\public class InOutRepository extends AbstractRepository { | ||
| 183 | |||
| 184 | public InOutRepository() {\\tableName = X_M_InOut.Table_Name;\\iface = InOut::new;\\}\\} | ||
| 185 | |||
| 186 | Los métodos retrieve (en todas sus variedades), delete, update, delete, process son gestionados por la superclase. | ||
| 187 | |||
| 188 | De manera similar, se debe implementar el repository InOutLineRepository: | ||
| 189 | |||
| 190 | @Repository\\public class InOutLineRepository extends AbstractRepository { | ||
| 191 | |||
| 192 | public InOutLineRepository() {\\tableName = X_M_InOutLine.Table_Name;\\iface = InOutLine::new;\\}\\} | ||
| 193 | |||
| 194 | == Implementación de service {{id name="implementación-de-service" /}}== | ||
| 195 | |||
| 196 | Las entidades que contemplan el scope de documento deberán además implementar la clase de servicio correspondiente para la gestión de procesado de documento, así como operaciones de recuperación del documento completo (abarcando por ejemplo sus líneas). En este caso, se deberá implementar **InOutService**, la cual deberá extender de **AbstractService**. | ||
| 197 | |||
| 198 | Los métodos a implementar son 3: | ||
| 199 | |||
| 200 | *. **getRepository()** el cual debe retornar el repositorio que gestiona la cabecera del documento (en este caso **InOutRepository**).\\ | ||
| 201 | *. **performCreate()** conteniendo la lógica de creación de la cabecera, líneas, etc.\\ | ||
| 202 | *. **performRetrieve()** conteniendo la lógica de recuperación de la cabecera, líneas, etc. | ||
| 203 | |||
| 204 | Por ejemplo, para la creacion de un documento de tipo remito: | ||
| 205 | |||
| 206 | @Override\\protected String **performCreate**(UserInfo info, Object document, String trxName) throws Exception {\\InOutDocument InOutDocument = (InOutDocument)document; | ||
| 207 | |||
| 208 | ~/~/ Cabecera\\Integer id = Integer.parseInt(inoutRepository.insert(info, InOutDocument.getHeader(), trxName)); | ||
| 209 | |||
| 210 | ~/~/ Lineas\\for (InOutLine InOutLine : getList(InOutDocument.getLines())) {\\InOutLine.setMInoutId(id);\\inoutLineLineRepository.insert(info, InOutLine, trxName);\\} | ||
| 211 | |||
| 212 | return Integer.toString(id);\\} | ||
| 213 | |||
| 214 | La superclase **AbstractService** se encargará de crear y commitear la transacción, y en caso de error realizar el rollback correspondiente. | ||
| 215 | |||
| 216 | == Implementación de controller {{id name="implementación-de-controller" /}}== | ||
| 217 | |||
| 218 | Se debe implementar el controller correspondiente para los remitos, llamado **InOutController**, el cual debe implementar **InoutApi** (autogenerada). **InOutController** interactua con **InOutRepository / InOutService** y debe extender de **AbstractController**, la cual tiene facilidades en común para todos los controllers. | ||
| 219 | |||
| 220 | El controller **InOutController** se apoyará tanto en **InOutRepository** como en **InOutService** a fin de responder a las operaciones add, delete, update, etc.. | ||
| 221 | |||
| 222 | @Controller\\@RequiredArgsConstructor\\public class InOutController extends AbstractController implements InoutApi { | ||
| 223 | |||
| 224 | private final HttpServletRequest request; | ||
| 225 | |||
| 226 | private final InOutRepository repository; | ||
| 227 | |||
| 228 | private final InOutService service; | ||
| 229 | |||
| 230 | @Override\\public ResponseEntity<String> **addInOut**(InOutDocument body) {\\return insertAction(request, (info) -> **service**.create(info, body));\\} | ||
| 231 | |||
| 232 | @Override\\public ResponseEntity<String> **deleteInOut**(Integer id) {\\return deleteAction(request, (info) -> **repository**.delete(info, id));\\}\\… | ||
| 233 | |||
| 234 | = Casos especiales {{id name="casos-especiales" /}}= | ||
| 235 | |||
| 236 | Ciertos circuitos requieren como entrada información completamente distinta a la que luego es almacenada en base de datos. El caso más común es el de OP/RC en donde se requiere la nómina de facturas a pagar y la nómina de pagos, sin información adicional, por ejemplo una estructura del tipo: | ||
| 237 | |||
| 238 | {\\“c_bpartner_id”: 1012142,\\“earlypayment”: false,\\“invoices”:\\[\\{\\“c_invoice_id”: “1022046”,\\“amount”: “1”\\}\\],\\“payments”:\\[\\{\\“c_pospaymentmedium_id”: “1010269”,\\“amount”: “1”,\\“c_payment_id”: “1012189”\\}\\]\\} | ||
| 239 | |||
| 240 | Si bien para las operaciones de recuperacion, eliminación, etc. las definiciones de modelo y clases autogeneradas son de utilidad, específicamente **para la generación de las OP/RC se requiere una estructura específica**. La misma se define bajo **model/allocation_new.yaml** y es referenciada para la operacion POST del endpoint de allocations. De esta manera es posible que “convivan” tanto el modelo autogenerado como incorporaciones adicionales específicas que sean requeridas. | ||
| 241 | |||
| 242 | = Testings de integración {{id name="testings-de-integración" /}}= | ||
| 243 | |||
| 244 | A fin de contar con una clase que automáticamente valide la correcta ejecución del código asociado al circuito implementado, es posible crear una clase que cuente con una serie de tests asociados. La clase **InOutIntegrationTests** extenderá de **CommonIntegrationTest**, y en ella deberán incorporase los distintos casos de pruebas, tales como creación de un remito, eliminación, modificación, etc. Por ejemplo un test para validar la correcta creación de un remito: | ||
| 245 | |||
| 246 | @Test\\@Order(1)\\void createInOutSouldReturnOK() throws Exception {\\ResponseEntity<String> response =\\restTemplate.exchange(getBaseURL(“v1.0/inouts”),\\HttpMethod.POST,\\new HttpEntity<>(getInOutContent(), getAuthHeaders()),\\String.class);\\System.out.println(response.getBody());\\assertThat(response.getStatusCode().toString()).contains(“200”);\\documentID = Integer.parseInt(response.getBody());\\assertThat(documentID>0);\\} | ||
| 247 | |||
| 248 | La superclase **CommonIntegrationTest** se encarga de la lógica en común a todos estos tipos de test como es la gestion del puerto para testing, la obtención del token, etc. | ||
| 249 | |||
| 250 | Luego pueden ejecutarse los tests creados a fin de validar su correcta ejecución. | ||
| 251 | |||
| 252 | [[image:image1.png]] | ||
| 253 | |||
| 254 | = Build del proyecto {{id name="build-del-proyecto" /}}= | ||
| 255 | |||
| 256 | Dentro de las tasks de gradle, ejecutar la task **build**. También se puede realizar desde terminal mediante el comando **//./gradlew build//**. | ||
| 257 | |||
| 258 | Esto generará el archivo **build/libs/lyrestapi-0.0.1-SNAPSHOT.jar** (o la versión que corresponda según la definición de version en **build.gradle**). | ||
| 259 | |||
| 260 | Notar que dentro del jar, en **/BOOT-INF/lib/** se encuentran las librerías **OXP.jar** y **OXPXLib.jar** utilizadas en el build del proyecto. Por consiguiente, en caso de actualizar la versión de Libertya CORE (o sus componentes), será necesario reemplazar estos archivos con las nuevas versiones. | ||
| 261 | |||
| 262 | **NOTA**: Tener en cuenta que el build disparará el test-set contenido en **src/test/java/oprg.libertya.api** lo cual puede demorar un tiempo considerable en ejecutar todas las pruebas. | ||
| 263 | |||
| 264 | == Release para LY CORE 22.0ar {{id name="release-para-ly-core-22.0ar" /}}== | ||
| 265 | |||
| 266 | LY REST API se apoya en ciertos cambios de CORE posteriores al release 22.0, con lo cual fue necesario realizar los siguientes pasos: | ||
| 267 | |||
| 268 | La generacion de **lyrestapi-1.0.0_for_LY22.0ar.jar** se realizó de la siguiente manera: | ||
| 269 | |||
| 270 | Tomar ServidorOXP_V22.0.zip, descomprimir. | ||
| 271 | |||
| 272 | Aplicar el patch **org.libertya.core.22.0.patches.a101ec1.99b34e5.jar**, conteniendo los siguientes commit IDs: | ||
| 273 | |||
| 274 | *. **a101ec1** (DocumentEngine)\\ | ||
| 275 | *. **99b34e5** (DB) | ||
| 276 | |||
| 277 | Reconfigurar la instancia ServidorOXP con dicho patch, lo cual generará el **OXP.jar** y **OXPXLib.jar** que el proyecto LYRESTAPI referencia. | ||
| 278 | |||
| 279 | Desde Intellij Idea, refrescar y buildear la app, lo cual genera el jar **lyrestapi-1.0.0.jar** generado en **build/libs** | ||
| 280 | |||
| 281 | Renombrado el jar a: **lyrestapi-1.0.0_for_LY22.0ar.jar** | ||
| 282 | |||
| 283 | **NOTA**: En caso de no aplicar los patches o de utilizar los binarios de una versión antigua o distinta a LY 22.0, la compilación puede fallar. Esto puede manifestarse por ejemplo con un error al querer compilar **ErrorController**, en donde se presenta el mensaje **Cannot resolve symbol ‘ERROR_STATUS_CODE’**. | ||
| 284 | |||
| 285 | **NOTA**: Si el build falla es probablEse que algún test no supere la validación. Puede deberse a que en la base de datos el período no esté abierto. Si la misma tiene control automático de período, entonces poner -9999 y 9999 en fecha hacia atras ya hacia adelante. | ||
| 286 | |||
| 287 | [[image:image2.png]] | ||
| 288 | |||
| 289 | == Consideraciones para LY CORE 26.0 o superiores {{id name="consideraciones-para-ly-core-26.0-o-superiores" /}}== | ||
| 290 | |||
| 291 | === Soporte Java 11 {{id name="soporte-java-11" /}}=== | ||
| 292 | |||
| 293 | Para versiones que se apoyen en una versión de Libertya que brinda soporte a **Java 11**, deberá realizarse la adecuación detallada a continuación. | ||
| 294 | |||
| 295 | La revisión **a0e93ef** de LY CORE incluye un conjunto de modificaciones para dar soporte a Java 11, entre ellas la inclusión de nuevas librerías de Jacorb para reemplazar módulos de Java EE y CORBA: | ||
| 296 | |||
| 297 | [[image:image3.png]] | ||
| 298 | |||
| 299 | Esto genera un conflicto con las librerías usadas en el proyecto LYRESTAPI, generando el siguiente mensaje de error: | ||
| 300 | |||
| 301 | java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. Either remove Logback or the competing implementation (class org.slf4j.impl.JDK14LoggerFactory loaded from file:/ServidorOXP/lib/OXPXLib.jar). If you are using WebLogic you will need to add ‘org.slf4j’ to prefer-application-packages in WEB-INF/weblogic.xml: org.slf4j.impl.JDK14LoggerFactory | ||
| 302 | |||
| 303 | La manera más sencilla de resolver este problema es simplemente modificar el archivo **OXPXLib.jar** que se está referenciando y eliminar el directorio **org/slf4j/impl**. | ||
| 304 | |||
| 305 | Tener en cuenta que la eliminación puede traer problemas con el META-INF/INDEX.LIST. Esto puede solucionarse eliminando también el index. Por ejemplo para incluir en un script: | ||
| 306 | |||
| 307 | |=zip -d OXPXLib.jar “org/slf4j/impl/*” zip -d OXPXLib.jar “META-INF/INDEX.LIST” | ||
| 308 | |||
| 309 | Una vez realizado esto, en Intellij Idea ir a **File → Reload All From Disk** para recargar los cambios en el entorno. De esta manera el error queda resuelto dado que ya no existirá el mencionado conflicto. | ||
| 310 | |||
| 311 | === Soporte Postgres 16 {{id name="soporte-postgres-16" /}}=== | ||
| 312 | |||
| 313 | Postgres 16 utiliza scram-sha-256 como método de encriptación, el cual no es soportado por versiones viejas de JDBC. Esto genera la imposibilidad de conectar contra una base de datos que **no** utilice trust como en el archivo **hba.conf**, bajo el mensaje de error: **psql: authentication method 10 not supported**. | ||
| 314 | |||
| 315 | La solución implica incorporar una versión reciente de JDBC, como por ejemplo la 42.7.7 en los binarios de LY CORE que están siendo referenciados por la API. El driver **postgresql.jar** descargado desde el sitio https://jdbc.postgresql.org/download/ debe ser ubicado en **/ServidorOXP/lib**, pisando la versión vieja y luego reconfigurar. | ||
| 316 | |||
| 317 | Si bien esta librería ya fue incorporada a los fuentes de LY CORE, versiones anteriores contendrán una versión desactualizada del JDBC y por lo tanto será necesario realizar los pasos aquí mencionados. | ||
| 318 | |||
| 319 | == Creacion de docker image {{id name="creacion-de-docker-image" /}}== | ||
| 320 | |||
| 321 | El proyecto cuenta con el script **DockerCreateImage.sh** que genera una imagen de la aplicación apoyada en **OpenJDK 8**. | ||
| 322 | |||
| 323 | usuario@pc-usuario:~~/workspace/org.libertya.api~$ **./DockerCreateImage.sh**\\BUILD SUCCESSFUL in 2s\\7 actionable tasks: 7 up-to-date\\[+] Building 2.0s (7/7) FINISHED\\=> [internal] load .dockerignore 0.1s\\=> => transferring context: 2B 0.0s\\=> [internal] load build definition from Dockerfile 0.1s\\=> => transferring dockerfile: 172B 0.0s\\=> [internal] load metadata for docker.io/library/openjdk:8-jdk-alpine 0.0s\\=> [internal] load build context 0.7s\\=> => transferring context: 67.80MB 0.6s\\=> [1/2] FROM docker.io/library/openjdk:8-jdk-alpine 0.1s\\=> [2/2] COPY build/libs/lyrestapi-1.0.0.jar lyrestapi-1.0.0.jar 0.6s\\=> exporting to image 0.5s\\=> => exporting layers 0.5s\\=> => writing image sha256:b155879ce2ab4dc1c89b6a287753435ba69aae268bc7c818a0e5bbce4e9192c3 0.0s\\=> => naming to docker.io/library/lyrestapi 0.0s | ||
| 324 | |||
| 325 | usuario@pc-usuario:~~/workspace/org.libertya.api~$ **docker images**\\REPOSITORY TAG IMAGE ID CREATED SIZE\\**lyrestapi** latest b155879ce2ab About a minute ago 173MB | ||
| 326 | |||
| 327 | = Uso {{id name="uso" /}}= | ||
| 328 | |||
| 329 | Ver el documento Libertya REST API - Manual de uso. |