miércoles, 30 de diciembre de 2020

Ubuntu. Solucionar apt-get update “the following signatures couldn’t be verified because the public key is not available”

Introducción


Para solucionar el problema he recurrido a Chris Jean 

Quiero utilizar el programa Sikulix para probar software, y para utilizar la parte de OCR para buscar texto, se necesita innstalar el OCR Tesseract 4.0.1 mínimo, y resulta que la clave pública no está en mi sistema y por tanto no se pueden instalar estos paquetes.

He hecho lo siguiente:

1. Cargar el repositorio

sudo add-apt-repository ppa:alex-p/tesseract-ocr

con lo que me sale una ratahila de mensajes y en concreto uno de ello me dice:

Las firmas siguientes no se han podido verificar porque la clave pública no está disponible: NO_PUBKEY F7E06F06199EF2F2

2. Actualizar el software

sudo apt-get update

y constesta entre otras cosas.

Las firmas siguientes no se han podido verificar porque la clave pública no está disponible: NO_PUBKEY F7E06F06199EF2F2
N: No se puede actualizar de un repositorio como este de forma segura y por tanto est desactivado per omisión.
N: Mire la página de manual apt-secure(8) para ver los detalles sobre la creación de repositorios y la configuración de usuarios.


3. Para añadir las claves públicas, Chris propone:

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F7E06F06199EF2F2

Vamos a probar a ver si ya se puede instalar el software.

Sikulixpara ello hacemos:(Sikulix-RaiMan)

sudo add-apt-repository ppa:alex-p/tesseract-ocr
sudo apt-get update
sudo apt install tesseract-ocr
sudo apt install libtesseract-dev
sudo ldconfig

y para ver la version

tesseract -v

Que nos devuelve:

tesseract 4.1.1

 leptonica-1.78.0

  libgif 5.1.4 : libjpeg 8d (libjpeg-turbo 1.5.2) : libpng 1.6.34 : libtiff 4.0.9 : zlib 1.2.11 : libwebp 0.6.1 : libopenjp2 2.3.0

 Found AVX2

 Found AVX

 Found FMA

 Found SSE

 Found libarchive 3.2.2 zlib/1.2.11 liblzma/5.2.2 bz2lib/1.0.6 liblz4/1.7.1

Con lo que ya lo tenemos instalado





lunes, 7 de diciembre de 2020

Certificados en Java (3). Configurar JBoss Server con https. autentificacion del cliente con certificado.

 1. Introducción

En el fichero server.xml se indica donde localizar los certificados

para encontralo, si se sabe que cuelga de "/opt" se puede probar con este comando

find /opt -name server.xml -print

Y nos salen

/opt/jboss-X.X.X.ZZ/server/all/deploy/jboss-web.deployer/server.xml
/opt/jboss-X.X.X.ZZ/server/default/deploy/jboss-web.deployer/server.xml

Parece ser que el segundo fichero es el correcto.

Miramos el contenido del fichero, y solamente la parte que nos interesa es:

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
               maxThreads="150" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS"
               ciphers="TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"
               keystoreFile="${jboss.server.home.dir}/conf/myjbosscert.p12" keystorePass="mypassword" keystoreType="PKCS12"
               truststoreFile="${jboss.server.home.dir}/conf/server.truststore" truststorePass="otherpassword" truststoreType="JKS" />

Ahora hay que cambiar myjbosscert.p12 por el nuevo certificado y tener en cuenta la nueva contraseña e indicarlo en el fichero server.xml

OJO: solo se puede activar para que vea los certificados como jks o como PKCS12. Por tanto hay que tener cuidado y leerse la documentación para no terner problemas, y ver que está activado el APR para utilizar certificados ".p12" (PKCS12) 


2. Pero y si tenemos un certificado en formato crt?

Para ello tenemos que convertirlo a p12 y para ello hacemos

openssl pkcs12 -export -in myjbosscert.crt -inkey myjboss.key -out myjbosscert.p12 -name myjboss -CAfile myCA.pem -caname root -chain

Donde myjboss.key es la clave que hemos creado para el servidor

y myCA.pem es el certificado X509 de la entidad certificadora.

Lo que hacemos es que añadimos la cadena de certificados al almacén PKCS12


NO ES OBLIGADO e incluso puede ser recomendable en ciertos casos no utilizar las opciones 

   -name myjboss    ni tampoco

   -caname root 

Y nos pedirá una contraseña.

NOTA: Al convertir un certificado de X509 v3 (con datos adicionales como los diversos SAN o "nombre-maquina+dominio" alternativos), parece que se pierde parte de esta información adicional. Si queremos ver el certificado resultante y sabiendo la contraseña que nos pide anteriormente podemos hacer:


