Las normas expuestas son de obligado cumplimiento. La STIC podrá estudiar los casos excepcionales los cuales serán gestionados a través de los responsables del proyecto correspondiente y autorizados por el Área de Gobernanza de la STIC. Asimismo cualquier aspecto no recogido en estas normas deberá regirse en primera instancia por las guías técnicas correspondientes al esquema nacional de seguridad y esquema nacional de interoperabilidad según correspondencia y en su defecto a los marcos normativos y de desarrollo software establecidos por la Junta de Andalucía, debiendo ser puesto de manifiesto ante la STIC.
La STIC se reserva el derecho a la modificación de la norma sin previo aviso, tras lo cual, notificará del cambio a los actores implicados para su adopción inmediata según la planificación de cada proyecto.
En el caso de que algún actor considere conveniente y/o necesario el incumplimiento de alguna de las normas y/o recomendaciones, deberá aportar previamente la correspondiente justificación fehaciente documentada de la solución alternativa propuesta, así como toda aquella documentación que le sea requerida por la STIC para proceder a su validación técnica.
Los cambios en la normativa vendrán acompañados de un registro de las modificaciones. De este modo se podrá realizar un seguimiento y consultar su evolución. Ordenándose de mas recientes a menos recientes, prestando especial cuidado a las cabezeras de la tablas dónde se indican las fechas de entrada en vigor y versión.
Versión
v01r1
6Fecha publicación
Fecha entrada en vigor
Alcance
Versión inicial sobre el componente que permite la integración con Estructura fácilmente
1. Introducción
En el presente documento se presenta la librería "estructuraApiClient", librería Java desarrollada por el SAS para facilitar el acceso a la información de la aplicación Estructura por terceras aplicaciones desarrolladas dentro de la organización.
Con esta librería los proveedores podrán abstraerse de los mecanismos de conexión existentes actualmente con la aplicación Estructura, facilitando considerablemente el acceso a la información de la misma y, lo que es más importante, conseguir desacoplar los aplicativos finales de Estructura, permitiendo que en un futuro Estructura pueda evolucionar sin impactar en el conjunto de aplicaciones que hacen uso de la misma.
Versión 2.2.1: Fix para nucleos de localidad nulos.
Versión 2.2.0: Se añaden servicios para la consulta de códigos postales, localidades, paises y vias.
Versión 2.1.1.1: Cambios menores
Versión 2.1.0.1: Añadido servicio para consulta de Dispositivos de Apoyo
Servicio añadido: DispositivoApoyoService
public FutureTask<DispositivoApoyo> getDispositivoApoyoByCodigo(Context context, String codigo);
public FutureTask<List<DispositivoApoyo>> getDispositivosApoyo(Context context);
public FutureTask<List<DispositivoApoyo>> getDispositivosApoyoByCentroAPActividad(Context context, String codigoCentroAP);
public FutureTask<List<DispositivoApoyo>> getDispositivosApoyoByCentroAPSede(Context context, String codigoCentroAP);
public FutureTask<List<DispositivoApoyo>> getDispositivosApoyoByNombre(Context context, String nombre);
Añadida propiedad tipoCentro a la entidad CentroEspecializada, necesario para especificar el tipo de centro consultado
Versión 2.0.0.1: Acceso a información de Estructura
Cambios realizados
Se dividen los servicios existentes en la API para ofrecer servicios más cohesionados y fáciles de mantener.
Se modifica la filosofía de uso de la librería, se publican todos los servicios haciendo uso de Futures, los cuales permiten realizar programación multihilo que mejoren el rendimiento del sistema.
Se crea el objeto EstructuraApiConfig como contenedor de configuración de parámetros de la librería.
Servicios ofrecidos
Area Conocimiento
public FutureTask<AreaConocimiento> getAreaConocimientoByCodigo(Context context, String codigo);
public FutureTask<List<AreaConocimiento>> getAreasConocimiento(Context context);
public FutureTask<List<AreaConocimiento>> getAreasConocimientoByNombre(Context context, String nombre);
Area Hospitalaria
public FutureTask<List<AreaHospitalaria>> getAreasHospitalarias(Context context, TipoGestionAreaHospitalariaEnum tipoGestion);
public FutureTask<List<AreaHospitalaria>> getAreasHospitalariasByNombre(Context context, TipoGestionAreaHospitalariaEnum tipoGestion, String nombre);
public FutureTask<AreaHospitalaria> getAreaHospitalariaByCodigo(Context context, TipoGestionAreaHospitalariaEnum tipoGestion, String codigo);
Centro Especializada
public FutureTask<CentroEspecializada> getCentroEspecializadaByCodigo(Context context, String codigo);
public FutureTask<List<CentroEspecializada>> getCentrosEspecializada(Context context);
public FutureTask<List<CentroEspecializada>> getCentrosEspecializadaByArea(Context context, String codigoArea);
public FutureTask<List<CentroEspecializada>> getCentrosEspecializadaByNombre(Context context, String nombre);
public FutureTask<List<CentroEspecializada>> getCentrosEspecializadaByUnidadFuncional(Context context, String codigoUnidadFuncional);
Centro Primaria
public FutureTask<CentroPrimaria> getCentroPrimariaByCodigo(Context context, String codigo);
public FutureTask<List<CentroPrimaria>> getCentrosPrimariaByCodigoPostal(Context context, Long codigoPostal);
public FutureTask<List<CentroPrimaria>> getCentrosPrimariaByDistrito(Context context, Long distrito);
public FutureTask<List<CentroPrimaria>> getCentrosPrimariaByLocalidad(Context context, Long localidad);
public FutureTask<List<CentroPrimaria>> getCentrosPrimariaByMunicipio(Context context, Long municipio);
public FutureTask<List<CentroPrimaria>> getCentrosPrimariaByNombre(Context context, String nombre);
public FutureTask<List<CentroPrimaria>> getCentrosPrimariaByZonaBasica(Context context, Long zonaBasica);
Comunidad Autonoma
public FutureTask<ComunidadAutonoma> getComunidadAutonomaByCodigo(Context context, String codigo);
public FutureTask<List<ComunidadAutonoma>> getComunidadesAutonomas(Context context);
public FutureTask<List<ComunidadAutonoma>> getComunidadesAutonomasByNombre(Context context, String nombre);
Distrito
public FutureTask<Distrito> getDistritoByCodigo(Context context, String codigo);
public FutureTask<List<Distrito>> getDistritos(Context context);
public FutureTask<List<Distrito>> getDistritosByMunicipio(Context context, String codigoMunicipio);
public FutureTask<List<Distrito>> getDistritosByNombre(Context context, String nombre);
public FutureTask<List<Distrito>> getDistritosByProvincia(Context context, String codigoProvincia);
Especialidad
public FutureTask<Especialidad> getEspecialidadByCodigo(Context context, String codigo);
public FutureTask<Especialidad> getEspecialidadByUnidadFuncional(Context context, String codigoUnidadFuncional);
public FutureTask<List<Especialidad>> getEspecialidadByNombre(Context context, String nombre);
public FutureTask<List<Especialidad>> getEspecialidades(Context context);
Provincia
public FutureTask<Provincia> getProvinciaByCodigo(Context context, String codigo);
public FutureTask<List<Provincia>> getProvincias(Context context);
public FutureTask<List<Provincia>> getProvinciasByComunidadAutonoma(Context context, String codigoComunidadAutonoma);
public FutureTask<List<Provincia>> getProvinciasByNombre(Context context, String nombre);
Tipo Asistencia
public FutureTask<TipoAsistencia> getTipoAsistenciaByCodigo(Context context, String codigo);
public FutureTask<List<TipoAsistencia>> getTiposAsistencia(Context context);
public FutureTask<List<TipoAsistencia>> getTiposAsistenciasByCentroAP(Context context, String codigoCentroAP);
public FutureTask<List<TipoAsistencia>> getTiposAsistenciasByNombre(Context context, String nombre);
Tipo Profesional
public FutureTask<TipoProfesional> getTipoProfesionalByCodigo(Context context, String codigo);
public FutureTask<List<TipoProfesional>> getTiposProfesionales(Context context);
public FutureTask<List<TipoProfesional>> getTiposProfesionalesByNombre(Context context, String nombre);
Ubicacion
public FutureTask<Ubicacion> getUbicacionByCodigo(Context context, TipoUbicacionEnum tipo, String codigo);
public FutureTask<List<Ubicacion>> getUbicaciones(Context context, TipoUbicacionEnum tipo);
public FutureTask<List<Ubicacion>> getUbicacionesByArea(Context context, TipoUbicacionEnum tipo, String codigoAreaHospitalaria);
public FutureTask<List<Ubicacion>> getUbicacionesByCentro(Context context, TipoUbicacionEnum tipo, Long codigoCentro);
public FutureTask<List<Ubicacion>> getUbicacionesByNombre(Context context, TipoUbicacionEnum tipo, String nombre);
public FutureTask<List<Ubicacion>> getUbicacionesByPadre(Context context, TipoUbicacionEnum tipo, String codigoPadre);
Unidad Funcional Especializada
public FutureTask<UnidadFuncionalEspecializada> getUnidadFuncionalByCodigo(Context context, String codigo);
public FutureTask<List<UnidadFuncionalEspecializada>> getUnidadesFuncionales(Context context);
public FutureTask<List<UnidadFuncionalEspecializada>> getUnidadesFuncionalesByArea(Context context, String codigoAreaHospitalaria);
public FutureTask<List<UnidadFuncionalEspecializada>> getUnidadesFuncionalesByCentro(Context context, String codigoCentro);
public FutureTask<List<UnidadFuncionalEspecializada>> getUnidadesFuncionalesByNombre(Context context, String nombre);
Unidad Funcional Primaria
public FutureTask<UnidadFuncionalPrimaria> getUnidadFuncionalByCodigo(Context context, String codigo);
public FutureTask<List<UnidadFuncionalPrimaria>> getUnidadesFuncionales(Context context);
public FutureTask<List<UnidadFuncionalPrimaria>> getUnidadesFuncionalesByCentroAPActividad(Context context, String codigoCentroAP);
public FutureTask<List<UnidadFuncionalPrimaria>> getUnidadesFuncionalesByCentroAPSede(Context context, String codigoCentroAP);
public FutureTask<List<UnidadFuncionalPrimaria>> getUnidadesFuncionalesByNombre(Context context, String nombre);
Versión 1.1.0.1: Acceso a información de Estructura
Atención Especializada
public List<AreaHospitalaria> getAreasHospitalarias(Context context, TipoGestionAreaHospitalariaEnum tipoGestion);
public List<AreaHospitalaria> getAreasHospitalariasByNombre(Context context, TipoGestionAreaHospitalariaEnum tipoGestion, String nombre);
public AreaHospitalaria getAreaHospitalariaByCodigo(Context context, TipoGestionAreaHospitalariaEnum tipoGestion, String codigo);
public CentroEspecializada getCentroEspecializadaByCodigo(Context context, String codigo);
public List<CentroEspecializada> getCentrosEspecializada(Context context);
public List<CentroEspecializada> getCentrosEspecializadaByArea(Context context, String codigoArea);
public List<CentroEspecializada> getCentrosEspecializadaByNombre(Context context, String nombre);
public List<CentroEspecializada> getCentrosEspecializadaByUnidadFuncional(Context context, String codigoUnidadFuncional);
public Especialidad getEspecialidadByCodigo(Context context, String codigo);
public Especialidad getEspecialidadByUnidadFuncional(Context context, String codigoUnidadFuncional);
public List<Especialidad> getEspecialidadByNombre(Context context, String nombre);
public List<Especialidad> getEspecialidades(Context context);
public Ubicacion getUbicacionByCodigo(Context context, TipoUbicacionEnum tipo, String codigo);
public List<Ubicacion> getUbicaciones(Context context, TipoUbicacionEnum tipo);
public List<Ubicacion> getUbicacionesByArea(Context context, TipoUbicacionEnum tipo, String codigoAreaHospitalaria);
public List<Ubicacion> getUbicacionesByCentro(Context context, TipoUbicacionEnum tipo, Long codigoCentro);
public List<Ubicacion> getUbicacionesByNombre(Context context, TipoUbicacionEnum tipo, String nombre);
public List<Ubicacion> getUbicacionesByPadre(Context context, TipoUbicacionEnum tipo, String codigoPadre);
public UnidadFuncionalEspecializada getUnidadFuncionalByCodigo(Context context, String codigo);
public List<UnidadFuncionalEspecializada> getUnidadesFuncionales(Context context);
public List<UnidadFuncionalEspecializada> getUnidadesFuncionalesByArea(Context context, String codigoAreaHospitalaria);
public List<UnidadFuncionalEspecializada> getUnidadesFuncionalesByCentro(Context context, String codigoCentro);
public List<UnidadFuncionalEspecializada> getUnidadesFuncionalesByNombre(Context context, String nombre);
Atención Primaria
public AreaConocimiento getAreaConocimientoByCodigo(Context context, String codigo);
public List<AreaConocimiento> getAreasConocimiento(Context context);
public List<AreaConocimiento> getAreasConocimientoByNombre(Context context, String nombre);
public CentroPrimaria getCentroPrimariaByCodigo(Context context, String codigo);
public List<CentroPrimaria> getCentrosPrimariaByCodigoPostal(Context context, Long codigoPostal);
public List<CentroPrimaria> getCentrosPrimariaByDistrito(Context context, Long distrito);
public List<CentroPrimaria> getCentrosPrimariaByLocalidad(Context context, Long localidad);
public List<CentroPrimaria> getCentrosPrimariaByMunicipio(Context context, Long municipio);
public List<CentroPrimaria> getCentrosPrimariaByNombre(Context context, String nombre);
public List<CentroPrimaria> getCentrosPrimariaByZonaBasica(Context context, Long zonaBasica);
public Distrito getDistritoByCodigo(Context context, String codigo);
public List<Distrito> getDistritos(Context context);
public List<Distrito> getDistritosByMunicipio(Context context, String codigoMunicipio);
public List<Distrito> getDistritosByNombre(Context context, String nombre);
public List<Distrito> getDistritosByProvincia(Context context, String codigoProvincia);
public TipoAsistencia getTipoAsistenciaByCodigo(Context context, String codigo);
public List<TipoAsistencia> getTiposAsistencia(Context context);
public List<TipoAsistencia> getTiposAsistenciasByCentroAP(Context context, String codigoCentroAP);
public List<TipoAsistencia> getTiposAsistenciasByNombre(Context context, String nombre);
public TipoProfesional getTipoProfesionalByCodigo(Context context, String codigo);
public List<TipoProfesional> getTiposProfesionales(Context context);
public List<TipoProfesional> getTiposProfesionalesByNombre(Context context, String nombre);
public UnidadFuncionalPrimaria getUnidadFuncionalByCodigo(Context context, String codigo);
public List<UnidadFuncionalPrimaria> getUnidadesFuncionales(Context context);
public List<UnidadFuncionalPrimaria> getUnidadesFuncionalesByCentroAPActividad(Context context, String codigoCentroAP);
public List<UnidadFuncionalPrimaria> getUnidadesFuncionalesByCentroAPSede(Context context, String codigoCentroAP);
public List<UnidadFuncionalPrimaria> getUnidadesFuncionalesByNombre(Context context, String nombre);
Geolocalizacion
public ComunidadAutonoma getComunidadAutonomaByCodigo(Context context, String codigo);
public List<ComunidadAutonoma> getComunidadesAutonomas(Context context);
public List<ComunidadAutonoma> getComunidadesAutonomasByNombre(Context context, String nombre);
public Provincia getProvinciaByCodigo(Context context, String codigo);
public List<Provincia> getProvincias(Context context);
public List<Provincia> getProvinciasByComunidadAutonoma(Context context, String codigoComunidadAutonoma);
public List<Provincia> getProvinciasByNombre(Context context, String nombre);
Versión 1.0.0.1: Acceso a información de Estructura
public FutureTask<AreaConocimiento> getAreaConocimientoByCodigo(Context context, String codigo);
public FutureTask<List<AreaConocimiento>> getAreasConocimiento(Context context);
public FutureTask<List<AreaConocimiento>> getAreasConocimientoByNombre(Context context, String nombre);
Área Hospitalaria
public FutureTask<List<AreaHospitalaria>> getAreasHospitalarias(Context context, TipoGestionAreaHospitalariaEnum tipoGestion);
public FutureTask<List<AreaHospitalaria>> getAreasHospitalariasByNombre(Context context, TipoGestionAreaHospitalariaEnum tipoGestion, String nombre);
public FutureTask<AreaHospitalaria> getAreaHospitalariaByCodigo(Context context, TipoGestionAreaHospitalariaEnum tipoGestion, String codigo);
Centro Especializada
public FutureTask<CentroEspecializada> getCentroEspecializadaByCodigo(Context context, String codigo);
public FutureTask<List<CentroEspecializada>> getCentrosEspecializada(Context context);
public FutureTask<List<CentroEspecializada>> getCentrosEspecializadaByArea(Context context, String codigoArea);
public FutureTask<List<CentroEspecializada>> getCentrosEspecializadaByNombre(Context context, String nombre);
public FutureTask<List<CentroEspecializada>> getCentrosEspecializadaByUnidadFuncional(Context context, String codigoUnidadFuncional);
Centro Primaria
public FutureTask<CentroPrimaria> getCentroPrimariaByCodigo(Context context, String codigo);
public FutureTask<List<CentroPrimaria>> getCentrosPrimariaByCodigoPostal(Context context, Long codigoPostal);
public FutureTask<List<CentroPrimaria>> getCentrosPrimariaByDistrito(Context context, Long distrito);
public FutureTask<List<CentroPrimaria>> getCentrosPrimariaByLocalidad(Context context, Long localidad);
public FutureTask<List<CentroPrimaria>> getCentrosPrimariaByMunicipio(Context context, Long municipio);
public FutureTask<List<CentroPrimaria>> getCentrosPrimariaByNombre(Context context, String nombre);
public FutureTask<List<CentroPrimaria>> getCentrosPrimariaByZonaBasica(Context context, Long zonaBasica);
Comunidad Autonoma
public FutureTask<ComunidadAutonoma> getComunidadAutonomaByCodigo(Context context, String codigo);
public FutureTask<List<ComunidadAutonoma>> getComunidadesAutonomas(Context context);
public FutureTask<List<ComunidadAutonoma>> getComunidadesAutonomasByNombre(Context context, String nombre);
Distrito
public FutureTask<Distrito> getDistritoByCodigo(Context context, String codigo);
public FutureTask<List<Distrito>> getDistritos(Context context);
public FutureTask<List<Distrito>> getDistritosByMunicipio(Context context, String codigoMunicipio);
public FutureTask<List<Distrito>> getDistritosByNombre(Context context, String nombre);
public FutureTask<List<Distrito>> getDistritosByProvincia(Context context, String codigoProvincia);
Especialidad
public FutureTask<Especialidad> getEspecialidadByCodigo(Context context, String codigo);
public FutureTask<Especialidad> getEspecialidadByUnidadFuncional(Context context, String codigoUnidadFuncional);
public FutureTask<List<Especialidad>> getEspecialidadByNombre(Context context, String nombre);
public FutureTask<List<Especialidad>> getEspecialidades(Context context);
Provincia
public FutureTask<Provincia> getProvinciaByCodigo(Context context, String codigo);
public FutureTask<List<Provincia>> getProvincias(Context context);
public FutureTask<List<Provincia>> getProvinciasByComunidadAutonoma(Context context, String codigoComunidadAutonoma);
public FutureTask<List<Provincia>> getProvinciasByNombre(Context context, String nombre);
Tipo Asistencia
public FutureTask<TipoAsistencia> getTipoAsistenciaByCodigo(Context context, String codigo);
public FutureTask<List<TipoAsistencia>> getTiposAsistencia(Context context);
public FutureTask<List<TipoAsistencia>> getTiposAsistenciasByCentroAP(Context context, String codigoCentroAP);
public FutureTask<List<TipoAsistencia>> getTiposAsistenciasByNombre(Context context, String nombre);
Tipo Profesional
public FutureTask<TipoProfesional> getTipoProfesionalByCodigo(Context context, String codigo);
public FutureTask<List<TipoProfesional>> getTiposProfesionales(Context context);
public FutureTask<List<TipoProfesional>> getTiposProfesionalesByNombre(Context context, String nombre);
Ubicacion
public FutureTask<Ubicacion> getUbicacionByCodigo(Context context, TipoUbicacionEnum tipo, String codigo);
public FutureTask<List<Ubicacion>> getUbicaciones(Context context, TipoUbicacionEnum tipo);
public FutureTask<List<Ubicacion>> getUbicacionesByArea(Context context, TipoUbicacionEnum tipo, String codigoAreaHospitalaria);
public FutureTask<List<Ubicacion>> getUbicacionesByCentro(Context context, TipoUbicacionEnum tipo, Long codigoCentro);
public FutureTask<List<Ubicacion>> getUbicacionesByNombre(Context context, TipoUbicacionEnum tipo, String nombre);
public FutureTask<List<Ubicacion>> getUbicacionesByPadre(Context context, TipoUbicacionEnum tipo, String codigoPadre);
Unidad Funcional Especializada
public FutureTask<UnidadFuncionalEspecializada> getUnidadFuncionalByCodigo(Context context, String codigo);
public FutureTask<List<UnidadFuncionalEspecializada>> getUnidadesFuncionales(Context context);
public FutureTask<List<UnidadFuncionalEspecializada>> getUnidadesFuncionalesByArea(Context context, String codigoAreaHospitalaria);
public FutureTask<List<UnidadFuncionalEspecializada>> getUnidadesFuncionalesByCentro(Context context, String codigoCentro);
public FutureTask<List<UnidadFuncionalEspecializada>> getUnidadesFuncionalesByNombre(Context context, String nombre);
Unidad Funcional Primaria
public FutureTask<UnidadFuncionalPrimaria> getUnidadFuncionalByCodigo(Context context, String codigo);
public FutureTask<List<UnidadFuncionalPrimaria>> getUnidadesFuncionales(Context context);
public FutureTask<List<UnidadFuncionalPrimaria>> getUnidadesFuncionalesByCentroAPActividad(Context context, String codigoCentroAP);
public FutureTask<List<UnidadFuncionalPrimaria>> getUnidadesFuncionalesByCentroAPSede(Context context, String codigoCentroAP);
public FutureTask<List<UnidadFuncionalPrimaria>> getUnidadesFuncionalesByNombre(Context context, String nombre);
Dispositivos de Apoyo
public FutureTask<DispositivoApoyo> getDispositivoApoyoByCodigo(Context context, String codigo);
public FutureTask<List<DispositivoApoyo>> getDispositivosApoyo(Context context);
public FutureTask<List<DispositivoApoyo>> getDispositivosApoyoByCentroAPActividad(Context context, String codigoCentroAP);
public FutureTask<List<DispositivoApoyo>> getDispositivosApoyoByCentroAPSede(Context context, String codigoCentroAP);
public FutureTask<List<DispositivoApoyo>> getDispositivosApoyoByNombre(Context context, String nombre);
5. Arquitectura de la librería
Puesto que a fecha de realización del presente documento los servicios web que ofrece Estructura para acceder a su información no permiten acceder a todo el catálogo de entidades almacenadas en Estructura, la única forma de acceder actualmente a dicha información es haciendo uso de Réplicas de base de datos.
Ya que el acceso a la información a través de réplicas de base de datos no está aconsejado por la gran dependencia que genera entre diferentes productos, la librería de acceso a la Estructura se ha desarrollado siguiendo un modelo de API/Implementación que permite exponer a los usuarios de la librería una API única que debe ser usada y una serie de implementaciones de dicha API, las cuales serán las verdaderas encargadas de acceder a la información.
Siguiendo este patrón se ha iniciado el desarrollo con una única implementación haciendo uso de réplicas (por ser la única forma posible actualmente), esperando que en un futuro se generen nuevas implementaciones que hagan uso de distintos métodos de acceso a Estructura (SOAP, REST, etc.). Los productos que estén ya desarrollados y haciendo uso de la API estándar podrán cambiar fácilmente de implementación si que el producto se vea afectado.
Requerimientos
Siguiendo la normativa vigente para desarrollo de aplicaciones Java en el SAS, la librería de acceso a estructura se ha implementado con Java 7 y ha sido testada en Oracle Weblogic 12.1.3, donde se ha creado proyectos de prueba que incorporan la librería a través de Maven.
(*) Consultar Artifactory para ver última versión disponible
Configuración
Antes de comenzar a configurar nuestro proyecto, conviene recordar que la implementación de la API desarrollada con la que se cuenta actualmente se basa en acceso a la información a partir de un origen de datos específico para el acceso a sus datos, mientras que por otro lado la aplicación podrá tener otro origen de datos distinto para acceder a sus datos, de esta forma la aplicación puede estar en una base de datos mientras que la información de estructura sea recuperada de otra distinta.
Dicho esto, y siendo consciente de que existen diferentes formas de hacer lo mismo, a continuación se expone una serie de instrucciones a seguir para configurar un proyecto web que haga uso de esta librería y que se ejecutará en un contenedor Weblogic:
Configurar origen de datos en Weblogic: El primer paso a seguir será configurar el origen de datos en Weblogic, donde debemos crear un origen de datos que tenga visibilidad con las tablas de réplicas de estructura alojados en un esquema llamado REP_PRO_EST. Por ejemplo, nuestro origen de datos podría llamarse "jdbc/Diraya-Estructura-DS"
Configurar persistence.xml: Configurar el fichero persistence.xml de nuestro proyecto web para añadir el orígen de datos configurado previamente. En este fichero se le asignara un nombre a la unidad de persistencia que posteriormente usará nuestro código a través de JPA. En el siguiente extracto puede verse como se crea una unidad de persistencia llamada "Diraya-Estructura-Persistence-Unit" y que es mapeada con el origen de datos que creamos previamente:
Es importante destacar que para aislar la unidad de persistencia del resto de la aplicación y evitar posibles conflictos, es recomendable añadir la etiqueta "class" y "exclude-unlisted-classes" con el valor que puede verse en el ejemplo para que la unidad de persistencia sólo actúe sobre el paquete indicado. En cuanto al fichero de mapeo de entidades, pueden usarse cualquiera de los siguientes mapeos:
META-INF/est-bd-replica.xml: Cuando nuestra cadena de conexión apunte a una base de datos donde existe una réplica de estructura en el esquema REP_PRO_EST. Este será la configuración usada en la mayoría de los casos
META-INF/est-bd-original.xml: Cuando nuestra cadena de conexión apunte directamente a la base de datos de Estructura
Cualquier otra configuración requerirá que el fichero xml sea redefinido por la aplicación que hace uso de la librería
Asignar EntityManager a la librería: Una vez configurada la unidad de persistencia sólo nos quedaría indicarle a la librería cuál va a ser el contexto de persistencia que queremos que use, ya que como se ha mencionado previamente, nuestra aplicación puede tener varios orígenes de datos distintos. Para ello nuevamente existen diferentes formas de hacerlo, a continuación se muestra una manera muy simple consistente en crear una clase que es ejecutada al iniciar nuestro servidor y se encarga de asignarle a la librería el contexto de persistencia a usar. A partir de este momento nuestra librería es completamente funcional.
@Singleton
@Startup
public class DaeEntityManagerConfig {
@PersistenceContext(unitName = "Diraya-Estructura-Persistence-Unit")
private EntityManager estructuraEntityManager;
@PostConstruct
public void init() {
EntityManagerContainer.setEntityManager(estructuraEntityManager);
}
}
Generar configuración de la API: A partir de la versión 2.x de la librería, al funcionar en base a Futures, se hace necesario el uso de un Executor encargado de gestionar los hilos que se vayan lanzando en el sistema. Para ello bastará con añadir un Produces en nuestro proyecto como el siguiente:
@Produces
@Singleton
public EstructuraApiConfig producerEstructuraApiConfig() {
return new EstructuraApiConfigBuilder().executorPoolSize(20).build();
}
IMPORTANTE: Es especialmente importante ser consciente de la forma de funcionar de un Produces, ya que si en cada inyección se realiza una llamada al Produces se creará en cada llamada un Executor diferente, generando un problema de rendimiento en el servidor por acumulación de hilos. Por tanto, queda a responsabilidad del programador que hace uso de la librería el asegurar que sólo se genere un Executor para toda la librería o por servicio. En el presente ejemplo esto se ha conseguido haciendo uso de @Singleton, pero igualmente podría conseguirse mediante variables estáticas, etc.
6. Instrucciones de uso
Una vez configurado nuestro proyecto, el uso de la librería es tan simple como inyectar el servicio que deseemos utilizar (AreaConocimientoService, AreaHospitalariaService, etc) en cualquier parte de nuestro código para poder hacer uso de toda la funcionalidad que ofrece la librería.
A partir de la versión 2.0.0.1 de la librería se ha modificado el modo de uso de la librería de forma que todos los servicios existentes han sido evolucionados a servicios equivalentes que devuelven Futures en lugar de devolver directamente las entidades solicitadas. De esta forma el programador podrá paralelizar otras tareas mientras la librería obtiene el dato, cosa que hará que mejore el rendimiento considerablemente en el caso de que el dato tenga que ser obtenido por medio de servicios webs
En el siguiente fragmento de código puede verse un ejemplo sencillo en el que se ha diseñado un servicio llamado "EpisodioService" el cual hará tres acciones típicas de sistemas sanitarios: En primer lugar buscará en su propia base de datos un episodio a partir de un identificador dado, posteriormente usará la librería de Estructura (Marcado en rojo) para recuperar la información asociada de la cama en la que se encuentra ingresado el paciente. Tras esta llamada la librería devuelve un Future y el hilo de ejecución continua, por lo que podemos recuperar en paralelo las citas del paciente (Marcado en verde):
public class EpisodioService {
private EpisodioDao episodioDao;
private CitasService citasService;
private UbicacionService ubicacionService;
@Inject
public EpisodioService(EpisodioDao episodioDao, CitasService citasService, UbicacionService ubicacionService) {
this.episodioDao = episodioDao;
this.citasService = citasService;
this.ubicacionService = ubicacionService;
}
public EpisodioDTO getEpisodio(Long numEpisodio) {
EpisodioDTO result = null;
Context context = GeneradorContexto.createContext(...);
Episodio epiAux = episodioDao.getByPk(numEpisodio);
FutureTask<Ubicacion> ubicacionFuture = ubicacionService.getUbicacionByCodigo(context, TipoUbicacionEnum.CAMA, epiAux.getCodCama())List<Citas> citas = citasService.getByEpisodio(numEpisodio);
if (epiAux != null) {
result = new EpisodioDTO();
result.setNumEpisodio(epiAux.getNumEpisodio());
result.setFchIngreso(epiAux.getFchIngreso());
result.setCama(ubicacionFuture.get());
}
return result;
}
}
Mención especial requiere el atributo "Context", marcado en azul en el ejemplo anterior. Este objeto tiene como objetivo ser un contenedor de información que representa el contexto en el que nos encontramos.
Actualmente, sólo consta de un objeto de tipo MacoUser, el cual podrá usarse el día de mañana para validar los usuarios en MACO. Por ello, el objetivo es tener un servicio encargado de generar los contextos que se pasarán a la API de Estructura (En este ejemplo, sería el objeto GeneradorContexto), de esta forma, al generarse siempre el contexto desde un punto común, cuando sea necesario realizar nuevas modificaciones, estas podrán realizarse en un único punto y aplicarán automáticamente a todo el código. Consulte JavaDoc para ver detalle del objeto. Este objeto debe ser pasado como parámetro en todas las llamadas a la librería, de esta forma la implementación de la API que se esté usando podrá hacer uso del contexto para validar el usuario.
7. JavaDoc y Código Fuente
Toda la documentación del proyecto en forma de JavaDoc, así como el código fuente del mismo, se encuentra desplegado al Artifactory del SAS, por lo que el programador podrá descargarlo y consultarlo para ver el detalle de todas las clases de la librería. Se recomienda especialmente consultar JavaDoc de los servicios principales de la API (AreaConocimientoService, AreaHospitalariaService, etc), donde podrá ver el detalle de todas las operaciones permitidas actualmente.
Pruebas de carga
Contexto:
Base de datos: Entornos de desarrollo de DAE, réplica de Estructura
Servidor web: Servicios REST publicados en una aplicación de ejemplo. Internamente hace uso de la API de Estructura
Intel Core i7 2520M 2.5GHz
8GB Ram
Windows 7 64Bits
Weblogic 12.1.3 (1GB Ram)
Cliente REST: jMeter 3.0
Pruebas:
En la siguiente captura puede observarse un rendimiento de unas 1000 peticiones por segundo en las pruebas de carga realizadas.
Sobre los errores producidos, se deben a urls mal formadas: