Mostrando entradas con la etiqueta java. Mostrar todas las entradas
Mostrando entradas con la etiqueta java. Mostrar todas las entradas

jueves, 28 de noviembre de 2024

Python (XV) utilizar librerias java (INCOMPLETO)

 Para ello se opta por utilizar Pyjnius, py4j, jpype, scyjava ..


1. Descargar los jars a una carpeta

Primeramente se instala maven en ubuntu:

sudo apt install maven -y

Creamos una carpeta que será la de nuestro proyecto, nos situamos dentro de ella

Vamos a mavencentral y buscamos nuestra dependencia por ejempo itext7 y descargamos el pom.xml en la carpteta


Veamos un ejemplo de pom.xml para poder descargar la libreria itext7

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>mi-proyecto-itext</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <itext.version>9.0.0</itext.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>com.itextpdf</groupId>
      <artifactId>itext7-core</artifactId>
      <version>${itext.version}</version>
      <type>pom</type>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <release>17</release>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>


Ejecutamos 

mvn dependency:copy-dependencies -DoutputDirectory=target/dependencies

si no se especifica -DoutputDirectory entonces lo descarga en target/dependencies

o tambien

mvn dependency:resolve -U

pero las copia en ~/.m2/repository/com/itextpdf/itext7-core/7.2.5/itext7-core-7.2.5.jar

Y ya tenemos las dependencia en el directorio que hemos indicado. Ahora falta usar dichos jars en python


2. Usar las librerias en python

 

martes, 7 de junio de 2022

Clave 2.0 Java (2) Configurar el proyecto de prueba

 Ahora que ya hemos podido arrancar la primera pantalla, hay que configurar la aplicación.

1. Configurar Tomcat con SSL

Vamos a configurar el Tomcat 8.5 para que admita protocolo https, pero vamos a utilzar el certificado que nos han suministrado.

Hay que ver los certificados que se guadan en el "KeyStore.jks" del directorio de configuración "Config". Ejecutamos:
 
keytool -list -keystore '<Ruta>/KeyStore.jks

le damos el password "local-demo"

y nos muestra que hay 2 entradas ("local-demo-cert-es" y "sello kit de pruebas (ac sector público)") 

Keystore type: jks

Keystore provider: SUN

Your keystore contains 2 entries

local-demo-cert-es, 16/11/2017, PrivateKeyEntry, 

Certificate fingerprint (SHA-256): B6:DD:C5:7D:A5:06:17:7A:E3:3B:9B:E9:2C:45:38:14:B7:98:3D:09:B8:A9:2E:34:3D:F5:BB:E3:3A:F3:53:44

sello kit de pruebas (ac sector público), 17/05/2022, PrivateKeyEntry, 

Certificate fingerprint (SHA-256): F3:ED:ED:01:F6:E5:C6:7B:AD:7F:26:76:3A:8E:D9:6F:1A:A1:FC:B1:CB:EB:87:86:D1:D8:36:C0:EA:BD:A3:1C

Warning:

<local-demo-cert-es> uses the SHA1withRSA signature algorithm which is considered a security risk. This algorithm will be disabled in a future update.

The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore CLAVE20_CONF/SP/KeyStore.jks -destkeystore CLAVE20_CONF/SP/KeyStore.jks -deststoretype pkcs12".

Vamos a utilizar el certificado con alias "local-demo-cert-es" como certificado del servidor.

Vamos a Servers -Tomcat v8.5 Server at localhost-config y modificamos el fichero server.xml


Añadimos las líneas que no estan comentadas sirviendo de ejemplo de las primeras que están comentadas.


<!--
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150" SSLEnabled="true">
        <SSLHostConfig>
            <Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
                         type="RSA" />
        </SSLHostConfig>
    </Connector>
    -->
    
    <Connector 
        SSLEnabled="true" 
        maxThreads="150" 
        port="8443" 
        protocol="org.apache.coyote.http11.Http11NioProtocol" 
        scheme="https" 
        secure="true">
        <SSLHostConfig>
            <Certificate 
                 certificateKeyAlias="local-demo-cert-es" 
                 certificateKeystoreFile="ruta.../Config/KeyStore.jks" 
                 certificateKeystorePassword="local-demo" 
                 type="RSA"/>
        </SSLHostConfig>
    </Connector>
    

Hay que darle la ruta correcta al keystore en "certificateKeystoreFile"!!!

Ejecutamos (Run As- Run On Server) y arranca con protocolo http. Para ver si va con https abrimos una pestaña del navegador y le indicamos https://localhost:8443/SP2 y debería de arrancar, dando los problemas de siempre que no se confía en ese certificado, pero al final arranca






miércoles, 1 de junio de 2022

Clave 2.0 Java (1) Instalar el proyecto de prueba

1. Preinstalación

1. Descargar el proyecto de prueba

Vamos a la PAE y descargamos el "Paquete de integracion Java 8" del 19/5/2022

2. Creamos un Workspace (WS_CLAVE) y dentro de él, una carpeta (Por ejemplo SP2 que es el "artifactId" que se indica en el pom.xml) dentro de un Workspace Java 

3. Abrimos el fichero zip descargado y copiamios el contenido de  "Paquete_Integracion_Java_Clave_2_0" dentro de esa carpeta


4. Ahora desde Eclipse importamos (File - Import -Maven - Existing Maven Projects) Y le indicamos la carpeta SP2

5. Una vez importado , hay que seleccionar el Java 1.8 en Eclipse

6.a. Establecemos la variable de entorno CLAVE_SP2_CONFIG_REPOSITORY que apunte donde se encuentra la carpeta Config. En este caso es: /home/ximo/MyWorkspaces/WS_CLAVE/SP2/Config/. Para ello editamos el fichero ~/.profile y le añadimos esta línea

export CLAVE_SP2_CONFIG_REPOSITORY="$HOME/MyWorkspaces/WS_CLAVE/SP2/Config/"

Para asegurar que ha cogido las variables de entorno, en una ventana de shell escribimos

source ~/.profile

NOTA: Para no tener problemas con la localización de la carpeta "Config", se podría copiar dicha carpeta a un ruta que no dependiera del proyecto como /home/ximo/CLAVE20_CONF, de esta manera si quisiéramos tener una segunda versión del proyecto, no tendríamos que tocar nada.


6.b. Alternativamente a la opción a), podemos modificar el fichero src/main/resources/spEnvironmentContext y cambiar

<constructor-arg value="#{ systemProperties['CLAVE_SP2_CONFIG_REPOSITORY'] ?: systemEnvironment['CLAVE_SP2_CONFIG_REPOSITORY'] }" />

por

<constructor-arg value="/home/ximo/MyWorkspaces/WS_CLAVE/SP2/Config/" />

7. A veces puede dar problemas que no encuentra algunas dependencias que se enuentran en la carpeta local "Dependencias"; si es el caso hay que modificar el pom.xml, casi al final del archivo, en la zona de <repositories> pues es incapaz de encontrar las dependencias, para ello cambiamos 

<url>file://Dependencias</url>  por

<url>file://${project.basedir}/Dependencias  </url>


y guardamos el fichero pom.xml

7. Ahora clicamos con el boton derecho sobre el proyecto Maven - Update Project  y deberian de desaparecer los problemas de compilación

8. Abrir la ventana de Servers (si no esta hay que añadirla en Window -Show View -Other - Servers ) y añadir un servidor Tomcat 8.5 y en  

9. Clicamos con el boton derecho sobre el proyecto Run As - Run on Server, seleccionar el Tomcat 8.5 que hemos instalado y al menos arranca:

10. Comprobamos que tengamos esta estructura de ficheros



Y desde el sistema operativo


Ahora viene la parte difícil de entender lo que hace.

2. Posibles problemas (si no ha arrancado)

1. Si sale este error:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'placeholderConfig' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Cannot resolve reference to bean 'securityConfigFileWithPath' while setting bean property 'locations' with key [0]; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1021E: A problem occurred whilst attempting to access the property 'spConfigRepository': 'Error creating bean with name 'spConfigRepository' defined in class path resource [spEnvironmentContext.xml]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [java.lang.String]: Constructor threw exception; nested exception is java.lang.NullPointerException: Cannot invoke "java.lang.StringBuffer.toString()" because "buffer" is null'

Hay que vigilar en la "Console" a ver si aparece un a referencia a un JDK que no sea el 1.8

INFORMACIÓN: Java Home:                         /home/edu/MyPrograms/eclipse2022-03/plugins/org.eclipse.justj.openjdk.hotspot.jre.full.linux.x86_64_17.0.2.v20220201-1208/jre