openssl pkcs12 -nokeys -info -in ximodante.p12 -passin pass:mypassword

OJO: este comando no muestra las SAN o DNS alternativos!!, pero si instalamos este certificado en un Tomcat y accedemos a este servidor desde Firefox y le decimos que muestre el certrificado de servidor, SI QUE NOS MUESTRA LOS SAN!!!!!

3. Apuntes de José María del Ayuntamiento de Mula

 1. En el servidor de la SEDE tenéis que modificar el nombre del certificado y pass en el server.xml de 

/opt/jboss-4.2.3.GA/server/default/deploy/jboss-web.deployer/server.xml

2. En Backoffice para el SELLO es en keystore.properties de la ruta 

/opt/jboss-4.2.3.GA/server/default/conf/keystore.properties



 



domingo, 11 de octubre de 2020

ECLIPSE muy lento, ¿Cómo espabilarlo?


En máquinas obsoletas, las nuevas versiones de eclipse van muy lentas, para agilizar un poco se puede hacer:

  1. Quitar la opción de               Project   -> Build Automatically
  2. Quitar la validación de JPA: Window-> Preferences -> Validation -> Buscar el JPA de la tabla y desmarcarlo.


Ahora cuando queramos ejecutar en el servidor:
La primera vez al abrir el workspace:
  1. Botón derecho sobre el proyecto: Run As --> Maven Clean
  2. Botón derecho sobre el proyecto: Maven  --> Update project
  3. Apretar el icono de Build

Cuando no se hagan cambios muy significativos, solo se apretara el iocono del Build.


martes, 6 de octubre de 2020

ERROR: no encuentra void com.sun.mail.util.TraceInputStream.(java.io.InputStream, com.sun.mail.util.MailLogger)

 Si se ejecuta en modo aplicación no da ningún problema pero en modo web con Tomcat si los da.


Parece ser segun stackoverflow que hay que añadir la dependencia de maven smtp, a pesar de que hay dependencia a javax.mail y simple-java-mail


<dependency>
  <groupId>com.sun.mail</groupId>
  <artifactId>smtp</artifactId>
  <version>${smtp.version}</version>
</dependency>
        
<dependency>
  <groupId>com.sun.mail</groupId>
  <artifactId>javax.mail</artifactId>
  <version>${javax.mail.version}/version>
</dependency>

<dependency>
  <groupId>org.simplejavamail</groupId>
  <artifactId>simple-java-mail</artifactId>
  <version>${simple-java-mail.version}></version>
</dependency>




viernes, 2 de octubre de 2020

STAX2-API: Error en Eclipse + Tomcat: Caused by: java.lang.NoSuchMethodError: 'org.codehaus.stax2.ri.SingletonIterator org.codehaus.stax2.ri.SingletonIterator.create(java.lang.Object)'

Problema

 El Tomcat no arranca, y es consecuencia de que se han declarado mas de una version de "stax2-api".

Por tanto hay que entrar en el "pom.xml" y comentar las declaraciones duplicadas de dependencias de stax2-api de diferentes versiones.

Esta duplicidad se produce debido a que los test de clases básicas que contienen Hibernate Envers necesitan estas declaraciones en <scope>runtime</scope> para funcionar, mientras en modo web no funcionan. Ver stackoverflow. Y ver también post anterior.

Por tanto cuando se ejecuten los test en modo java application (y no en modo web) hay que descomentarlo

Solución 1

20/01/2022. Se puede solucionar lo de Hibernate Envers utilizando la nueva implementación de jakarta que no utiliza el stax2-api


implementation 'org.hibernate:hibernate-core-jakarta:5.6.3.Final'
implementation 'org.hibernate:hibernate-envers-jakarta:5.6.3.Final'
//implementation "org.hibernate:hibernate-testing-jakarta:5.6.3.Final'
implementation "org.hibernate:hibernate-validator:7.0.2.Final" 


Solución 2

Utilizar Maven shadow plugin o Gradle shadow plugin

martes, 29 de septiembre de 2020

Conflicto de librerias de Hibernate Envers: java.lang.NoSuchMethodError: org.codehaus.stax2.ri.EmptyIterator.getInstance()

Problema (ir al apartado de solución)

El problema viene que hay un conflicto de dependencias de la stax2-api pues se uilizan distintas versiones.

El sistema de compilación de Maven parece ser que elimina las versiones mas viejas, por tanto cualquier referencia a métodos que se encuentren excluisivamente en versiones viejas, dan error de "runtime" que en este caso indica que no encuentra el método.

