Aquest wiki està orientat a que sigui una base de coneixements corporatius relacionats amb el Framework JEE Corporatiu.
Està dividida en els següents blocs:
El següent article explica com instal·lar la versió 12.2.1.3 del producte Oracle Weblogic Server en local i com configurar el nou servidor al framework proporcionat amb el FAM 4, Eclipse Mars.
Els servidors Weblogic dels entorns DVOL, INT, PRE i PRD es van actualitzar a la versió 12.2.1.3 i la versió del servidor instal·lada localment és la 12.1.3.0
Decarregar l'arxiu zip [5]amb el servidor Weblogic configurat i descomprimir a C:\diba_mars\servers.
A continuació, obrir l'Eclipse Mars i configurar un nou servidor Weblogic.
Finestra de servidors, botó dret.
Selecciona la versió del servidor Weblogic
Indicar el directori home de la instalació: C:\diba_mars\servers\wls12213\wlserver
Seleccionar el domini:
I finalitzar:
En aquest cas, descarrega el zip de la instal·lació generica [6] i segueix els següents passos, adaptant els directoris a les teves necessitats. Els passos següents estan fets amb els següents valors:
Obrir una finestra com administrador
Executar les següents instruccions:
cd D:\UserData\gimenezbf\Downloads\tools
cd d:
c:\diba_mars\jdk\jdk1.8.0_40\bin\java.exe -jar fmw_12.2.1.3.0_wls.jar
Directori d’instal·lació: C:\diba_mars\servers\wls12213
Potser no troba un JDK, però es configurarà amb el de la finestra
I ara la configuració del domini de Weblogic, canviem el nom del domini per defecte a ‘local’, com l’actual configuració del Weblogic 12.1.3 C:\diba_mars\servers\wls12213\user_projects\domains\local
Plantilla per defecte
Clau de l'administrador: welcome1
Directori del JDK per defecte
Finalment, instal·lar les llibreries de suport (p. ex. JAX-RS, que necessiten moltes de les aplicacions FAM4) segons Oracle [7].
Documentació relativa a aplicacions basades en el model FAM
Aquest document pretén ser una guia per a desenvolupar aplicacions web basades en Framework de la DIBA de 2012 i alineades amb el prototipus d’exemple FAM.
Aquestes normes estan ordenades segons la importància i agrupades per tipologia. Cadascuna d’elles tindrà un codi identificador o tag.
http://svn.corpo.ad.diba.es:8080/subversion/[codi_prj]/releases [8]
Documentació relacionada: FWK_Mapeig_BBDD.doc
Documentació relacionada: Estructura_FWK.pdf – DAOS
Documentació relacionada: Estructura_FWK.pdf – Services
Documentació relacionada: Estructura_FWK.pdf – Beans
Documentació relacionada: FWK_FAM_Properties
Documentació relacionada: FWK_FAM_Missatges.
Documentació relacionada: FWK_FAM_Missatges.
Documentació relacionada: FWK_FAM_Missatges.
Documentació relacionada: FWK_FAM_Missatges.
Documentació relacionada: FWK_FAM_Missatges.
Documentació relacionada: FWK_Documentació_Site.doc
Documentació relacionada: FWK_Documentació_Site.doc
Documentació relacionada: FWK_Documentació_Site.doc
Documentació relacionada: FWK_Crear_Nou_Projecte_BackOffice.doc
I en canvi per a les combos de filtre de llistats s’haurà de tenir un objecte de tipus List dins de la classe del xxxlistModule, amb el booleà corresponent indicant si està habilitat o no si es tracta de combos anidades. Aquests objectes de llista seran omplerts des de la corresponent classe xxxService i l’entitat que estigui continguda en el combo haurà d’implementar la interfície DibaSelectItem que obliga a tenir el parell id – descripció.
Documentació relacionada: FWK_Desplegament_projecte_eclipse.doc.
new -> run configurations -> Nou Projecte BackOffice
Introduir parametres
Nota: Aquest pas es pot deixar per més endavant però mai es pot omitir.
Nota: La generació de entitats es fa a partir de la base de dades. Eclipse necessita tenir definida una connexió a l’esquema.
Nota: Tenir present la base de dades contra la que es vol fer el mapeig (recomenat SIT).
Entrar a la perspectiva de database development
Comprovar si existeix la connexió i contra que esquema, adaptar-lo al projecte.
Botó dret al projecte -> JPA Tools -> Generate Entities from Tables
A la pantalla que s’obre seleccionar la connexió, l’esquema i les taules que es vulguin mapejar (per exemple, totes llevat la PLAN_TABLE) i fer next
Surt una pantalla on s’indiquen les associacions que es mapejaran.
Dependrà de cada projecte i de cada relació però la configuració desitjable és mapejar les relacions pares però no les filles. Si é vol fer un manteniment mestre detall on els fills estiguin en memòria, llavors s’han de carregar les relacions pares i filles.
La següent captura mostra la configuració de la primera relació. Es mapeja la relació pare (Generate this association) però no la relació fills (generate a reference to a collection...)
Nota: És important revisar que estiguin totes les relacions i configurar-les una per una abans de continuar. Estalviarà molta feina manual.
Al següent pas s’ha d’indicar la seqüència oracle del projecte per generar els ids.
També s’ha de indicar el package per posar les entities (ha de ser el configurat en crear el projecte) car.diba.jee.[CodiDelProjecte].model.entities
A la última pantalla es poden configurar els mapeigs a nivell de entitat canviant el tipus de dada o el nom de les propietats.
No s’haurien de fer canvis en aquesta pantalla.
Fer finish i esperar que termini
- Sequence bug: S’ha d’afegir a les entitats la propietat allocationSize=1 veure exemple al fam.
- Datas: Els camp de data s’han de configurar per que siguin TimeStamp si tenen hora.@Temporal(TemporalType.DATE) @Temporal(TemporalType.TIMESTAMP)
- Tipus: S’ha de configurar el mapeig per tipus, els checboxes a booleans, els BigDecimals a Longs o Doubles...
- Formatejar i documentar les entitats
- Interfícies i implementació de mètodes
La estructura de classes del FAM en referència als manteniments es defineix en tres capes com es detalla a continuació
Encarregada de construir les queries, tant natives com JPQL
Encarregada de fer conjunts de crides que tinguin un sentit de servei. S'encarreguen de les transaccions i fan crides als mètodes de la capa DAO
Encarregada de comunicarse amb les jsp. Fan crides als mètodes de la capa de serveis.
Aquest document explica com fer un manteniment simple d’una entitat de base de dades, es a dir, una pàgina de llista i una de detall on es puguin fer les accions més habituals.
Nota: Aquest manteniment d’exemple es farà sobre la entitat document, copiant el manteniment de Zona del Fam que és un dels més simples.
Nota: Per entendre la estructura de les classes veure el document FWK_Estructura_Classes
FAM: FamZona (implements DibaEntity)
Exemple: TedibaDocument (implements DibaEntity)
Aquest manteniment es basarà en una entitat (classe java associada a una taula). Si aquesta entitat no està creada, veure el document FWK_Mapeig_BBDD per generar el model de dades en java.
FAM: ZonaSearchFilter (extends BaseSearchFilter)
Exemple: DocumentSearchFilter (extends BaseSearchFilter)
Crear una classe (còpia de ZonaSearchFilter) que especifiqui els camps que es poden filtrar.
Adaptació de la classe:
FAM: ZonaDAO (extends DefaultGenericListDao<FamZona, ZonaSearchFilter>)
Exemple: DocumentDAO (extends
DefaultGenericListDao<TedibaDocument, DocumentSearchFilter>)
Crear una classe (còpia de ZonaDAO) que sigui la encarregada de treballar amb la base de dades.
Adaptació de la classe:
FAM: ZonaService (extends DefaultGenericListService<FamZona, ZonaSearchFilter>)
Exemple: DocumentService (extends
DefaultGenericListService<TedibaDocument, DocumentSearchFilter>)
Crear una classe (còpia de ZonaService) que sigui la encarregada de tenir les accions en serveis, com ara operacions amb base de dades dintre de transaccions.
Adaptació de la classe:
FAM: ZonaListModule (extends AbstractGenericListBB< ZonaSearchFilter, FamZona>)
Exemple: DocumentListModule (extends
AbstractGenericListBB <DocumentSearchFilter, TedibaDocument>)
Crear una classe (còpia de ZonaListModule) que tindrà les funcionalitats relatives a llistes de manera que es pugui aprofitar en diferents llocs (Beans de manteniments, popups, autocompletar...).
Adaptació de la classe:
FAM: ZonaBB (extends AbstractGenericBB< ZonaSearchFilter, FamZona>)
Exemple: DocumentBB (extends
AbstractGenericBB <DocumentSearchFilter, TedibaDocument>)
Crear una classe (còpia de ZonaBB) que es farà servir per connectar amb les jsp.
Adaptació de la classe:
Cal afegir la definició del bb al faces-config-bb per que es pugui veure des de les jsp.
<managed-bean>
<managed-bean-name>zonaBB</managed-bean-name>
<managed-bean-class>cat.diba.jee.fam.view.bb.ZonaBB</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
FAM: pZonaLlista.jspx
Exemple: pDocumentLlista.jspx
Pendent de especificar per dummies
FAM: pZonaDetall.jspx
Exemple: pDocumentDetall.jspx
Pendent de especificar per dummies
Afegir un punt d’entrada, per exemple al menú com al FamZona
<navigation-case>
<from-action>#{zonaBB.enter}</from-action>
<from-outcome>MENU</from-outcome>
<to-view-id>/jsp/pZonaLlista.jspx</to-view-id>
</navigation-case>
Definir la navegació entre la llista i el detall
<!-- ZONA -->
<navigation-rule>
<from-view-id>/jsp/pZonaLlista.jspx</from-view-id>
<navigation-case>
<from-outcome>DETALL</from-outcome>
<to-view-id>/jsp/pZonaDetall.jspx</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/jsp/pZonaDetall.jspx</from-view-id>
<navigation-case>
<from-outcome>LLISTA</from-outcome>
<to-view-id>/jsp/pZonaLlista.jspx</to-view-id>
</navigation-case>
</navigation-rule>
Pensar com afegir funcionalitats (referenciar a altres documents)
La gestió d’una entitat requereix la definició del mapa de navegació entre les interfícies que la composen per definir correctament quines la composaran.
Les aplicacions basades en el FAM utilitzen Java Server Faces (JSF) com a tecnologia pel desenvolupament de la capa de presentació o vista.
JSF requereix la definició d’un fitxer de configuració (anomenat faces-config-nav.xml) amb la navegabilitat entre cadascuna de les interfícies, tal i com es mostra a continuació.
Tal i com es pot veure a la configuració de l’exemple, per definir la navegabilitat entre les diferents interfícies es defineix un literal per a cadascuna de les regles de navegació.
Els literals estàndards utilitzats per les aplicacions basades en FAM són:
A continuació es mostra el flux de navegació per la gestió d’una entitat anomenada Entitat. El flux mostra, a més de les pantalles que intervenen, el mètode del controlador que resol aquestes peticions.
El següent gràfic representa el flux de navegació del FAM a un nivell més avançat lligat amb els backed beans
Quan parlem de missatges dividim dos casos: literals i missatges. Llevat de casos concrets, els primers es refereixen a textos inclosos directament a la jsp, els segons a textos afegits per java com ara excepcions o avisos.
És important treballar amb tots el missatges d’aplicació amb fitxers de propietats com s’explica en aquest document.
En treballar amb fitxers de propietats, s’ha de fer servir el editor de l’entorn (veure imatge amb la pestanya marcada). Aquest editor tracta bé els accents i permet definir més d’un idioma per definir els missatges.
Els literals que es mostrin en pàgines jsp, no s’han de incloure directament, sinó a través dels fitxers de propietats. A les aplicacions basades en el Fam, s’incorporen dos fitxers de recursos:
Aquests fitxers es defineixen a les jsp per poder fer-los servir.
<f:loadBundle var="litCore" basename="cat.diba.jee.fam.base.jsp.resources.literalsCore" />
<ice:menuItem value="#{litCore.MenuInici}" action="#{applicationBB.entra}" immediate="true" />
Per treballar de manera modular amb els missatges, s’ha creat la interficie Message que només conté el mètode getMessage() amb paràmetres opcionals.
Les excepcions corporatives (DIbaException) treballen amb aquesta interfície de manera que la seva tipologia et dona el missatge al moment de mostrar-lo per pantalla o per log.
La classe MessageUtils treballa amb la interficie Message, per tant amb qualsevol implementació.
Aporta mètodes que mostren els missatges per pantalla:
infoMessage, warnMessage, errorMessage.
Si es vol afegir un missatge nou, lo més normal seria afegir al AppMessage una nova entrada de la enumeració i al app.message afegir aquesta mateixa entrada amb el text descriptiu.
Amb això, és pot pintar per pantalla fent servir la classe MessageUtils o creant una nova excepció.
Aquesta és la classe encarregada de gestionar els fitxers de propietats. En arrencar el servidor es carreguen totes les properties en memòria i es poden accedir des de qualsevol lloc.
El fam i els projectes nous venen configurats amb un fitxer de propietats app.properties que es carrega al AppPropertiesFactory i es accessiible mitjançant el mètode appProperties().
La classe AppPropertiesFactory està preparada per carregar totes les propietats depenents del perfil, com ara els drets. Per defecte, es carreguen uns perfils estandards però es pot configurar. Es proporciona el mètode perfilProperties(String perfil) per recuperar les properties d’un perfil concret.
Si es volen afegir fitxers de propietats, seria bo considerar:
El component GenericPagedDataModel utilitzat en les aplicacions basades en FAM permet gestionar, d’una forma senzilla, la paginació de les dades obtingudes en una cerca.
Aquest component es basa en el component DataModel de JSF i s’encarrega de definir els mètodes
La instància del servei (DefaultGenericListService) definit al component GenericPagedDataModel permet finalment accedir al mètode creaQuery del Dao definit al nostre desenvolupament (que hereta de DefaultGenericListDao) a través del mètode findPageByFilter.
Per crear la documentació del site, agafem com a exemple el codi de projecte XXX.
Nota: Aquesta acció pot trigar uns 5 minuts
Això genera la documentació a la carpeta /target del projecte. S’ha de copiar manualment la carpeta site sencera per no perdre-la
La configuració del site està definida al pom.xml a la secció de report
Cada report que es descriu a continuació
Per poder personalitzar més l’aparença i el contingut del site, es pot afegir opcionalment una plantilla. Això està fet, definint una carpeta site i un fitxer site.xml es defineix automàticament la plantilla del site. Aquest fitxer es configura per afegir la capçalera amb estils de l’aplicació i enllaços a la carpeta del projecte i als entorns de desenvolupament. És totalment configurable.
També es poden afegir noves planes amb uns formats específics:
Al FAM a mode exemple s’afegeix FAQ.fml i dibaInfo.apt i s’enllacen al site.xml (menú informació)
Aquest informe exporta tot el codi font en un format que sigui referenciable per línia. D’aquesta manera s’integra amb altres plugins que fan referència a alguna línia de codi en concret.
Aquest informe genera la revisió de codi amb checkstyle. Es comproven normes d’estil o de format del codi, com ara que es facin servir noms de variables correctes, que estigui tot documentat amb javadoc, l’ús correcte del nivell d’accés a les variables...
L’informe mostra un resum dels warnings que s’han generat linkable amb el codi font Xref.
Nota: S’ha de reduir al màxim aquests avisos, però no ha de ser una obsessió deixar a zero aquest informe. De vegades hi ha warnings justificables o que en intentar resoldre’ls s’afegeix una complexitat innecessària al codi.
Aquest informe genera un resum de les tasques (FIXME, TODO, DIBA_REV i totes les que es defineixin) que queden pendents de fer. Al codi es marquen com tasques a revisar i el plugin fa un resum de les que queden obertes.
Aquest informe genera la revisió de codi amb PMD. Es comproven regles de codificació per evitar fer dissenys de poca qualitat. L’informe mostra un resum dels warnings i errors que s’han generat linkable amb el codi font Xref.
Nota: Igual que al checkstyle, s’ha de reduir al màxim aquests avisos, però no ha de ser una obsessió deixar a zero aquest informe.
Aquest informe genera la revisió de codi amb Findbugs. Es cerquen possibles bugs d’aplicació o trossos de codi que puguin generar problemes. L’informe mostra un resum dels warnings i errors que s’han generat linkable amb el codi font Xref.
Aquest informe mostra un llistat dels canvis fets a subversion a l’últim mes (configurable). Apareix la versió, usuari i data del canvi, el comentari que ha afegit el desenvolupador i els fitxers afectats. L’informe està enllaçat amb urls de svn.
Nota: És importatnt afegir comentaris en pujar codi al subversion per poder fer un bon seguiment de l’estat del projecte.
Aquest informe genera la documentació javadoc.
Aquest informe genera un resum dels tests que s’han executat pel projecte.
Aquest informe genera tot un seguit d’estadistiques en relació a la estructuració del codi (encapsulament, abstraccio...)
Nota: Aquest informe és de caire més tècnic i s’ha de fer un estudi ‘avançat’ per poder treure informació d’interés..
Per integrar el SAMC...
S’han d’afegir al pom.xml les llibreries de SAMC que estan al repositori corporatiu.
<!-- SAMC -->
<dependency>
<groupId>cat.diba.ws</groupId>
<artifactId>samcClient</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>weblogic</groupId>
<artifactId>weblogic</artifactId>
<version>10.3.0.0</version>
<scope>provided</scope>
</dependency>
Es configura SAMC per fitxers de propietats depenent de l’entorn, així s’ha d’afegir al app.properties les següents propietats que dependran de l’entorn.
SAMC.WSDL = ${SAMC.WSDL}
SAMC.aplicacio = ${SAMC.aplicacio}
SAMC.encoding = ${SAMC.encoding}
SAMC.format = ${SAMC.format}
SAMC.password = ${SAMC.password}
SAMC.usuari = ${SAMC.usuari}
I a tots els xxx-filter.properties afegir els paràmetres propis de l’aplicació, on el wsdl usuari i password dependrà del entorn (veure el tercer prerequisit).
SAMC.WSDL = http://iasdsv.diba.es:7777/sam/samWS?wsdl
SAMC.aplicacio = XXX
SAMC.encoding = UTF-8
SAMC.format = text/html
SAMC.password = XXX
SAMC.usuari = XXX
Per poder fer les crides al webservice, es pot copiar la classe del fam ‘WsSamcManager’ que fa servir les propietats d’entorn que hem definit.
Per enviar mails hem de cridar el mètode sendEmails de la classe WsSamcManager passant els paràmetres necessaris.
Es configura el NAS per fitxers de propietats depenent de l’entorn, així s’ha d’afegir al app.properties les següents propietats que dependran de l’entorn.
nas.directory = ${nas.directory}
I a tots els xxx-filter.properties afegir els paràmetres propis de l’aplicació que dependran del entorn (veure el tercer prerequisit).
nas.directory = /nas/data/APP_DATA/FAM_DVOL
Nota: En local es gravarà al propi disc dur, i es recomana fer servir una carpeta similar a la de desenvolupament, amb ruta relativa a la carpeta del instralable: /diba/extras/nas/data/APP_DATA/FAM_DVOL
Les classes per treballar amb NAS es fan servir al FAM (package cat.diba.jee.fam.base.managers), d'on es poden copiar:
Per treballar amb NAS, posem un exemple
DocumentManager gestorDoc = new DocumentManagerNAS();
Long docId = 1234L;
gestorDoc.downLoad(docId);
CSS (Cascading Style Sheets) és un llenguatge de fulls d’estil utilitzat per descriure la semàntica de la capa de presentació de les nostres aplicacions web.
Aquests es defineixen a les nostres interfícies mitjançant el tag link de HTML, tal i com es mostra a continuació.
<link rel="stylesheet" type="text/css" href="https://comunitatdstsc.diba.cat/mystyles.css" media="screen" />
Els estils a les aplicacions basades en FAM defineixen els estils associats als components de presentació a tres nivells diferents:
i aquests es defineixen al fitxer head.jspx
Tal i com es pot veure a la imatge superior,
Nota: En cas que es vulgui definir un nou estil propi a l’aplicació que es desenvolupa caldrà fer l’adaptació necessària al fitxer aplicacio.css
Els timers son uns components Java que permeten executar tasques en background.
Disposem de diferents exemples a aplicacions webs fetes
Al web.xml s'ha d'afegir la següent configuració
<!-- DIBA: Servlet que es fa servir per programar tasques --> <servlet> <description>Servlet que es fa servir per programar tasques</description> <display-name>Timer Servlet</display-name> <servlet-name>Timer Servlet</servlet-name> <servlet-class>cat.diba.jee.fam.base.servlet.TimerServlet</servlet-class> <load-on-startup>9</load-on-startup> </servlet> <!-- DIBA: Necessari pel servlet --> <resource-ref> <res-ref-name>tm/TimerManager</res-ref-name> <res-type>commonj.timers.TimerManager</res-type> <res-auth>Container</res-auth> <res-sharing-scope>Unshareable</res-sharing-scope> </resource-ref> <servlet-mapping> <servlet-name>Timer Servlet</servlet-name> <url-pattern>/timerServlet</url-pattern> </servlet-mapping>
Nota: On diu cat.diba.jee.fam.base.servlet.TimerServlet indicar el package del projecte.
S'ha de fer el servlet que gestiona tots els timers. Hi ha un exemple al projecte eNoti.
Aquesta classe ha d'incloure:
private static final String JNDI_TIMER_MANAGER = "java:comp/env/tm/TimerManager";
public void init() throws ServletException { super.init(); try { ic = new InitialContext(); tm = (TimerManager) ic.lookup(JNDI_TIMER_MANAGER); tm.scheduleAtFixedRate(new TimerController(new NotificacioEstatsEnotiTaskTimer()), 3 * DEFAULT_PERIOD, DEFAULT_PERIOD); tm.scheduleAtFixedRate(new TimerController(new NotificacioEstatsEnotumTaskTimer()), 3 * DEFAULT_PERIOD, DEFAULT_PERIOD); tm.scheduleAtFixedRate(new TimerController(new ComunicacioEstatsEnotiTaskTimer()), 3 * DEFAULT_PERIOD, DEFAULT_PERIOD); } catch (Throwable t) { LOG.error("Error en la càrrega de registres ", t); } }
private class TimerController implements TimerListener { private TaskTimable taskTimable; private long initPeriod; private long period; private ConfigService servei = new ConfigService(); public TimerController(TaskTimable taskTimable) { super(); this.taskTimable = taskTimable; } /* (non-Javadoc) * @see commonj.timers.TimerListener#timerExpired(commonj.timers.Timer) */ @Override public void timerExpired(Timer timer) { try { boolean ambProxy = AppPropertiesFactory.appProperties().getBooleanProperty("entorn.ambProxy"); if (ambProxy) { ProxySwitch.activateProxy(); } taskTimable.process(); refreshScheduleTimer(timer); // Mail diari } catch (Exception e) { //Error al saber si necesitem el Proxy LOG.debug("Error : " + e.getMessage()); } } /** * Schedule timer. * * @param timer the timer */ private void refreshScheduleTimer(Timer timer) { try { if (isPeriodeTimerModificat()) { timer.cancel(); tm.scheduleAtFixedRate(new TimerController(taskTimable), initPeriod, period); // tm.schedule(new TimerController(), initPeriod, period); } } catch (Exception e) { //Si hi ha un error no el timer continua igual LOG.debug("Error : " + e.getMessage()); } } /** * Checks if is periode timer modificat. * * @return true, if is periode timer modificat * @throws Exception the exception */ private boolean isPeriodeTimerModificat() throws Exception { Long configPerIni = Long.valueOf(servei.obtenirConfigPerClau(taskTimable.getIniciConstant()) .getCfgValor()); Long configPer = Long.valueOf(servei.obtenirConfigPerClau(taskTimable.getPeriodConstant()) .getCfgValor()); if (initPeriod != configPerIni || period != configPer) { initPeriod = configPerIni; period = configPer; return true; } return false; } }
Aquestes tasques per anar lligades amb la classe inner comentada anteriorment han de complir la interficie TaskTimable. Aquesta interficie defineix els métodes:
En desplegar el timer, hem de considerar que hi haurà una instància per cada màquina virtual. Per tant en un cluster de 4 hi hauran 4 timers que si, per exemple, envien mails cada hora, aquest mail s'enviarà 4 cops.
Per resoldre això tenim dues opcions:
Com el timer s'executarà en un Thread diferent, si l'aplicació té configurat per codi l'ús d'un proxy, també s'haurà d'activar al timer.
Google ofereix una api per poder recuperar mapes estàtics (ho recupera com a imatge i es pot posar dintre d'un enllaç que apunti al mapa de google maps).
Aquesta és la web amb les especificacions. https://developers.google.com/maps/documentation/staticmaps/ [15]
Per integrar aquest servei a una aplicació fam s'ha de tenir un enllaç del següent tipus:
<a href="http://maps.google.com/maps?q=Pl Comercial, 12, Barcelona" target="_blank"> <img width="170" height="170" src="http://maps.google.com/maps/api/staticmap?center=Pl+Comercial%2C+12%2C+Barcelona&markers=Pl+Comercial%2C+12%2C+Barcelona&zoom=14&size=170x170&maptype=roadmap&sensor=false" /> </a>
La clau és que l'enllaç ha de tenir una referència a google maps i la font de la imatge és la pròpia crida a la api de google.
A banda de paràmeters com la mida, és important el paràmete de la ubicació que és vol mostrar tant al enllaç ("?q=Pl Comercial, 12, Barcelona") com a la font de la imatge ("?center=Pl+Comercial%2C+12%2C+Barcelona")
Per poder definir aquesta crida parametritzable i que s'escapin correctament els valors, s'ha definit la crida amb components de icefaces
<ice:outputLink value="#{xxxBB.staticMap.linkUrl}" target="_blank" rendered="#{not empty xxxBB.staticMap.linkUrl}"> <img width="600" height="300" src="#{xxxBB.staticMap.imageUrl}" /> </ice:outputLink>
Veient aquest codi s'enten que necessitem tenir un ben amb un objecte de tipus staticMap que ens doni linkUrl i imageUrl. Per tals efectes s'ha construit la classe GoogleStaticMapDto que s'inicialitza enviant una adreça
public class GoogleStaticMapDTO { private static final String SCHEME = "http"; private static final String HOST = "maps.google.com"; private static final String PATH_IMAGE = "/maps/api/staticmap"; private static final String PATH_LINK = "/maps"; private String imageUrl; private String linkUrl; public String getImageUrl() { return imageUrl; } public String getLinkUrl() { return linkUrl; } public void init(String center) { try { URI uriImage = new URI(SCHEME, HOST, PATH_IMAGE, "center=" + center + "&zoom=14&size=600x300&maptype=roadmap&sensor=true", null); imageUrl = uriImage.toASCIIString(); URI uriLink = new URI(SCHEME, HOST, PATH_LINK, "q=" + center, null); linkUrl = uriLink.toASCIIString(); } catch (URISyntaxException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
A mode exemple, s'ha integrat aquesta crida a la pantalla de Àreas del FAM. S'ha escollit aquesta pantalla per que no tenia molt de negoci.
El funcionament és que en carregar informació de la entitat al formulari (entityToForm) s'inicialitza aquest objecte.
A la jsp, en entrar al detall d'un àrea es mostra la imatge del mapa corresponent a la ubicació amb un enllaç a google maps
Aquest article pretén recollir les els components tecnològics que s'han afegit a cada aplicació.
Es categoritza per component tecnològic i dintre de cada conjunt s'indiquen les aplicacions que ho fan servir.
Si hi ha una aplicació que fa servir el component per còpia d'altra aplicació, s'ha de fer referència de quina
EREG:
Es signen unes dades xml
TeDiba:
Applet configurat per treballar amb signatura XADES-T detached amb hash precalculat. Afegeix segell de temps
Es fa signatura múltiple (signar 10 decrets d'un cop)
Es fa en un sol click (el js crida al faces per jQuery)
Jano: (Còpia del Tediba)
PMT:
Es signen unes dades xml
TeDiba:
El timer està dintre de la pròpia aplicació
Es controla el temps d'execució dels timer mitjançant base de dades
Es bloquegen els registres en tractarlos el timer
Té dos timers per enviament diari de mails
Té un timer per l'execució en background del procés llarg de registre d'un decret. (Aquest procés té molts pasos on crida a diferents plataformes i es fa així per donar una resposta ràpida al usuari i per tenir un millor control dels errors)
PMT:
Té un timer per reintentar el registre quan falla
Està desenvolupat com una aplicació independent i desplegat en un sol node.
eNoti:
Es configuren els temps dels timers per bd i es bloquegen els registres en tractar-los
Està desenvolupat com a part de la aplicació.
Té un timer pel processament de les comunicacions pas a pas (demanar num. de registre, enviar a EACAT, desar el rebut, etc)
Té un timer pel processament de les notificacions pas a pas (demanar num. de registre, enviar a eNotum, desar el rebut, etc)
Té un timer pel processament del canvi d'estat de les notificacions. (Llegida, caducada, rebutjada...)
eNoti:
Es tracten els xmls de les dades amb xstream
PMT:
Es tracten les dades xml dels registres
eBOP:
Log de publicació signant hash de document amb plataforma PSIS de Catcert.
eBOP (OAS):
Signa PDF's amb plataforma ASF.
Uliep:
Manipulació de PDF, modificant metadades i aplicant una contrasenya de seguretat per l'edició del document.
PMTRestful:
Exposa dades del PMT en format JSON mitjançant un servei web restful. Utilitza la llibreria jersey [16] per generar-lo. També és possible que generi la sortida sigui XML, text pla, html, etc., a més de poder definir URLs amigables.
Per aefegir...
Quan es treballa amb Java sovint necessitem treballar amb dades xml, transformant-les de Java a Texte i vice-versa
Versió simple vs complexe
Per implementar el tractament simple de xml a una aplicació tipus FAM hem de seguir els següents passos:
Modificar el pom.xml
<dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.3.1</version> <type>jar</type> <scope>compile</scope> </dependency>
Es tracta de definir una classe amb variables privades i els respectius getters i setters.
Per defecte, si transformem la classe agaafrà els noms derivats del nom de la variable. Si volem canviar algun nom del camp o fer configuracions més avançades, definirem anotacions sobre la classe. Para muestra un botón:
@XStreamAlias(value="DadesComunes") public class DadesComunesDTO { @XStreamAlias(value="NumeroRegistre") public String numeroRegistre; public String getNumeroRegistre() { return numeroRegistre; } public void setNumeroRegistre(String numeroRegistre) { this.numeroRegistre = numeroRegistre; } [... codi extra...]
Dintre del mateix DTO podem definir el mètode que parsegi l'objecte a xml
public String convertToXmlString() throws DibaException { XStream xstream = new XStream(); xstream.processAnnotations(DadesComunesDTO.class); String result = xstream.toXML(this); return result; }
Les claus d'aquest objete son:
Quan el xml està ben definit per un xsd i està tot molt controlat, és poden fer servir eines més avançades per tractar-lo com ara JAX-B.
Es poden generar classes de JAX-B amb l'eclipse, el SOAP-UI o altres eines.
S'ha de tenir clar que aquesta opció no és tan felxible com la de XStream i que si s'han adaptat les classes generades i hi ha canvis al model, costa asaptar-los.
Al TeDiba tenim l'exemple de TDocAdminRegistrat i tot el tractament de les signatures, on s'ha hagut de definir molt al detall per tal de no trencar les signatures.
[... A aquest article li falta contingut... s'hauria de definir bé com treballar amb JAX-B ...]
Al projecte eNoti s'ha definit una classe que formateja dades XML amb una plantilla XSLT.
Per motius del projecte, la entrada i sortida de les dades es fa per String, mentre que la plantilla és un recurs del projecte que es recupera per fitxer. Això es pot personalitzar acceptant altres tipus de entrada i/o sortida.
A mode de exemple, mostrem la implementació del eNoti. En aquest projecte, s'ha definit una classe (XsltTransformer) que parseja un XML rebut per paràmetre amb una plantilla fixa.
Aquesta classe bàsicament fa tractament de Strings i fitxers i amb el package javax.xml.transform fa la fusió de dades amb la plantilla.
/** * The Class XsltTransformer. */ public class XsltTransformer { /** * The Constant PATH_TEMPLATE_XSLT. */ private static final String PATH_TEMPLATE_XSLT = "/generic.xslt"; /** * Transform. * * @param dataXml the data xml * @return the string * @throws DibaException the diba exception */ public String transform(String dataXml) throws DibaException { try { Source src = new StreamSource(new java.io.StringReader(dataXml)); InputStream template = getClass().getResourceAsStream(PATH_TEMPLATE_XSLT); TransformerFactory factory = TransformerFactory.newInstance(); StreamSource xslStream = new StreamSource(template); Transformer transformer = factory.newTransformer(xslStream); StringWriter writer = new StringWriter(); StreamResult out = new StreamResult(writer); transformer.transform(src, out); return writer.toString(); } catch (Exception e) { throw new DibaException(AppMessage.ERROR_XSLT_TRANSFORM, e); } } }
Aquesta classe es pot reaprofitar per altres projectes i és pot adaptar per treure-li millor rendiment.
Per exemple, si un projecte té una taula on cada registre té un XML i una plantilla definida, aquesta classe haurà de rebre els dos paràmetres per String.
La plantilla definida al eNoti, és una plantilla que pinta qualsevol XML de manera formatejada
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="/"> <table> <xsl:apply-templates select="/DadesEspecifiques/*"/> </table> </xsl:template> <xsl:template match="*"> <tr> <td> <p class="xmlTag"><xsl:value-of select="name()"/></p> </td> <td> <p class="xmlValue"><xsl:value-of select="."/></p> </td> </tr> </xsl:template> <xsl:template match="*[*]"> <tr> <td> <p class="xmlTag"><xsl:value-of select="name()"/></p> </td> <td> <table class="xmlSubTable"> <xsl:apply-templates/> </table> </td> </tr> </xsl:template> </xsl:stylesheet>
Xslt en sí és un 'llenguatge' i té tot un seguit de especificacions que s'hauran de estudiar si és necessari
En aquest article, s'explica com fer crides a serveis REST des d'una aplicació tipus FAM.
Aquest tipus de serveis té una estructura molt més simple que la de serveis web (fins i tot es poden fer crides per url)
Donat un servei REST publicat volem fer una crida des d'una aplicació FAM. Ho farem amb l'ajut de la llibreria Jersey [16]
Primer de tot necessitem definir al pom.xml la dependència amb la llibreria del client de Jersey
<dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> <version>1.8</version> </dependency>
Per problemes de llibreries s'ha d'afegir la llibreria client de weblogic
<dependency> <groupId>weblogic</groupId> <artifactId>wlfullclient</artifactId> <version>10.3.0.0</version> <scope>provided</scope> </dependency>
Un cop definida la dependència podem fer el client que farà les crides
Client client = Client.create(); WebResource wr = client.resource(url); ClientResponse response = wr.accept("application/xml").get(ClientResponse.class);
A partir d'una url et fa la crida
En aquest exemple (implementat al projecte eNoti) es tracta la resposta per validar l'estat i després es parseja per poder carregar la classe resposta i poder llegir la informació, com ara el contingut de la plantilla.
if (response.getStatus() != 200) { throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); } PlantillaRestResposta output = response.getEntity(PlantillaRestResposta.class); byte[] byteArray = output.getPlantilla();
La resposta real del repositori de plantilles és un xml com
<plantillaRestRespostaplantillaRestResposta> <nomPlantilla>TramesaGen</nomPlantilla> <plantilla>bytearrayplantilla</plantilla> <versio>1.1</versio> </plantillaRestResposta>
Per poder parsejar aquesta resposta es defineix la classe PlantillaRestResposta com
package cat.diba.jee.enoti.ws.repositoriplantilles; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class PlantillaRestResposta { private byte[] plantilla; private String versio; private String nomPlantilla; public PlantillaRestResposta() { } [... Getters i Setters ...] }
La situació óptima seria que en fer un servei REST es donessin també les classes de resposta en un jar
L'exemple del VUS és anàleg, però la resposta és molt més complexa i s'han de fer multiples objectes relacionats per poder tractar-la.
Al projecte eNoti hi ha un integració feta.
Per poder provar aquests serveis, es pot fer des del navegador o amb l'ajuda de plugins que permeten definir la crida amb més detall (per exemple, paràmetres per post)
Per Chrome tenim el plugin Postman https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm
JSF permet fer aplicacions multiidioma de una manera molt senzilla. A més, al FAM, s'ha intentat treballar de la manera correcta per tal que internacionalitzar una aplicació sigui fàcil.
Per mirar de modularitzar la internacionalització de les aplicacions dintre del FAM, s'ha preparat un Backed Bean que inclogui la lògica multiidioma.
Aquest Bean inclou:
public class IdiomaBB extends AbstractDibaBB { private static final String PARAM_IDIOMA = "codiIdioma"; enum IDIOMAS {ca, es} private String idioma = IDIOMAS.ca.name(); public String getIdioma() { return idioma; } public String canviIdioma() { idioma = WebUtils.facesRequestParam(PARAM_IDIOMA); updateLocale(idioma); return NavigationConstants.OK; } private void updateLocale(String idioma) { Locale locale = new Locale(idioma); FacesContext context = FacesContext.getCurrentInstance(); context.getViewRoot().setLocale(locale); context.getApplication().setDefaultLocale(locale); } public boolean isCastella() { return IDIOMAS.es.name().equals(idioma); } public boolean isCatala() { return IDIOMAS.es.name().equals(idioma); } }
A les jsp's s'ha d'indicar que la vista agafi l'idioma del bean de sessió que hem creat
<f:view locale="#{idiomaBB.idioma}">
Al menú s'han d'afegir les opcions de canvi d'idioma, visibles o no en funció de l'idioma seleccionat
<li style="float: right"><ice:commandLink title="Cambio de idioma a Castellano" rendered="#{idiomaBB.catala}" action="#{idiomaBB.castellaAction}">[es]</ice:commandLink></li> <li style="float: right"><ice:commandLink title="Cambio de idioma a Catalán" rendered="#{idiomaBB.castella}" action="#{idiomaBB.catalaAction}">[ca]</ice:commandLink></li>
L'editor de l'eclipse permet definir els literals per diferents idiomes.
També s'ha d'indicar el valor per defecte.
Sovint es necessita la funcionalitat de seleccionar un orgànic en una representació amigable.
Al FAM s'ha desenvolupat aquesta funcionalitat per tal que sigui fàcil de implementar
Es troba desplegat al FAM, dintre de la pantalla de jerarquía.
Per tal d'implementar aquesta solució s'han de copiar les classes del FAM que donen la funcionalitat:
GgrlOrganicDTO: Aquesta classe és la que conté la estructura d'un orgànic.
GgrlOrganicSearchFilter: És la classe de filtre per poder cercar per nom
GgrlOrganicDAO: És la classe que té implementada la cerca a la base de dades
GgrlOrganicService: Fa la transacció i crida al DAO
GgrlOrganicListModule: Mòdul de llista per poder cercar
PopupGgrlOrganicBB: Bean del popup
JerarquiaBB: La classe que contingui el popup, ha de copiar d'aquesta classe, la inclusió del popup i dels mètodes de obrir i seleccionar.
A més, s'han de definir les pàgines que ho facin servir
Per acabar, s'han d'actualitzar els estils copiant les imatges dintre de img/tree per tal que el popup surti amb icones.
El problema és que no es pot obrir més d'una aplicació del tipus FAM en un mateix navegador (una aplicació per tab o pestanya). En el moment en que s'obre una segona aplicació en un altre pestanya, es tanca la sessió automàticament de les dos aplicacions.
Totes les aplicacions JEE Web fan servir una cookie per gestionar les sessions. El nom per defecte és JSESSIONID. Aquesta cookie permet el seguiment de l'usuari entre peticions i alhora està relacionada amb al domini de les aplicacions, que en el nostre cas sempre és el mateix: aplicacions.diba.cat (producció).
Llavors, en el nostre escenari, totes les aplicacions JEE tenen el mateix domini i el mateix nom de cookie pel seguiment (JSESSIONID).
Cal tenir en compte també l'arquitectura de servidors: balancejadors i servidors Apache configurats amb el plugin de WebLogic que direccionen les peticions HTTP/HTTPS cap al cluster de servidors d'aplicacions WebLogic.
I el darrer factor és la gestió d'aquesta cookie per part d'IceFaces 1.8.2.
Llavors, una explicació simplificada de perquè passa això és que al fer un segon inici de sessió des del mateix navegador, la cookie de sessió pren un valor diferent que comporta automàticament l’anul·lació de la seva validesa per motius de seguretat. Aquesta anul·lació es feta per IceFaces ja que no pot distingir a quina pestanya pertany cadascuna de les cookies.
La solució consta de dos parts:
Per facilitar el manteniment dels noms de les cookies es recomana seguir el patró J<codi projecte>ID. Exemples: JFAMID, JSISEMANAGERID, ....
El nom de la cookie de sessió es configura a l’arxiu weblogic.xml.
Exemple d'arxiu weblogic.xml del projecte SISEMANAGER on es pot observar en negreta i itàlica la configuració del nom de la cookie:
<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app
xmlns:wls="http://www.bea.com/ns/weblogic/weblogic-web-app"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd [17] http://www.bea.com/ns/weblogic/weblogic-web-app [18] http://www.bea.com/ns/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd">
<wls:weblogic-version>10.3.0</wls:weblogic-version>
<wls:context-root>siseManager</wls:context-root>
<wls:container-descriptor>
<wls:show-archived-real-path-enabled>true</wls:show-archived-real-path-enabled>
</wls:container-descriptor>
<wls:session-descriptor>
<wls:cookie-name>JSISEMANAGERID</wls:cookie-name>
</wls:session-descriptor>
</wls:weblogic-web-app>
Aquesta part la realitza Plataformes i cal demanar-li el canvi indicant el nom de la cookie per l'aplicació concreta i l'entorn (DVOL, INT, PRE PRD) i ells s'encarreguen d'actualitzar la configuració de l'Apache. Un cop rebuda la confirmació, cal procedir amb el desplegament de l'aplicació a l'entorn corresponent.
La manera més eficient de verificar el nom de la cookie és mitjançant les eines de desenvolupament del navegador Google Chrome
Obre el navegador i polsa F12 per habilitar les eines Web. Selecciona de la part superior la opció 'Resources' i llavors a la esquerra desplega la opció 'Cookies'. Es mostrarà una entrada per cadascun del dominis visitats i seleccionant el domini es mostrarà a la dreta les cookies que te emmagatzemades i els seus valors.
A les següents imatges podem veure les diferents cookies segons es van obrint pestanyes amb noves aplicacions.
Primera aplicació oberta: SISE Manager.
Segona aplicació oberta: FAM. Es pot veure que tenen noms de cookies de sessió diferents.
I finalment la tercera aplicació que no està configurada: SIGAC-
Amb això no n'hi ha prou, cal verificar que tots els elements des del navegador fins a l'aplicació estan ben configurats i això es confirma navegant per l’aplicació. Si amb l’ús de l’aplicació es manté el valor de la cookie i no apareix un altre de nova, llavors tots els elements estan ben configurats. El següent pas seria fer la prova obrint un altre pestanya i un altre aplicació tipus FAM.
Aquesta solució no s'ha d'aplicar encara. Sembla que soluciona el problema de les dues aplicacions però provoca altres problemes quan caduca la sessió. S'ha de mirar més a fons.
Des de fa anys, tenim un problema amb les aplicacions desplegades a Weblogic.
Si tens una aplicació oberta i obres altra dins del mateix entorn (Producció, Pre, int, o dev segons el servidor) la segona aplicació col·lisionava amb la primera tancant-se les dues sessions.
Sembla ser que la gestió per defecte que fa weblogic de les cookies, les discrimina per servidor i no per contexte. Això feia que les cookies de sessió es compartissin entre aplicacions i provocava el problema esmentat.
Per tal d'evitar això, la solució és indicar a les aplicacions quin és el contexte de les cookies.
Això es fa modificant el fitxer weblogic.xml (dintre de Webroot/WEB-INF) afegint-li la propietat cookie-path amb el valor del contexte de l'aplicació
És pot fer modificant el xml:
<wls:weblogic-web-app xmlns:wls="http://www.bea.com/ns/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd [17] http://www.bea.com/ns/weblogic/weblogic-web-app [18] http://www.bea.com/ns/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd"> <wls:weblogic-version>10.3.0</wls:weblogic-version> <wls:context-root>fam</wls:context-root> <wls:container-descriptor> <wls:show-archived-real-path-enabled>true</wls:show-archived-real-path-enabled> </wls:container-descriptor> <wls:session-descriptor> <wls:cookie-path>fam</wls:cookie-path> </wls:session-descriptor> </wls:weblogic-web-app>
O amb el dissenyador
Al FAM s'ha afegit un exemple de generació d'informes amb JasperReports.
Aquesta funcionalitat es troba al menu Demo Jasper Report.
S'han d'afegir les llibreries de jasper reports al pom.xml, son les seguents:
<!-- japer report --> <dependency> <groupId>net.sf.jasperreports</groupId> <artifactId>jasperreports</artifactId> <version>5.6.0</version> </dependency> <dependency> <groupId>net.sf.jasperreports</groupId> <artifactId>jasperreports-fonts</artifactId> <version>4.0.0</version> </dependency> <dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-all</artifactId> <version>2.0.1</version> </dependency> <dependency> <groupId>xalan</groupId> <artifactId>xalan</artifactId> <version>2.6.0</version> </dependency> <dependency> <groupId>com.lowagie</groupId> <artifactId>itext</artifactId> <version>2.1.7</version> </dependency> <dependency> <groupId>commons-digester</groupId> <artifactId>commons-digester</artifactId> <version>1.8</version> </dependency>
La classe JasperReportManager és la principal peça d'integració amb aquest mòdul. És la que fa la fusió
Al FAM s'han fet dos exemples per exportar en PDF i en HTML. (És una de les virtuts d'aquests reports, amb una plantilla pots fer diferents sortides)
Les plantilles es poden fer amb la eina iReport que tenim inclosa al instal·lable. Els informes es generen fàcilment amb aquesta eina visual.
Recomanem, com fem a l'exemple, definir les plantilles multidioma, passant l'idioma per paràmetre. També deixar la plantilla juntament amb els literals a una carpeta del NAS fora del projecte per poder fer els canvis més àgilment
Sovint les aplicacions Java necessiten accedir a serveis externs. Per tal d'accedir a aquests serveis, s'ha de fer servir el proxy o no es tindrà visibilitat. Aquest article intenta explicar com configurar-lo correctament.
La manera de implementar la sortida per proxy és canviant les propietats de sistema de la màquina virtual de Java, això es faria amb un codi com aquest:
Properties systemSettings = System.getProperties(); systemSettings.put("http.proxyHost", "proxyxic.corpo.ad.diba.es"); systemSettings.put("http.proxyPort", "80"); systemSettings.put("http.nonProxyHosts", "*.diba.es|*.diba.cat"); systemSettings.put("https.proxyHost", "proxyxic.corpo.ad.diba.es"); systemSettings.put("https.proxyPort", "80");
És suficient amb una sola crida al codi, tot i que normalment està implementat cada cop que es fa login o si hi han timers, en inicialitzar-se aquests.
Als projectes FAM la implemantació s'encapsula amb una classe ProxySwitch que té els valors definits en constants.
Com de vegades segons l'entorn és vol fer servir el proxy o no, es va afegir una variable ${entorn.ambProxy} que s'informa amb les variables de entorn definides a xxx-filter.properties.
Des de plataformes ens informen que hi han aplicacions que han definit el proxy sense excloure els *.diba.cat i que això provoca que la consola tingui problemes, totes les aplicacions que facin servir el proxy haurien de tenir la propietat nonProxyHosts definida correctament
Al sortir a internet pel proxy les IPs públiques que es veuen externament són:
Sovint, al fer un segon desplegament d'una aplicació al WebLogic, apareixen errors del tipus classe no trobada referent a una classe de les entitats declarades a l'arxiu persistence.xml
Aquest problema es pot minimitzar tancant l'objecte estàtic que gestiona les transaccions (EntityManagerHelper
) quan es destrueix el context de l'aplicació i això succeeix normalment quan s’atura l’aplicació al WebLogic
Per aplicar aquesta solució cal seguir els següents pasos:
web.xml
:<listener>
<listener-class>cat.diba.jee.servlet.PersistenceAppListener</listener-class>
</listener>
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import cat.diba.jee.base.model.EntityManagerHelper;
public class PersistenceAppListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent evt) {
}
public void contextDestroyed(ServletContextEvent evt) {
EntityManagerHelper.closeEntityManagerFactory();
}
}
EntityManagerHelper
: public static void closeEntityManagerFactory() {
if (emf != null) {
emf.close();
emf = null;
}
}
Al FAM es fa servir el component de data de Icefaces amb un format de data dd/MM/yyyy.
Aquest component tracta els dia mes i l'any com tres numérics de manera que converteix
1/1/1 -> 01/01/0001
Això provoca que si l'usuari introdueix la data manualment amb dos digits per l'any per ex. 25/04/95 ho converteixi en 25/04/0095.
Per tal d'evitar aquest comportament es recomana fer validacions de servidor de les dates comprovant que siguin més grans que 1900 per exemple i si no ho és retornar un error o avís segons la funcionalitat de l'aplicació.
Enllaços:
[1] https://comunitatdstsc.diba.cat/wiki/operacions-framework
[2] https://comunitatdstsc.diba.cat/wiki/fam-documentacio
[3] https://comunitatdstsc.diba.cat/wiki/eines-components
[4] https://comunitatdstsc.diba.cat/wiki/formacio
[5] https://drive.google.com/open?id=1_Fmlfxl05nii2KHZuTtYaP7tPY021wcW
[6] https://drive.google.com/open?id=1zvdH2569pSD3Gc0zKw-vM7b-FHjPMafB
[7] https://docs.oracle.com/middleware/1213/wls/RESTF/use-jersey20-ri.htm#RESTF297
[8] http://svn.corpo.ad.diba.es:8080/subversion/[codi_prj]/releases
[9] https://comunitatdstsc.diba.cat/wiki/FWK2012_-_Creacio_de_datasource_en_weblogic
[10] http://xxx.fam.xxx
[11] http://xxx.codiprojecte.xxx
[12] https://comunitatdstsc.diba.cat/wiki/FWK2012_-_Crear_nou_projecte_tipus_FAM
[13] https://comunitatdstsc.diba.cat/wiki/FWK2012_-_Descarregar_projecte_existent
[14] https://comunitatdstsc.diba.cat/wiki/FAM_-_Crear_nou_projecte_tipus_FAM
[15] https://developers.google.com/maps/documentation/staticmaps/
[16] https://jersey.java.net/
[17] http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd
[18] http://www.bea.com/ns/weblogic/weblogic-web-app