Como se puede ver hace referencia a java 17. Por tanto hay que arreglar el Java Build path para que apunte donde toca (jdk o jre 8).

2. Si sale este error:

org.springframework.beans.factory.BeanInitializationException: Could not load properties; nested exception is java.io.FileNotFoundException: /home/edu/MyWorkspaces/WS_CLAVE/SP2/ConfigsecurityConf.xml (No existe el archivo o el directorio)

Es que nos hemos olvidado de de indicar en el punto 6.a o 6.b la barra final (/) del path
/home/ximo/MyWorkspaces/WS_CLAVE/SP2/Config/

A veces parece que está bien escrito la ruta anterior y no lo está. Vale la pena entrar en un navegador de archivos y copiar la ruta y pegarla. Estos errores dan mucha guerra y son difíciles de encontrar

viernes, 13 de mayo de 2022

Java REST client (2) :GET con autorización de "token"

 Ahora toca crar una petición con GET insertando el token en la cabecera (de tipo Authorisation), y atacando a una url diferente con distintos nombres de operacion.

Para simplficar suponemos que el token es "mitoken" y la url de servicio es:

https://urlserviciodeprueba/api/padron/motivospeticion 

sindo "motivosoperacion" el nombre de la operacion

Con  "curl" sería para una operación sin parámetros:


curl https://urlserviciodeprueba/api/padron/motivospeticion  -H "Authorization: Bearer mitoken"

y para una operacion con  parámetros

curl "https://urlserviciodeprueba/api/padron/volantefirmado?filtros[0].Nombre=CodigoProvincia&filtros[0].Valor=99&filtros[1].Nombre=CodigoMunicipio&filtros[1].Valor=999&filtros[2].Nombre=TipoDocumentoINE&filtros[2].Valor=1&filtros[3].Nombre=Documentacion&filtros[3].Valor=11111111H" -H "Authorization: Bearer mitoken"


Veamos todo el código en java tanto para el post anterior como este de forma unificada

hay que tener en cuenta de meter en gradle las dependencias de apache http client y Jackson (tambien puede falta algunas como lombok..)

//Apache
implementation 'org.apache.httpcomponents:httpclient:4.5.13'
    
/* Jackson */
implementation "com.fasterxml.jackson.core:jackson-core:2.13.2"
implementation "com.fasterxml.jackson.core:jackson-annotations:2.13.2"
implementation "com.fasterxml.jackson.core:jackson-databind:2.13.2.2"

Y el codigo java

package ph.utils;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.Getter;

public class HttpXimo {
	private CloseableHttpClient httpclient = null;
	@Getter private String urlAuth = null;
	@Getter private String urlService = null;