Para solucionarlo hacemos uso de <scope>runtime</scope> en cada una de las dependencias antigua que queremos.

Su suso está bien explicado en Baeldung y en mi caso tenía que suministrar las versiones 4.2.1 y la 3.1.4

Quedando en el pom.xml este fragmento



<dependency>
  <groupId>org.codehaus.woodstox</groupId>
  <artifactId>stax2-api</artifactId>
  <version>4.2.1</version>
  <scope>runtime</scope>
</dependency>
		 
<dependency>
  <groupId>org.codehaus.woodstox</groupId>
  <artifactId>stax2-api</artifactId>
  <version>3.1.4</version>
  <scope>runtime</scope>
</dependency>

Con esta adición de dependencias parece ser que se ha solucionado si se ejecuta como Java applicaion pero no en modo web

Por tanto para ejecutar una clase que abra una sesion de JPA Hibernate que haga uso de Hibernate Envers con la anotiación @Audited en una Entidad como la clase FirstControlLoad, hay que añadir este código al pom-xml, pero hay que quitarlo para generar el war!!!

Solución buena

20/01/2022. Se puede solucionar lo de Hibernate Envers utilizando la nueva implementación de jakarta que no utiliza el stax2-api


implementation 'org.hibernate:hibernate-core-jakarta:5.6.3.Final'
implementation 'org.hibernate:hibernate-envers-jakarta:5.6.3.Final'
//implementation "org.hibernate:hibernate-testing-jakarta:5.6.3.Final'
implementation "org.hibernate:hibernate-validator:7.0.2.Final" 



jueves, 17 de septiembre de 2020

JPA Problema: @MappedSuperClass No reconoce el @Id las clases hijas

Problema:

Tenemos una clase anotada con @MappedSuperClass a la que defibnimos un campo con la notación @Id y queremos que este campo se herede para todas las clases hijas,

El problema surge cuando:

1. Anotamos con @Entity a las clases hijas y

2. Las clases hijas están en otro paquete

Entonces Eclipse se queja diciendo que:

"The entity has no primary key attribute defined" 


Solución:

Añadir la clase madre(la del @MappedSuperClass)  con una tag  <class> al fichero "persistence.xml" si este tiene la etiqueta <exclude-unlisted-classes> a true

martes, 15 de septiembre de 2020

JSON XML + LOMBOK + SICRES 3.0 Problemas de mapeado de clases

 Tenemos el siguiente error

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `openadmin.model.sicres.DeInteresado` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('E')


Solución:

Cambiar este código:

XmlMapper mapper = new XmlMapper();

Por este

JacksonXmlModule xmlModule = new JacksonXmlModule();
xmlModule.setDefaultUseWrapper(false);
ObjectMapper mapper = new XmlMapper(xmlModule);
mapper.registerModule(new JaxbAnnotationModule()); // Accept JAXB Annotations !!!!

para que acepte JAXB annotations!


miércoles, 12 de agosto de 2020

Certificados en Java (2). Configurar Tomcat (tambien en Eclipse) https autentificacion cliente certificado. Tarjeta, Smartcard cliente

1. Configurar Tomcat  para https

Segun Namecheap  podemos instalar en Tomcat certificados .jks y tembién .p12 (pkcs12)

1.a con certificado jks

Supongamos que tenemos un certificado p12 llamado mykeystore.jks con contraseña "mypassword", entonces:

Modificamos el conector en el fichero server.xml de la carpeta conf de tomcat y para el puerto 8443 para que quede así

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<!-- Define a SSL HTTP/1.1 Connector on port 8443
        This connector uses the JSSE configuration, when using APR, the
        connector should be using the OpenSSL style configuration
        described in the APR documentation -->
    <Connector port="8443" 
              protocol="HTTP/1.1"
              SSLEnabled="true"
              maxThreads="150" 
              scheme="https" 
              secure="true"
              clientAuth="false" <!-- true to read client certificate -->
              sslProtocol="TLS" <!--"TLSv1.2" -->
              keyAlias="tomcat" <!-- Alias cuando se crea mykeystore,jks -->
	      keystoreFile="/home/ximo/mykeystore.jks"
	      keystorePass="mypassword" 
              
    /> 

Y ahora vamos al directorio "bin" del tomcat y paramos y rearrancamos el servicio

./shutdown.sh
./startup.sh

1.b con certificado pem

