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();
      }	
    }
}


Thread fácil (1)

 Segun stackoverflow, esta es una manera fácil de hacer threads en java


new Thread(() -> {
  try {
    this.share = FirmadocUtils.getSMBShare (this.FirmadocProps);
   
    FirmadocUtils.persistAllCSVsSamba(this.share, this.FirmadocProps,this.daoCSVLog);
  } catch (Exception e) {e.printStackTrace();}
}).start();




miércoles, 15 de diciembre de 2021

AYTOS-FIRMADOC-FACE: Tablas importantes y ficheros

1. FIRMADOC

Esquema DBO

BIB_AY.IDX_IMP  Guarda el codigo de verificacion CSV

-> IDX_IMP.IM_IDX-> IDX.IDX_ID

  • IIM_IDX: Id (PK) y nombre del documento ejemplo 498589(.PDF)
  • IIM_CVA: Código de verificación documento (CSV)
  • IIM_CRC: Otro código complementario

BIB_AY.FIRM  Guarda las firmas del documento
  • FIR_IDX: id del documento = BIB_AY.IDX_IMP.IM_IDX  
  • FIR_FCH: Fecha de la firma 
  • FIR_UOR: Firmantes = ADMDDA.A_ORG_UOR.UOR_COD ( cargo=UOR_NOM)
  • FIR_UOR_SUS: Firmante sustituto = ADMDDA.A_ORG_UOR.UOR_COD ( cargo=UOR_NOM)
  • FIR_USU: Firmantes (Usuario) = ADMDDA.USU.USU_IDE  ( cargo=USU_NOM)