	public HttpEdu(String urlAuth, String urlService) {
		this.urlAuth = urlAuth;
		this.urlService = urlService;
		try {
			httpclient = HttpClients.createDefault();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public String get(String url, String operation, String[] paramNames, String[] paramValues, String token) throws Exception {
		String urlWithParams=url+operation;
		for (int i=0; i<paramNames.length; i++) {
			String myUnionChar = "&";
			if (i==0) myUnionChar="?";
			urlWithParams+= myUnionChar + paramNames[i] + "=" + paramValues[i];
		}	
		System.out.println(urlWithParams);
		HttpGet request = new HttpGet(urlWithParams);
		//String auth = "Authorization: Bearer " + token;
		//byte[] encodedAuth = Base64.encodeBase64(
		//  auth.getBytes(StandardCharsets.ISO_8859_1));
		//String authHeader = "Basic " + new String(encodedAuth);
		String authHeader = "Bearer " + token;
		request.setHeader(HttpHeaders.AUTHORIZATION, authHeader);
		
		System.out.println("request.uri=" + request.getURI());
		for (Header header : request.getAllHeaders()) System.out.println("HEADER=" + header.getName() + "====" + header.getValue());

		//HttpClient client = HttpClientBuilder.create().build();
		HttpResponse response = httpclient.execute(request);
		HttpEntity entity = response.getEntity();
		InputStream in = entity.getContent();
		String s = new String(in.readAllBytes());
		System.out.println("ENTITY=" + s);
		// do something useful with the response body
		// and ensure it is fully consumed
		EntityUtils.consume(entity);
		return s;

	}
	
	public String post(String url, String[] paramNames, String[] paramValues) throws Exception {
		
		HttpPost httpPost = new HttpPost(this.urlAuth);
		List<NameValuePair> nvps = new ArrayList<>();

		//Add form parameters
		for (int i = 0; i < paramNames.length; i++)
			nvps.add(new BasicNameValuePair(paramNames[i], paramValues[i]));
		
		//Encode url
		httpPost.setEntity(new UrlEncodedFormEntity(nvps));
		
		//Get response
		CloseableHttpResponse response2 = httpclient.execute(httpPost);
		HttpEntity entity2 = response2.getEntity();
		
		//Read the response from input stream
		InputStream in = entity2.getContent();
		String s = new String(in.readAllBytes());
		
		//Close input stream
		EntityUtils.consume(entity2);
		return s;

	}
	
	public String getKeyValue(String jsonString, String key) throws JsonMappingException, JsonProcessingException {
		ObjectMapper  objMapper= new ObjectMapper();
		Map<String,String>mp=new HashMap<>();
		mp=objMapper.readValue(jsonString, mp.getClass());
		return mp.get(key);
	}	
	
	
	public static void main(String[] args) throws Exception {
		HttpEdu myHttp = new HttpXimo(
				"https://urlautorizaciondeprueba/identity/connect/token",
				"https://urlserviciodeprueba/api/padron/");
		String[] names = { "username", "password", "grant_type", "scope", "client_id", "client_secret" };
		String[] values = { "miUsuario", "miClave", "password", "miEmpresa",
				"yoMismo", "1234567890" };

		String strResponse= myHttp.post(myHttp.getUrlAuth(), names, values);
		System.out.println(strResponse);
		String token =myHttp.getKeyValue(strResponse, "access_token");
		System.out.println("TOKEN="+token);
		
		//===================MOTIVOS PETICION==============================
		String[] names1 = {};
		String[] values1 = {};
		
		strResponse= myHttp.get(myHttp.getUrlService(), "motivospeticion", names1, values1, token);
		System.out.println(strResponse);
		
		//===================VOLANTE FIRMNADO==============================
		String[] names2 = { "filtros[0].Nombre", "filtros[0].Valor", "filtros[1].Nombre", "filtros[1].Valor", 
				"filtros[2].Nombre", "filtros[2].Valor","filtros[3].Nombre", "filtros[3].Valor" };
		String[] values2 = { "CodigoProvincia", "99", "CodigoMunicipio", "999",
				"TipoDocumentoINE", "1", "Documentacion", "11111111H"  };
				
		strResponse= myHttp.get(myHttp.getUrlService(), "volantefirmado", names2, values2, token);
		System.out.println(strResponse);
		
		
	}

}









Java REST client (I) :Post con parametros de formulario

 1. Introducción

Tengo que conseguir un "token" que me servira para consumir la REST api para un aplicación que estoy intentando integrar con otra.

Para ello me suministran:

1. la URL a la cual llamar (por ejemplo ficticiamente: 

 https://empresaauthorization.es/identity/connect/token

2. Usuario y contraseña como parámetros:

Parametro:  "username" valor: "miUsuario"

Parametro: "password"  valor: "miClave"

3. Otros parametros adicionales

Parametro:  "grant_type" valor: "password"

Parametro: "scope"  valor: "miAplicacion"

Parametro: "client_id"  valor: "yoMismo"

Parametro: "client_secret"  valor: "AH0124EF5832HA321"



2. Llamadas

Con "curl" se haría así:

curl -X POST --data "username=miUsuario&password=miClave&grant_type=password&scope=miAplicacion&client_id=yoMismo&client_secret=AH0124EF5832HA321" -k https://empresaauthorization.es/identity/connect/token

En cambio en Java he creado este módulo que me ha hecho penar:

En gradle le he dado esta dependencia

implementation 'org.apache.httpcomponents:httpclient:4.5.13'

package ph.utils;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;

import org.apache.http.util.EntityUtils;

public class HttpXimo {
	private CloseableHttpClient httpclient = null;
	private String url = null;

	public HttpEdu(String url) {
		this.url = url;
		try {
			httpclient = HttpClients.createDefault();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public String post(String[] paramNames, String[] paramValues) throws Exception {
		
		HttpPost httpPost = new HttpPost(this.url);
		List<NameValuePair> nvps = new ArrayList<>();

		//Add form parameters
		for (int i = 0; i < paramNames.length; i++)
			nvps.add(new BasicNameValuePair(paramNames[i], paramValues[i]));
		
		//Encode url
		httpPost.setEntity(new UrlEncodedFormEntity(nvps));
		
		//Get response
		CloseableHttpResponse response2 = httpclient.execute(httpPost);
		HttpEntity entity2 = response2.getEntity();
		
		//Read the response from input stream
		InputStream in = entity2.getContent();
		String s = new String(in.readAllBytes());
		
		//Close input stream
		EntityUtils.consume(entity2);
		return s;

	}

        public static void main(String[] args) throws Exception {
		HttpXimo myHttp = new HttpEdu("https://empresaauthorization.es/identity/connect/token");
		String[] names = { "username", "password", "grant_type", "scope", "client_id", "client_secret" };
		String[] values = { "Parametro", "miClave", "password", "miAplicacion",
				"yoMismo", "AH0124EF5832HA321" };

		System.out.println("HOLA=" + myHttp.post(names, values));
	}

	

Y la respuesta que obtenemos es esta (en formato JSON)

{"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IjF6ZTUxZnlxcFFZVkJVaTJlMzVTRmVxX0J0byIsImtpZCI6IjF6ZTUxZnlxcFFZVkJVaTJlMzVTRmVxX0J0byJ9.eyJjbGllbnRfaWQiOiJJbnRlcnB1YmxpY2EiLCJzY29wZSI6IkludGVycHVibGljYSIsInN1YiI6IjMzOTBlYjAyLTRiM2ItNDVmMy1iMzk3LWEzMDhmOWQ2YTNlNCIsImFbciI6WyJwYXNzd29yZCJdLCJhdvRoX3RpbWUiOjE2NTI0MjIxMjgsImlkcCI6Imlkc3J2IiwicHJlZmVycmVkX3VzZXJuYW1lIjoiVGF2ZXJuZXNWYWxsZGlnbmFTZWRpIiwiZW1haWwiOiJub0Buby5jb20iLCJlbWFpbF92ZXJpZmllZCI6InRydWUiLCJwaG9uZV9udW1iZXIiOiIxMjM0NTY3ODkiLCJwaG9uZV9udW1iZXJfdmVyaWZpZWQiOiJ0cnVlIiwiVXN1YXJpbyI6IjM0MyIsIlNlcnZpZG9yIjoiMiIsIkRvbWluaW8iOiI0IiwiRW50aWRhZCI6IjM0MyIsInJvbGUiOlsiRG9tYWluIiwiSW50ZXJwdWJsaWNhIiwiUGFkcm9uIl0sImp0aSI6ImQxNzNiZTY5ZGRjOWUxMDYyNDkzZjZlYzNiMDgxMWIzIiwiaXNzIjoiaHR0cHM6Ly9pbnRlcnB1YmxpY2FhdXRob3JpemF0aW9uLmRpdmFsLmVzL2lkZW50aXR5IiwiYXVkIjoiaHR0cHM6Ly9pbnRlcnB1YmxpY2FhdXRob3JpemF0aW9uLmRpdmFsLmVzL2lkZW50aXR5L3Jlc291cmNlcyIsImV4cCI6MTY1MjQyNTcyOCwibmJmIjoxNjUyNDIyMTI4fQ.ewb85x5PDL6gGvhdeZUlhn15DfGfZ4TgeTB7nY5RvAmUF0tFUs-gG38cZ5LcF87yVALlPzB8gwKMbVHfXVseO2cXpiQTxlF4xLF006aDXT1zN9bTIcFb55BUyDFeJmQyzW_euUi8KX0kKDK3XCkS01LvK_7NGIGeL_M78m7_4LumqnurWUAv2JEApIBZkBFXZ_zREk1LzJt1Pqlt6muTcS8XEZsLXK8EoTNjWkkHZzU0VdXArwSy-RKQRm3HbOr43eV96eMAKudoY8nbAeeqzsS5_qLk7soNUihwlvoM9A-EdjDsySFf_KxTtWAyemkdoE5PRPTAwmXoYPBuwKOwdw","expires_in":3600,"token_type":"Bearer"}

Para leer la respuesta se añade este código sustituyendo al método "main"


        public String getKeyValue(String jsonString, String key) throws JsonMappingException, JsonProcessingException {
		ObjectMapper  objMapper= new ObjectMapper();
		Map<String,String>mp=new HashMap<>();
		mp=objMapper.readValue(jsonString, mp.getClass());
		return mp.get(key);
	}	
	
	
	public static void main(String[] args) throws Exception {
		HttpXimo myHttp = new HttpEdu("https://interpublicaauthorization.dival.es/identity/connect/token");
		String[] names = { "username", "password", "grant_type", "scope", "client_id", "client_secret" };
		String[] values = { "Parametro", "miClave", "password", "miAplicacion",
				"yoMismo", "AH0124EF5832HA321" };
String strResponse= myHttp.post(names, values); System.out.println(strResponse); String token =myHttp.getKeyValue(strResponse, "access_token"); System.out.println(token); }

Ahora ya tenemos el token, vamos a por la segunda parte que consiste en utilizar este token para usar la REST API











jueves, 16 de diciembre de 2021

La API de JPA 2.1 (IX) JPA-JNDI sin persistence.xml

 0. Introducción

Continuamos del post anterior, pero ahora tenemos que utilizar JNDI en una aplicación web, en este caso Vaadin.

Veamos la estructura de ficheros ya vista en otro blog

src
   |->main
   |   |->webapp
   |   |   |->WEB-INF       Not used (can be deleted)
   |   |   |   |->beans.xml Not used 
   |   |   |->skins
   |   |   |   |->ui
   |   |   |   |->content
   |   |   |->META-INF
   |   |   |   |>context.xml (JNDI pool of connections)
   |   |   |->imgs
   |   |   |   |->enterprise (or any particular folder with images)
   |   |   |->icons
   |   |   |   |->flags (or any particular folder with icons)
   |   |->resources
   |   |   |->view (in yaml or any partiular folder with some info)
   |   |   |->reports (or any partiular folder with jasper reports)
   |   |   |->readme (or any partiular folder with some info)
   |   |   |->properties (property files)
   |   |   |   ->control_post.properties
| | |->META-INF | | | |->services | | | |->com.vaadin.flow.server.VaadinServiceInitListener | | | |->persistence.xml | | |->i18n (all teh internationalization resources) | | | |->file_en.properties ; file_es.properties | | |->docs (any doc ) | | |->simplelogger.properties | |->java | | |->ui | | |->openadmin |->test frontend |->tone-edu (test with js) | |->tone-test.js |->three-edu (test with js) | |->three-test.js |->apex-charts (test with js) | |->apex-charts-test.js |->styles (all the css defined) | |->my-defined.css.css |->src (empty) |->generated | |->vaadin.ts |->font-awesome | |->webfonts, svgs, sprites, scss, metadata, less, js, css.. gradle.properties build.gradle

En este caso com es lógico no utilizaremos el presistence.xml


1. Ficheros importantes


En src/main/webapp/META-INF tenemos context.xml. En este ejemplo solo utilizaremos solo el recurso "control_post"

 
<Context path="/openweb" docBase="openweb"
        debug="5" reloadable="true" crossContext="true">
    <Resource 
      name="control_post"
      auth="Container"
      type="javax.sql.DataSource"
      username="my_user"
      password="my_password"
      maxTotal="50"
      maxIdle="20"
      maxWait="10000"
      timeBetweenEvictionRunsMillis="180000"
      removeAbandonedOnMaintenance="true"
      removeAbandonedOnBorrow="true"
      driverClassName="org.postgresql.Driver"
      url="jdbc:postgresql://192.1.1.1:5432/openweb" 
    />
    
    <Resource 
      name="other-persistence-unit"
      auth="Container"
      type="javax.sql.DataSource"
      username="other_user"
      password="other_password"
      maxTotal="50"
      maxIdle="20"
      maxWait="10000"
      timeBetweenEvictionRunsMillis="180000"
      removeAbandonedOnMaintenance="true"
      removeAbandonedOnBorrow="true"
      driverClassName="org.postgresql.Driver"
      url="jdbc:postgresql://192.1.1.2:5432/other_db" 
    />
        
</Context>



En src/resources/properties metemos este fichero control_post.properties

#-----------------------------------------------------------------------------
#1. General Properties
persistence.unit.name=            control_post
persistence.provider.class.name=  org.hibernate.jpa.HibernatePersistenceProvider
jta.datasource.name=              control_post
#non.jta.datasource=               
#mapping.file.names=
#jar.file.urls=
#persistence.unit.root.url
managed.classes=                  openadmin.model.csv.AytosCSV;\
                                  openadmin.model.csv.CSVLog;\
                                  openadmin.model.sedipualba.Expedient;\
                                  openadmin.model.sedipualba.Document

exclude.unlisted.classes=         true	
#shared.cache.mode=
#-----------------------------------------------------------------------------
#Properties not included in datasource
hibernate.dialect=                org.hibernate.dialect.PostgreSQLDialect
#hibernate.hbm2ddl.auto=           update
hibernate.hbm2ddl.auto=           none
hibernate.show_sql=               true


En src/main/java/utils tenemos PersistenceUnitInfoEdu que es la clase que va a recoger todas las propiedades de la conexión e hibernate. Observar la línea con el fondo amarillento que es la que se encarga de recoger el recurso JNDI de Tomcat. Observar tambien la ruta en rojo para buscar el recurso que quedaría: "java:/comp/env/control_post"


package utils;

import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.SharedCacheMode;
import javax.persistence.ValidationMode;
import javax.persistence.spi.ClassTransformer;
import javax.persistence.spi.PersistenceUnitInfo;
import javax.persistence.spi.PersistenceUnitTransactionType;
import javax.sql.DataSource;

import org.apache.commons.lang3.StringUtils;

import lombok.Getter;
import lombok.Setter;
import openadmin.utils.basic.StringUtilsEdu;

public class PersistenceUnitInfoEdu implements PersistenceUnitInfo {
    
    public static String JPA_VERSION = "2.2";
    @Getter @Setter private String persistenceUnitName; //OK
    @Getter @Setter private PersistenceUnitTransactionType transactionType   = PersistenceUnitTransactionType.RESOURCE_LOCAL; //OK
    @Getter @Setter private String persistenceProviderClassName="org.hibernate.jpa.HibernatePersistenceProvider"; //OK
    @Getter @Setter private DataSource jtaDataSource=null; //OK a falta de JNI
    @Getter @Setter private DataSource nonJtaDataSource=null; //OK a falta del no JNI
    @Getter @Setter private List<String> mappingFileNames = new ArrayList<>(); //OK
    @Getter @Setter private List<URL> jarFileUrls=null; //OK
    @Getter @Setter private URL persistenceUnitRootUrl=null; //OK
    @Getter @Setter private List<String> managedClassNames = new ArrayList<>(); //OK
    @Getter @Setter private boolean excludeUnlistedClasses=false; //OK
    @Getter @Setter private SharedCacheMode sharedCacheMode=null; //OK
    @Getter @Setter private ValidationMode validationMode=ValidationMode.AUTO; //OK
    @Getter @Setter private Properties properties=null; //OK
    @Getter @Setter private String persistenceXMLSchemaVersion=JPA_VERSION; //OK
    @Getter @Setter private ClassLoader classLoader=null; //OK
    @Getter @Setter private List<ClassTransformer> transformers = new ArrayList<>(); //OK addTransformes
    @Getter @Setter private ClassTransformer transformer=null;
    @Getter @Setter private ClassLoader newTempClassLoader=null; //OK
    
    public PersistenceUnitInfoEdu(String persistenceUnitName, List<String> managedClassNames, boolean excludeUnlistedClasses, Properties properties) {
        this.persistenceUnitName = persistenceUnitName;
        this.managedClassNames = managedClassNames;
        this.excludeUnlistedClasses=excludeUnlistedClasses;
        this.properties = properties;
    }

	@Override
	public boolean excludeUnlistedClasses() {
		return excludeUnlistedClasses;
	}

	@Override
	public void addTransformer(ClassTransformer transformer) {
		// TODO Auto-generated method stub
	}

	public PersistenceUnitInfoEdu(Properties props) throws Exception {
        this.persistenceUnitName = props.getProperty("persistence.unit.name").trim();
        this.persistenceProviderClassName=props.getProperty("persistence.provider.class.name").trim();
        
        String dtSrc=props.getProperty("jta.datasource.name","").trim();
        /*
        if (dtSrc.length()>0) { 
        	Context initContext = new InitialContext();
        	Context envContext  = (Context)initContext.lookup("java:/comp/env");
        	//DataSource ds = (DataSource)envContext.lookup("jdbc/myoracle");
        	this.jtaDataSource=(DataSource)envContext.lookup(dtSrc);
        }
        */	
        if (dtSrc.length()>0) { 
        	InitialContext cxt = new InitialContext();
        	if ( cxt == null ) {
        	   throw new Exception("Uh oh -- no context!");
        	}

        	this.jtaDataSource= (DataSource) cxt.lookup( "java:/comp/env/"+dtSrc );

        	if ( this.jtaDataSource == null ) {
        	   throw new Exception("Data source not found!");
        	}
        	
        }
        
        String[] managedCls=StringUtilsEdu.splitAndTrim(props.getProperty("managed.classes"),";");
        this.managedClassNames =  Arrays.asList(managedCls);
        
        this.excludeUnlistedClasses=Boolean.parseBoolean(props.getProperty("exclude.unlisted.classes").trim());
     
        this.properties = props;
    }
	
	
}


En src/main/java/utils tenemos JPANoPersistenceUtils que permite obtener las EntitymanagerFactory


package utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;


import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;
import javax.persistence.spi.PersistenceUnitInfo;

import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
import org.hibernate.jpa.boot.internal.PersistenceUnitInfoDescriptor;



public class JPANoPersistenceUtils {
	
	public static PersistenceUnitInfoEdu getPsUnitInfo(String persistenceUnitName, List<String> managedClassNames, boolean excludeUnlistedClasses, Properties properties) {
		return new PersistenceUnitInfoEdu(persistenceUnitName, managedClassNames, excludeUnlistedClasses, properties);
	}
	
	public static PersistenceUnitInfoEdu getPsUnitInfo (Properties properties) throws Exception {
		return new PersistenceUnitInfoEdu(properties);
	}
	
	public static EntityManagerFactory getEntityManagerFactory(PersistenceUnitInfo psUnitInfo) {
		Map<String, Object> configuration = new HashMap<>();
		return new EntityManagerFactoryBuilderImpl(
		          new PersistenceUnitInfoDescriptor(psUnitInfo), configuration)
		          .build();
	}
	
	public static EntityManagerFactory getEntityManagerFactory(String persistenceUnitName, List<String> managedClassNames, boolean excludeUnlistedClasses, Properties properties) {
		PersistenceUnitInfo persistenceUnitInfo = getPsUnitInfo(persistenceUnitName,managedClassNames,excludeUnlistedClasses,properties);
		return getEntityManagerFactory(persistenceUnitInfo);
	}
	
	public static EntityManagerFactory getEntityManagerFactory(Properties properties) throws Exception {
		PersistenceUnitInfo persistenceUnitInfo = getPsUnitInfo(properties);
		return getEntityManagerFactory(persistenceUnitInfo);
	}
	
	

	public static void main(String[] args) {
		List<String>classes=new ArrayList<String>();
		classes.add("openadmin.utils.nopersistencexml.Test");
		EntityManagerFactory emf=getEntityManagerFactory("my-h2",classes,true,MyConnectionProps.getPropsH2());
		
		
		EntityManager em=emf.createEntityManager();
		
		//Query q=em.createNativeQuery("SELECT * FROM TEST");
		Query q=em.createQuery("SELECT t FROM Test t WHERE t.id<1000");
		List<Test> ltest=q.getResultList();
		for (Test t:ltest) System.out.println(t.getId()+"-"+ t.getName());
			
		em.close();
		emf.close();
	}

}


Veamos una clase de prueba para abrir una conexión.OJO, está clase se debe de llamar dentro de una aplicacion web en marcha. Observar como se obtiene la ruta al fichero de propiedades "control_post.properties" que se encuentra dentro del directorio "properties". Solamante se crea una EntityManagerFactory y a partir de esta una EntityManager. 


 package utils;

import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;


import openadmin.utils.nopersistencexml.JPANoPersistenceUtils;

public class Test {

  public static void main(String[] args) {
      String propsPath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
      propsPath += File.separator + "properties"+File.separator+ "control_post.properties";
      Properties controlProps=new Properties();
      try {
          controlProps.load(new FileInputStream(propsPath));
          EntityManagerFactory factory = JPANoPersistenceUtils.getEntityManagerFactory(controlProps);
          EntityManager em = factory.createEntityManager();
          em.close();
          //Do some stuff
          factory.close();
      } catch (Exception e) {
          e.printStackTrace();
      }	
    }
}