Supongamos que hemos obtenido de LetsEncrypt, estos certificados que estan en la carpeta  /etc/letsencrypt/live/midominio.es
  • cert.pem (certificado "solo")
  • chain.pem (cadena de certificados del root)
  • fullchain.pem (certificado "solo" + cadena de certificados del root. Equivale a los 2 ficheros anteriores juntos)
  • privkey.pem (clave privada)
Modificamos el conector en el fichero server.xml de la carpeta conf de tomcat y para el puerto 19443 para que quede así

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
 <Connector port="19443"
      protocol="HTTP/1.1"
      SSLEnabled="true"
      maxThreads="150"
      scheme="https"
      secure="true"
      sslProtocol="TLS"

      clientAuth="true"
      keyAlias="tomcat"


      SSLCertificateFile="/etc/letsencrypt/live/midominio.es/cert.pem"
      SSLCertificateChainFile="/etc/letsencrypt/live/midominio.es/chain.pem"
      SSLCertificateKeyFile="/etc/letsencrypt/live/midominio.es/privkey.pem"
   />

  
Como vemos,:
  1.  No nos ha hecho falta el fullchain.pem
  2. Tampoco nos ha hecho falta ninguna contraseña
  3. Estamos trabajando en un puerto https adicional 19443 (junto con el anterior 8443) sin ningún problema

Y ahora vamos al directorio "bin" del tomcat y paramos y rearrancamos el servicio

./shutdown.sh
./startup.sh


2. Obtener un certificado jks versión fácil


En un blog anterior hemos creeado una entidad certificadora. 


Para ello hay que seguir las instrucciones de Mkyong :

Nos situamos en el directorio /home/ximo/mycerts y creamos un keystore con un certificado auto firmado:

keytool -genkey -alias tomcat -keyalg RSA -keystore mykeystore.jks

OJO: El alias tomcat del mykeystore es el que se debe de indicar en el "keyAlias" del web.xml del tomcat
nos pide una nueva contraseña para el nuevo keystore por ejemplo "mypassword"

podemos listar el contenido del keystore con

keytool -list -v -keystore mykeystore.jks



3. Obtener un certificado jks con un certificado emitido por nuestra entidad certificadora.

Aprovechamos todos los pasos anteriores y generamos el Certificate Signing Request CSR. Para ello volvemos al directorio  /home/ximo/mycerts y tecleamos

keytool -certreq -alias tomcat1 -file mytomcat.csr -keystore mykeystore.jks

Observar que el alias el mismo que hemos creado antes (tomcat)  y nos ha creado el fichero mytomcat.csr


OJO: Para obtener cada una de las DNS, debemos hacer este comando:

nslookup 192.168.2.2

siendo 182.168.2.2 la dirección IP del servidor que queremos crear el certificado, y nos devuelve:

ws.ximodante.es
otro.ximodante.es

Y con esta información de los DNS creamos el fichero de configuración siguiente (mytomcat.conf):

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = 192.168.2.2
DNS.2 = localhost --> SOLO PARA PUEBAS en PRE
DNS.3 = otro.ximodante.es
DNS.4 = ws.ximodante.es

Por tanto debeis cambiar a la IP que realmente está usando el servidor 

Ahora generamos el certificado

openssl x509 -req -in mytomcat.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial -out mytomcat.crt -days 825 -sha256 -extfile mytomcat.conf
 
Hay que tener en cuenta que debemos disponer de los certificados de nuestra entidad certificadora (myCA.key y myCA.pem) obtenidos en el post anterior.

Finalmente importamos el certificado generado usando el mismo alias "tomcat" a nuestro almacén de claves.

keytool -import -alias tomcat1 -file mytomcat.crt -keystore mykeysore.jks

Y rearrancamos el servicio de Tomcat como hemos hecho antes:


./shutdown.sh
./startup.sh

Y si entramos en el navegador se quejará, salvo que le indiquemos al navegador que confie en nuestra entidad certificadora.

4. Autentificación en el servidor con certificado de cliente.


Si queremos que el cliente nos muestre su certificado, hay que indicarle en la línea 11 del fragmento anterior de servers.xml:

clientAuth="true" 

Con lo que nos pide el certificado de cliente y podemos autenticarnos en el servidor mediante certificado.

5. Autentificación en el servidor con tarjeta criptográfica (en cliente).

Cuando se intenta acceder con tarjeta criptográfica en el cliente, nos da este error en el cliente:
SSL_ERROR_BAD_CERT_ALERT

Supongo que tal vez haya que indicar un truststore que contenga el certificado raíz.
Parece ser que tomcat utiliza el alacen de certificados de java.