BIB_AY.IDX (Nombre del documento +  relaciones

  • IDX_ID: Id PK = BIB_AY.IDX_IMP.IM_IDX  
  • IDX_ALI: "Nombre del documento (Relaciones de transferencias)
  • IDX_TDO:  ->ADMDDA.TDO.TDO_ID (descrip=TDO_DES (Relaciones de transferencias)
  • IDX_CP1: "Identificadores:"
  • IDX_FFD: Fecha y hora de firma del documento (SI nulo, no firmado)
  • IDX_FCH: Fecha para localizar la carpeta del documento (AAAAMMDD)

  • BIB_AY.SIG (Firma binaria)

  • SIG_ID: Id PK = BIB_AY.FIR.FIR_SIG
  • SIG_CNT Firma binaria

  • ADMDDA
    .A_ORG_UOR Cargos y usuarios
    • UOR_COD (PK)
    • UOR_NON Cargo

    ADMDDA.TDO Tipos de documento
    • TDO_ID (PK)
    • TDO_DES
    • TDO_DE1
    ADMDDA.USU Usuarios
    • USU_IDE (PK)
    • USU_NOM 


    Veamos los campos que hacen falta para llenar la cabecera



    Cuando alguno de los campos falta, aparecen en blanco

    (1) ADMDDA.TDO.TDO_DES
    (2) BIBAY.IDX.IDX_ALI

    (3) BIBAY.IDX_IMP.IIM_CVA
    (4) Fecha del sistema actual

    (5) ADMDDA.TDO.TDO_DES
    (6) BIBAY.IDX.IDX_CP1

    Para cada firmante
    (7)BIBAY.FIRM.FIR_UOR          ->ADMDDA.A_ORG_UOR.UOR_COD (muestra cargo UOR_NOM)        
    (7)BIBAY.FIRM.FIR_UOR_SUS ->ADMDDA.A_ORG_UOR.UOR_COD (muestra cargo sustituto si hay UOR_NOM)        
    A veces también se ponen los nombres :
    (7)BIBAY.FIRM.FIR_USU ->  ADMDDA.USU .USU_ID (USU_NOM) 

    (9) BIBAY.IDX.IDX_FDD (Fecha de firma)



    Veamos una consulta para extraer los datos

    SELECT A.IIM_IDX, A.IIM_CVA, --Nombre doc, CSV
           B.IDX_ALI, B.IDX_CP1, B.IDX_FFD, --Documento 2 , Identificadores 2, Firmado  
           10000*YEAR(B.IDX_FCH)+100*MONTH(B.IDX_FCH)+DAY(B.IDX_FCH) AS folder,   
           C.TDO_DES, C.TDO_DE1, --Documento 1, identificadores 1
           X.FIR_FCH, -- Fecha de la firma 
           D.UOR_NOM, D1.UOR_NOM,  -- Cargos (firmante y en nombre)
           E.USU_NOM --Nombre firmante
           
    FROM BIB_AY.dbo.IDX_IMP A
    JOIN BIB_AY.dbo.IDX B ON B.IDX_ID=A.IIM_IDX
    JOIN ADMDDA.dbo.TDO C ON TDO_ID=B.IDX_TDO
    LEFT JOIN BIB_AY.dbo.FIR X ON X.FIR_IDX=A.IIM_IDX
    LEFT JOIN ADMDDA.dbo.A_ORG_UOR D ON D.UOR_COD=X.FIR_UOR
    LEFT JOIN ADMDDA.dbo.A_ORG_UOR D1 ON D1.UOR_COD=X.FIR_UOR_SUS 
    LEFT JOIN ADMDDA.dbo.USU E ON E.USU_IDE=X.FIR_USU
    


    2. FACE

    Se localizan los ficheros en AYTOS-FACTURA/FACe/in o AYTOS-SICALWIN/sageaytos/FACe/in

    SQL SERVER (I) Buscar que tabla y campo contiene un valor

     Me parece muy interesantes las repuestas de stackoverflow 


    Una de las que más me ha gustado es de sbrbot  que he adaptado un poco para el caso de tipo "string"


    DECLARE @search VARCHAR(100), @table SYSNAME, @column SYSNAME, @schema SYSNAME
    DECLARE curTabCol CURSOR FOR SELECT c.TABLE_SCHEMA , c.TABLE_NAME, c.COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS c JOIN INFORMATION_SCHEMA.TABLES t ON t.TABLE_NAME=c.TABLE_NAME AND t.TABLE_TYPE='BASE TABLE' -- avoid views WHERE c.DATA_TYPE IN ('varchar','nvarchar','text','ntext','char','nchar') -- searching only in these column types --AND c.COLUMN_NAME IN ('NAME','DESCRIPTION') -- searching only in these column names ORDER BY c.TABLE_NAME, c.COLUMN_NAME SET @search='PHXN' OPEN curTabCol
    FETCH NEXT FROM curTabCol INTO @schema, @table, @column
    WHILE (@@FETCH_STATUS = 0) BEGIN EXECUTE('IF EXISTS (SELECT * FROM ' + @schema + '.[' + @table + '] WHERE [' + @column + '] LIKE ''%' + @search + '%'')
    PRINT ''' + @table + '.' + @column + '''') FETCH NEXT FROM curTabCol INTO @schema, @table, @column END CLOSE curTabCol DEALLOCATE curTabCol



    y para tipo "enteros"


    DECLARE @search int, @table SYSNAME, @column SYSNAME, @schema SYSNAME
    
    DECLARE curTabCol CURSOR FOR
        SELECT c.TABLE_SCHEMA , c.TABLE_NAME, c.COLUMN_NAME
        FROM INFORMATION_SCHEMA.COLUMNS c
        JOIN INFORMATION_SCHEMA.TABLES t 
          ON t.TABLE_NAME=c.TABLE_NAME AND t.TABLE_TYPE='BASE TABLE' -- avoid views
        WHERE c.DATA_TYPE IN ('numeric','int','bigint','decimal') -- searching only in these column types
        --AND c.COLUMN_NAME IN ('NAME','DESCRIPTION') -- searching only in these column names
        ORDER BY c.TABLE_NAME, c.COLUMN_NAME 
    
    
    --SET @search='SPHXN-YNS5H-9TV6R'
    --SET @search='10BC9C2A9F54521E4AE70402CCFC4A87F569F8A8'
    SET @search=418534
    
    OPEN curTabCol
    FETCH NEXT FROM curTabCol INTO @schema, @table, @column
    
    WHILE (@@FETCH_STATUS = 0)
    BEGIN
        --PRINT '                                  ' + @table + '.' + @column
        EXECUTE('IF EXISTS 
                 (SELECT * FROM ' + @schema + '.[' + @table + '] WHERE [' + @column + '] = ' + @search + ') 
                  PRINT ''' + @table + '.' + @column + '''')
        FETCH NEXT FROM curTabCol INTO @schema, @table, @column
    END
    
    CLOSE curTabCol
    DEALLOCATE curTabCol
    







    viernes, 10 de diciembre de 2021

    Certificados en Java (6).Tipos y Conversión de certificados. KeystoreExplorer. contraseñas NO ASSCII

    0. Introducción

    Nos basamos en sslshopper , Serverfault , medium , Digicert 


    Segun Mkyong java reconoce los formatos JKS o PKCS#12 pero no PEM.

    Veamos algunos formatos de certificados

    .csr: (Certificate Signing Request) Para pedir certificados a las entidades certificadoras (en adelante CA). Incluye detalles como: "subject, organization, state.." y la clave pública del certificado a firmar. Se firman pot la CA y se devuelve el certificado que es el certificado público (que incluye la clave pública pero no la privada). El certificado devueltopor la CA puede estar en varios formatos.

    .pem: (Privacy Enhanced Mail)Es un contenedor. Puede incluir:

    • el certificado público ó
    • una cadena entera de certificados (clave pública + clave privada + certificados raiz (root)
    .key: Suele ser un fichero en formato ".pem" y contiene solo la clave privada de un determinado certificado.

    .pkcs12 .pfx .p12 :(Public Key Cryptography Standards PKCS variante 12) Es un contenedor protegido por contraseña que contiene los pares de certificados privados y públicos). Al contrario que los ficheros ".pem" el contenedor está completamente encriptado. 

    Estos no son tan utilizados:

    .der: Advertir que un fichero ".pem" es un ficcero ".der" codificado en Base64. 
    Para convertir der (.crt .cer .der) a pem:

    .cert .cer .crt: Es un certificado ".pem" (a veces ".der") con una extensión distinta (reconocible por Windows Explorer)

    .p7b .keystore: (Public Key Cryptography Standards PKCS variante 7). Al contrario que los certificados ".pem", tiene una forma definida de incluir los "certification-path certificates".

    .crl: Lista de revocación de certificados. Lo producen las CAs para desautorizar loos certificados a punto de expirar.

    Los mas utilizados son PEM, PKCS7, PKCS12 y DER

    1. Conversiones

    Para convertir de p12 (.pfx .p12) a pem:

    openssl pkcs12 -in file-to-convert.p12 -out converted-file.pem -nodes

    Para convertir de p12 (.pfx .p12)  conteniendo una clave privada y certificados a pem:

    openssl pkcs12 -in keystore-to-convert.pfx -out keystore-converted.pem -nodes
    Para convertir de p12 (.pfx .p12)  a certificado pem(crt.pem) mas clave pem(key.pem) (stackoverflow):

    openssl pkcs12 -in keystore-to-convert.pfx -out crt.pem -clcerts -nokeys 
    openssl pkcs12 -in keystore-to-convert.pfx -out key.pem -nocerts -nodes
    Para convertir un certificado pem (.pem .crt) con una clave privada (.key) y la cadena de certificados (.pem .crt)  a de p12 (.pfx .p12):

    openssl pkcs12 -export -inkey privateKey.key -in cert.crt -certfile CACert.crt -out cert.pfx
      Siendo:
         privateKey.key: la clave privada 
         cert.cert : Certificado
         CACert: La cadena de certificados de la entidad certificadora

    Para convertir un certificado pem (.pem .crt que contiene tanto al certificado como la cadena de certrificados de la entidad certificadora)  y una clave privada (.key) a de p12 (.pfx .p12) (Mkyong) con password "1234" :

    openssl pkcs12 -export -inkey privateKey.key -in cert.crt -passout pass: 1234 -out cert.pfx

    Para convertir der (.crt .cer .der) a pem:
    openssl x509 -inform der -in file-to-convert.der -out converted-file.pem

    Para convertir pem a der:

    openssl x509 -outform der -in file-to-convert.pem -out converted-file.der
    Para convertir p12 (PKCS#12 keystore) a jks (java keystore) IBM: OJO: Ver las observaciones!!
    keytool -importkeystore -srckeystore <source_keystoreFile> -srcstoretype PKCS12 -destkeystore <destination_keystoreFile>  -deststoretype JKS -srcstorepass mysecret -deststorepass mysecret -srcalias myalias -destalias myalias -srckeypass mykeypass -destkeypass mykeypass -noprompt

    Para convertir jks (java keystore) a p12 (PKCS#12 keystore) (Baeldung):
    keytool -importkeystore -srckeystore jks_keystore.jks -destkeystore keystore.p12 -srcstoretype jks -deststoretype pkcs12

    OBSERVACIONES: La herramienta keytool no admite contraseñas con caracteres NO ASCII como ñ, acentos, etc. Por tanto para convertir un certificado en formato p12 con una contraseña como "Cañón", no podemos utilizar keytool. Para ello utilizamos Keystore Explorer 

    Tras seleccionar el certificado p12, nos pide la contraseña para poder verlo. Le damos "Cañón" en nuestro caso


    Vemos el alias ss_profile y el tipo RSA



    En el menú Tools > Change Keystore Type > JKS     Convertimos de p12 a JKS




    Y le damos la misma contraseña (Cañón en nuestro caso.)

    Ahora lo guardamos con otro nombre y extensión JKS (File > Save As ) y ya lo tenemos