Se va a copiar el fichero keystore  java_path/lib/security/cacerts a una carpeta de pruebas y con el programa keystore explorer, añadimos los certificados raiz de la etidad certificadora de la tarjeta obtenidas de la ACCV 

En concreto añadimos el certificado raiz, los 110 y 120

y vamos a modificar el server.xml para que tenga un truststore


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<!-- Define a SSL HTTP/1.1 Connector on port 8443
        This connector uses the JSSE configuration, when using APR, the
        connector should be using the OpenSSL style configuration
        described in the APR documentation -->
    <Connector port="8443" 
              protocol="HTTP/1.1"
              SSLEnabled="true"
              maxThreads="150" 
              scheme="https" 
              secure="true"
              clientAuth="false" <!-- true to read client certificate -->
              sslProtocol="TLS" <!--"TLSv1.2" -->
              keyAlias="tomcat" <!-- Alias cuando se crea mykeystore,jks -->
	      keystoreFile="/home/ximo/mykeystore.jks"
	      keystorePass="mypassword" 
              
    /> 



6. Configurar el tomcat de Eclipse.



"If you've already created the server, you can edit the server.xml template it copies. If you use the project explorer, It is under Other Projects->Servers->Tomcat Server Name->server.xml"

Así de fácil localizamos el server.xml y lo configuramos como si fuera un tomcat normal.








lunes, 3 de agosto de 2020

La API de JPA 2.1 (VII) Copiar entidades de una base de datos a otra

1. Introducción 

Este problema parece sencillo pero no lo es, sobre todo cuando una entidad tiene colecciones y además los ID son generados automáticamente:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)

2. Proceso

  
  1. Ejecutar una consulta y obtener una lista (colección) de objetos de la entidad a copiar
  2. Para cada instancia:
    2.1 Se crea un objeto igual al de la instancia
    2.1 Mediante recursividad, se copian todos todos los campos del objeto y se asigna NULL al Id propio y de cada una de las colecciones que tenga en el objeto copia.
    2.3 Hacer un persist del nuevo objeto en la nueva EntityManager (EntityManager.persist(obj))

Al recorrer todos los campos del objeto y los campos de los objetos anidados conseguimos que se haya cargado completamente el objeto (pues el "Lazy Loading", solo carga lo que se necesita. 

El objeto original NO DEBE ESTAR DETACHED, pues no haria el "lazy loading" mientras el objeto no està "detached"), 

Para cada instancia (que llamamos "obj") se hará:

1
2
3
T copy=obj; //Define a copy object
ReflectionUtilsEdu.setSameValueToAllNestedBaseFields(copy,"id",null); //Copy by reflection to force lazy Loading
em.persist(copy); //Save the copy

3. Función para hacer nulls los Ids

En esta función le pasamos de parámetros:
  1. El objeto a modificar el atributo recursivamente
  2. Nombre del atributo
  3. Valor del atributo
Si el nombre del atributo le indicamos "id" y al valor "null" entonces hay que tener en cuenta que cualquier campo que se llame id se va a hacer nulo, indepenedienntemente que esté en dicho objeto o en cualquiera de sus colecciones!!!

Aqui le pasamos el objeto y el nombre del campo y valor
Este és el código:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public static Object ObjectCloneAndsetSameValueToAllNestedBaseFields(Object obj,String fldName,Object value) throws Exception {
		
	if (obj==null) return null;
		
	//Create the clone object
	Object clone=obj.getClass().getDeclaredConstructor().newInstance();

	//Get all fields
	List<Field> lFlds= new ArrayList<>(Arrays.asList(FieldUtils.getAllFields(obj.getClass())));
		
	for (Field fld:lFlds) {
			
		// 1. The field value has to be changed
		if (fld.getName().equals(fldName)) FieldUtils.writeField(fld, clone, value, true);
			
		// 2. The field  is a descendant of Base
		else if (Base.class.isAssignableFrom(fld.getType())) {
			Object myObjA=FieldUtils.readField(fld, obj, true);
			Object myObjB=ObjectCloneAndsetSameValueToAllNestedBaseFields(myObjA,fldName, value);
			FieldUtils.writeField(fld, clone, myObjB, true);
			
		// 3. the field is a Collection: let's copy the collection
		}else if (Collection.class.isAssignableFrom(fld.getType())) {
			Collection<?> collA=(Collection<?>)FieldUtils.readField(fld, obj, true);
			// Presume collections as Lists !!!!!!!! May fail if Sets or other Collections type !!!!!!
			Collection<Object> collB=new ArrayList<Object>(); 
			if (collA!=null) {
				Iterator<?> iter=collA.iterator();
				Object myObjA=iter.next();
				Object myObjB=ObjectCloneAndsetSameValueToAllNestedBaseFields(myObjA,fldName, value);
				collB.add(myObjB);
			}
			FieldUtils.writeField(fld, clone, collB, true);
			
		// 4. If the class is serializable, let's use SerializationUtils from Apache	
		}else if (Serializable.class.isAssignableFrom(fld.getType())) {
			Serializable myObjA=(Serializable) FieldUtils.readField(fld, obj, true);
			Serializable myObjB=SerializationUtils.clone(myObjA);
			FieldUtils.writeField(fld, clone, myObjA, true);
		
		// 5. A primitive type or not serializable is assigned without cloning	
		}else if (ClassUtils.isPrimitiveOrWrapper(fld.getType()) 
			  || !Serializable.class.isAssignableFrom(fld.getType())){
			Object myObjA=FieldUtils.readField(fld, obj, true);
			FieldUtils.writeField(fld, clone, myObjA, true);
			
		// 5. Throw exception for other fields
		} else {
			throw new Exception("EDU: The object " + fld.getName() + "(" +fld.getType() + ") is not clonable");
		}
	}
	return clone;
}

4. Posibles errores

1. Verificar que exista un esquema general (en posgres "public") que pueda albergar las relaciones que no entran en un esquema particular. Esto me pasó por borrar el esquema "public" en Postgres.
2. Hibernate hace un proxy del objeto, lo que significa que altera su estructura. Las colecciones las mete en una especie de saco, y és difícil averiguar si son Lists, Sets o otra estructura. En principio se ha supuesto aue son Lists, por tanto si falla , hay que rehacer el código para que acepte otra clase de estructura para las colecciones.


domingo, 2 de agosto de 2020

Maven (3) Proyectos multi-módulo. Copia de seguridad y restauración del proyecto

1. Introducción

Cuando creamos un proyecto multimódulo, es conveniente copiar solamente aquello que es importante como los archovos de configuración (pom.xml), recursos (carpetas resources), carpeta front end ... y no copiar las clases compiladas. Mas tarde el proceso de restauración debe de poder crear un proyecto en condiciones.

2. Programa shell de copia de ficheros importantes.

Veamos un shell script para linux (Ubuntu) donde se hace un tar con compresión y se excluyen los ficheros que se pueden regenerar (como las clases compiladas y otros ficherps que se pueden descargar con Maven)

Para ello hay que rellenar los parámetros del nombre del proyecto (carpeta), carpeta del workspace y carpeta donde se va a guardar el tar


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/bin/bash

#--Explicación
#-------------------------------------------------------------------------------------------
# 1. Indicar project_name, workspace_folder i tar_folder
# 2. Se guardaran en la carpeta tar_folder indicando la fecha
# 3. Utilizamos las opciones cJf para guardar en formato comprimido "xy" que es mas efectivo
#-------------------------------------------------------------------------------------------

#--Parameters

project_name='MyVaadin15_02Parent'
workspace_folder='/home/eduard/Workspace202006/'
tar_folder='/home/eduard/BACKUPS/'

#--Calculations

project_file=${workspace_folder}${project_name}
my_time=`date +"%Y%m%d_%H%M"`
tar_file=${tar_folder}${project_name}"_"${my_time}".tar"


echo $tar_file
echo $project_file

#--Execution

cd ${workspace_folder}
tar -cJvf ${tar_file} --exclude='*/target' --exclude='*/.*' --exclude='*/node_modules' ${project_name}


3. Restauración

Tener en cuenta que los proyectos multi-módulo son un poco especiales a la hora de importarlos y no todos los métodos de imporación de Eclipse funcionan bien.

Para ello descomprimimos la copia de seguridad en la carpeta de nuestro WORKSPACE en Eclipse y hacemos:

File - Import - General - Projects from Folder or Archive



Y seleccionamos la carpeta del proyecto



Tenemos que seleccionar  tanto el proyecto padre como cada uno de los hijos a la vez. Una vez que Eclipse ve el proyecto padre y sus módulos hijos, tenenmos que verificar que encuentra el Java JDK correcto. Para ello hacemos

Window - Preferences - Java - Installed JREs


Ahora si queremos, se puede hacer clik_derecho sobre el proyecto (a veces no aparece la opción y hay que hacer el click derecho sobre el fichero pom.xml) y le damos Run As - Maven clean y repetimos con el  click derecho y Maven - Update Project 

4. Resolución de problemas


1. Si se ha instalado una nueva versión de Eclipse, verificar que se ha instalado Lombok!
2. Si se ha descomprimido el proyecto ebn otra carpeta, este proyecto NO SE COPIA a nuestro workspace, sino que queda vinculada, por eso hay que tener mucho cuidado.
3. Verificar que se apunta al JDK correcto Window - Preferences - Java - Installed JREs
 

martes, 14 de julio de 2020

La API de JPA 2.1 (VI) Persistence.xml, definiendo la conexión a algunas BDs. Maven multimódulo

Veamos como solucionar algunos casos que me han pasado y que me han requerido bastante tiempo para solucionarlos o al menos para medianamente entenderlos. Recordar que en "maven", le persistence.xml es conveniete colocarlos en "src/main/resources

Caso 1º. Acceso a H2 (en linux). Ruta absoluta


En este caso , nuestra base de datos está situado en el directorio DB del directorio del usuario (/home/usuario) y se llama "myh2", en el persistence.xml se tenía:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<persistence-unit name="myh2" transaction-type="RESOURCE_LOCAL">
  <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
     
  <properties>
    <!-- (FUNCIONA EN MODO LOCAL) property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/DBs/myh2" /> -->
    <!-- (FUNCIONA EN MODO LOCAL) property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://192.168.100.100/~/DBs/myh2" /> -->
    <!-- OJO una ruta absoluta necessita // despres del server !!! -->
    <property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://192.168.100.100//home/eduard/DBs/myh2" />
    <property name="javax.persistence.jdbc.user" value="myuser"/>
    <property name="javax.persistence.jdbc.password" value="mypassword"/>
    <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
    <!-- <property name="hibernate.hbm2ddl.auto" value="update" /> -->
    <property name="javax.persistence.schema-generation.database.action" value="none"/>
  
    <!-- Provider specific properties -->
    <property name="hibernate.show_sql" value="true" />
    <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
            
			        
  </properties>
      
 </persistence-unit>


Se pueden ver como en las líneas  5 y 6 se puede acceder de forma local y usando el mismo usuario (pues se está usando el símbolo "~" que indica que es el directorio del usuario que se ha conectado. Si nos conectamos como otro usuario, la conexión falla.

Para evitarnos sustos debemos indicar la ruta absoluta como se indica en la línea 8, donde despues de la dirección del server (o del puerto del server si se ha indicado), hay que dar doble barra "//

Caso 2º. Acceso a una BD Postgres por JNDI

JNDI permite asociar nombres a objectos. Estos objetos pueden ser contenedores de datos. En este caso particular, le decimos a nuestro Tomcat que sea él el encargado de gestionar la connexión a la base de datos. Veamos el "persistence.xml".

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<persistence-unit name="jndi_postgres" transaction-type="RESOURCE_LOCAL">
  <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
  <!-- BEGIN: FOR Data Source in Tomcat -->
  <jta-data-source>java:comp/env/mypostgres</jta-data-source>
      
  <!--????? OJO: Revisar el context.xml de webapp/META-INF que apunta al servidor 192.168.100.101 -->
        
  <!-- END:   FOR Data Source in Tomcat-->
  <properties>
    <property name="hibernate.dialect"	value="org.hibernate.dialect.PostgreSQLDialect" />
    <property name="hibernate.hbm2ddl.auto" value="update" />
    <property name="hibernate.show_sql" value="true" />				  
  </properties>
    
</persistence-unit>

Observar la línea 4 que tiene la etioqueta "<jta-data-source> le descarga la responsabilidad al JDNI. La nomenclatura empleada es "java:comp/env/nombre_recurso"

Ahora muchas propiedades han desaparecido, ya que se supone que se encarga el JNDI de apañárselas.

Para definir el JNDI, en Deployed Resources - webapp - META_INF tenemos que crear el fichero "context.xml" 



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/mypath" docBase="mypath" debug="5" reloadable="true" crossContext="true">
        
   
    <!-- PRIMER RECURSO (el que hace referencia en persistence.xml-->
    <Resource 
      name="mypostgres"
      auth="Container"
      type="javax.sql.DataSource"
      username="mysuser"
      password="mypassword"
      maxTotal="50"
      maxIdle="20"
      maxWait="10000"
      timeBetweenEvictionRunsMillis="180000"
      removeAbandonedOnMaintenance="true"
      removeAbandonedOnBorrow="true"
      driverClassName="org.postgresql.Driver"
      url="jdbc:postgresql://192.168.100.101:5432/mypostgresdb" 
    />

    <!-- SEGUNDO RECURSO -->
    <Resource 
      name="mypostgres2"
      auth="Container"
      type="javax.sql.DataSource"
      username="mysuser2"
      password="mypassword2"
      maxTotal="50"
      maxIdle="20"
      maxWait="10000"
      timeBetweenEvictionRunsMillis="180000"
      removeAbandonedOnMaintenance="true"
      removeAbandonedOnBorrow="true"
      driverClassName="org.postgresql.Driver"
      url="jdbc:postgresql://192.168.100.102:5432/mypostgres2db" 
    />
      
    
</Context>


Como se puede ver, se pueden definir múltiples recursos, en este caso el primero es el que hace referencia el "persistence.xml". Se observa que se ha delegado la URL de acceso a la BD al "context.xml".

Caso 3º. Maven multimódulo, no puede mapear las clases!

El proceso de mapeado (reconocimiento) de las clases que entran en juego en la persistencia, es un poco complejo. En principio no hay ningun problema cuanto tenemos un olo módulo maven y una sola "persistence unit".

Cuando complicamos un poco la cosa y le metemos una segunda "persistence unit" en el "persistence.xml", a la hora de crear las clases automáticamente, se lia la cosa y crea las clases en las 2 persistence units a la vez. Para solucionar esto, se puede hacer:
  1. Trabajar con esquemas, onde le decimos cada clase a que esquema pertenece.
  2. Definir con la etiqueta <class> cada clase que interviene en cada persistence unit.
Si ademas tenemos bastantes módulos y las clases de cada persistence unit las tenemos separadas en módulos... entonces únicamente he podido conseguir que mapaeara las clasess creando una etiqueta <class> con cada una de las clases a mapear en el persistence unit. Si alguien encuentra una solución mejor que me lo diga. También se podria utilizar la etiqueta <jar-file> si somos capaces de crear un jar de cada módulo.


miércoles, 27 de mayo de 2020

Putty: Copiar y pegar en Putty de Linux. Problema: PuTTY: unable to load font "server:fixed"

1. Copia y pega


Según Capy:

1. Con el ratón seleccionamos el texto a copiar (dentro de la ventana de putty)
2. Nos vamos a la aplicación donde queramos copiar y apretamos la rueda que está en el botón central y se pega.
3. También podemos pegar a putty desde otra aplicación, apretando la rueda.

Muuuuuuuuuuuuuuuy útil.

2. PuTTY: unable to load font "server:fixed"


Para cada uno de los servidores:
  • Ir a Category: Session
  • Marcar con el boton izquierdo del raton (sobre el nombre del servidor)
  • Apretar el boton Load
  • En Category:Fonts
  • Apretar el boton Change ... de "Font used for ordinary text"
Y seleccionar la fuente que se muestra junto con el tamaño y darle al boton OK

Le damos al boton Open y a funcionar








Ubuntu Server. Definir IP estática

Cuando se copian máquinas virtuales de Ubuntu Server 18.04, parece ser que la configuración de la dirección IP ya no se puede cambiar por el entorno gráfico, ya que cuando se reinicia se pierde la configuración de la IP.

Para ello he tenido que recurrir al blog de Gorka Izquierdo.

En resumidas cuentas hay que hacer lo siguiente:

1. Buscar en /etc/netplan un fichero que termine en .yaml

En mi caso se llama 50-cloud-init.yaml. su contenido es:

    ethernets:
        ens192:                        # verificar nombre arjeta de red con ifconfig   
            addresses:
                - 192.168.28.201/24    # IP estática a asignar
            gateway4: 192.168.28.100   # IP del gateway o puerta de enlace
            nameservers:
                addresses:
                    - 192.168.28.207   # IPs de los DNS
                    - 192.168.28.210
                search:
                    - mi.dominio
    version: 2


2. Ejecutar ifconfig para obtener el nombre de la tarjeta de red

Obtenenos el nombre de nuestra tarjeta de red, en este caso ens192


 ens192: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.28.201  netmask 255.255.255.0  broadcast 192.168.28.255
        inet6 fe80::250:56ff:feb5:3a1e  prefixlen 64  scopeid 0x20<link>
        ether 00:50:56:b5:3a:1e  txqueuelen 1000  (Ethernet)
        RX packets 7950  bytes 580000 (580.0 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 371  bytes 46630 (46.6 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 842  bytes 218267 (218.2 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 842  bytes 218267 (218.2 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


3. Editar el fichero con el editor nano

Este editor funciona con putty y hay que darle el nombre de la tarjeta de red, y las IPs a asignarle al servidor, del gateway y de los DNS


4. Activar la configuración

Hay  que aplicar cambios y reiniciar la red para ello ejecutamos estos 2 comandos


netplan apply

systemctl restart networking

y ya está.