martes, 17 de marzo de 2020

JavaFX (3) Empaquetar/distribuir la aplicación (2/2)

1. Introducción

Ahora ya sabemos como crear el pom.xml para empaquetar nuestra aplicación.

2. Clases importantes en JavaFx y la clase a ejecutar

Este punto es muy importante, despúes del pom.xml

JavaFx tiene una clase principal, en este caso "App" que hereda de Application. Esta clase debe de tener los métodos "start" y "main". Con esta clase solo (junto con las clases que hace referencia) se puede ejecutar la aplicacion tral como se indica en el punto siguiente (con maven clean javafx:run)

Pero si queremos tener un jar para ejecutar esta aplicación hay que crear una clase (en mi caso NewMain) que contenga un main que llame al main de la clase que hereda de Application (en mi caso App)


package ximodante.JavaFX01;

public class NewMain {
    public static void main(String[] args) {
        ximodante.JavaFX01.App.main(args);
    }
}

Esta clase la "NewMain" es la que hay que indicar al "pom.xml" (línea 151) que hace referencia el maven-jar-plugin en su clausula <mainClass>

Mientras que la clase App es:


  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
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
package ximodante.JavaFX01;

import javafx.application.Application;
//import javafx.fxml.FXMLLoader;

import javafx.scene.Scene;
import javafx.scene.control.Button;

import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
//import javafx.stage.Modality;
import utils.CompressUtils;
import utils.FileUtils;
import utils.PropertiesUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Properties;

/**
 * JavaFX App
 */
public class App extends Application {
   
 //boolean isJar=false;
 boolean isJar=true;
 Properties props=null;    
 String propsFileName="app.properties";
 String propsFileAbsoluteName="";
 String DBFile="";
 String destinationFolder="";
 
    @Override
    public void start(Stage stage) throws IOException {
     //stage.initModality(Modality.APPLICATION_MODAL);  //NO VA
     stage.initStyle(javafx.stage.StageStyle.DECORATED);
     //stage.setFullScreen(true);
     stage.setTitle("Copia de seguretat de la BD");
     
     try {
      if (isJar) {
       props=PropertiesUtils.getRelativeFromJarFileProperties(propsFileName);
       propsFileAbsoluteName=FileUtils.getJarContainingFolder() + File.separator + propsFileName;
      }
      else {
       props=PropertiesUtils.getRelativeProperties(propsFileName);
       URL url = ClassLoader.getSystemResource(propsFileName);
       propsFileAbsoluteName=url.getPath();
      }
  } catch (Exception e2) {
   // TODO Auto-generated catch block
   e2.printStackTrace();
   props=null;
  }
     
     File propsFile= new File(propsFileAbsoluteName);
     if (props!=null && propsFile.exists()) {
      DBFile=props.getProperty("db.name");
         destinationFolder=props.getProperty("destination.folder");
     } else props=null; 
     
     System.out.println("DBFile=" + DBFile);
     
     //TextField txtDBFileName = new TextField();
     TextArea txtDBFileName = new TextArea();
     txtDBFileName.setPrefWidth(600);
     txtDBFileName.setPrefHeight(60);
     txtDBFileName.setText(DBFile);
     //txtDBFileName.setText("");
     
     TextArea txtFolderName = new TextArea();
     txtFolderName.setPrefWidth(600);
     txtFolderName.setPrefHeight(60);
     txtFolderName.setText(destinationFolder);
     //txtFolderName.setText("");
     
     
     TextField txtMessage = new TextField();
     txtMessage.setStyle("-fx-font-weight: bold;");
     
     FileChooser fileChooser = new FileChooser();
     fileChooser.getExtensionFilters().addAll(
           new FileChooser.ExtensionFilter("Acces DB <2003 mdb", "*.mdb")
          ,new FileChooser.ExtensionFilter("Acces DB >2003 accdb", "*.accdb")
      );
     
     DirectoryChooser directoryChooser = new DirectoryChooser();
     
     
     Button btSelectFile = new Button("Tria el fitxer de la BD");
     btSelectFile.setPrefHeight(40);
     
     
     Button btSelectFolder = new Button("Tria la carpeta on fer la còpia comprimida");
     btSelectFolder.setPrefHeight(40);
     
     Button btOK= new Button("Fes la còpia");
     btOK.setStyle("-fx-font-size: 24px; -fx-font-weight: bold;");
     btOK.setPrefHeight(60);
     
     
     
     
     //Actions
     btSelectFile.setOnAction(e -> {
      try {
       DBFile=txtDBFileName.getText().trim();
       File DBFolder=null;
          if (DBFile!=null && DBFile.length()>0) DBFolder=new File(new File(DBFile).getParent());
          if (DBFolder !=null && DBFolder.exists()) fileChooser.setInitialDirectory(DBFolder);
         } catch (Exception e2) {
       // TODO Auto-generated catch block
       e2.printStackTrace();
      } 
      File selectedFile = fileChooser.showOpenDialog(stage);
            if (selectedFile!=null && selectedFile.exists()) txtDBFileName.setText(selectedFile.getAbsolutePath());
        });
     
     
     btSelectFolder.setOnAction(e -> {
      try {
       destinationFolder=txtFolderName.getText().trim();
          File destFolder=new File(destinationFolder);
          if (destFolder!=null && destFolder.exists()) directoryChooser.setInitialDirectory(destFolder);
         } catch (Exception e2) {
       // TODO Auto-generated catch block
       e2.printStackTrace();
      }
      File selectedDirectory = directoryChooser.showDialog(stage);
            if (selectedDirectory!=null && selectedDirectory.exists()) txtFolderName.setText(selectedDirectory.getAbsolutePath());
        });
     
     btOK.setOnAction(e -> {
      if (txtDBFileName.getText().trim().length()>1 && 
        txtFolderName.getText().trim().length()>1 )
    try {
     DBFile=txtDBFileName.getText().trim();
        destinationFolder=txtFolderName.getText().trim();
        File f1=null;
        File f2=null;
        try {
         f1=new File(DBFile);
         f2=new File(destinationFolder);
        }catch (Exception e3) {
         e3.printStackTrace();
        }
        System.out.println (f1.toString());
        System.out.println (f2.toString());
     if (f1!=null && f2!=null && f1.exists() && f2.exists()) {
      String fitxerEixida=CompressUtils.compresFiletoFolder(DBFile, destinationFolder);
     
      txtMessage.setText("Copia de seguretat realitzada correctament!-->" + fitxerEixida);
      if (props!=null) {
       props.setProperty("db.name", DBFile);
       props.setProperty("destination.folder", destinationFolder);
       PropertiesUtils.saveRelativeFromJarFileProperties(props, propsFileName, "");
      }
     } else {
      String msg="";
      if (f1==null || !f1.exists()) msg=msg + " No existeix el fitxer " + DBFile;
      if (f2==null || !f2.exists()) msg=msg + " No existeix la carpeta " + destinationFolder;
      txtMessage.setText(msg);
     }
    } catch ( Exception e1) {
     e1.printStackTrace();
    }
        });
     
     
     GridPane gridPane = new GridPane();
     gridPane.setHgap(20);
     gridPane.setVgap(20);
     
     gridPane.add(btSelectFile  , 1 , 0, 1 , 1);
     gridPane.add(txtDBFileName , 2 , 0, 20, 1);
     gridPane.add(btSelectFolder, 1 , 1, 1 , 1);
     gridPane.add(txtFolderName , 2 , 1, 20, 1);
         
     gridPane.add(btOK          , 19, 2, 1 , 1);
     
     gridPane.add(txtMessage    , 1 , 3, 21, 1);
     
        Scene scene = new Scene(gridPane, 950, 350);
        stage.setScene(scene);
        stage.show();
    }
 
    public static void main(String[] args) {
        launch(args);
    }
    
    /*
    
    @Override
    public void start(Stage stage) throws IOException {
        scene = new Scene(loadFXML("primary"), 640, 480);
        stage.setScene(scene);
        stage.show();
    }
 
    static void setRoot(String fxml) throws IOException {
        scene.setRoot(loadFXML(fxml));
    }
    
    private static Parent loadFXML(String fxml) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource(fxml + ".fxml"));
        return fxmlLoader.load();
    }
    */
}

Hay un fichro de propiedades "app.properties" (en ser/main/properties) que contiene solo 2 valores


db.name = /home/eduard/sindrec.mdb
destination.folder = /home/eduard/Documents

3. Classes de Utilidad

Tenemos 3 clases de utilidades con métodos estáticos que son:
1. CompressUtils (para comprimir ficheros)
2. FileUtils (Para trabajar con ficheros)
3. PropertyUtils (para manejar propiedades)

Veamos CompressUtils.java


package utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/*
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile;
import org.apache.commons.io.FilenameUtils;
*/


public class CompressUtils {

 /*
 public static void compresFiletoFolder(String fileToArchiveName, String destinationFolderName) throws IOException {
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  String date = sdf.format(new Date()); 
  String fName=FilenameUtils.getName(fileToArchiveName);
  String compressedFileName=destinationFolderName+ "/"+ fName +"."+ date + ".7z";
  System.out.println(compressedFileName) ; 
  SevenZOutputFile sevenZOutput = new SevenZOutputFile(new File(compressedFileName));
  
  SevenZArchiveEntry entry = sevenZOutput.createArchiveEntry(new File(fileToArchiveName), fName);
  sevenZOutput.putArchiveEntry(entry);
  sevenZOutput.write(Files.readAllBytes(Paths.get(fileToArchiveName)));
  sevenZOutput.closeArchiveEntry();
  sevenZOutput.close(); 
 }
 */
 
 public static String compresFiletoFolder(String fileToArchiveName, String destinationFolderName) throws IOException {
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  String date = sdf.format(new Date()); 
  
  File fileToZip = new File(fileToArchiveName);
  String fName=fileToZip.getName(); 
  
  String compressedFileName=destinationFolderName+ "/"+ fName +"."+ date + ".zip";
  System.out.println(compressedFileName) ; 
  
  FileOutputStream fos = new FileOutputStream(compressedFileName);
        ZipOutputStream zipOut = new ZipOutputStream(fos);
  
        FileInputStream fis = new FileInputStream(fileToZip);
        ZipEntry zipEntry = new ZipEntry(fileToZip.getName());
        zipOut.putNextEntry(zipEntry);
        
        byte[] bytes = new byte[1024];
        int length;
        while((length = fis.read(bytes)) >= 0) {
            zipOut.write(bytes, 0, length);
        }
        zipOut.close();
        fis.close();
        fos.close();
        return compressedFileName;
 }
 
 public static void main(String[] args) {
  try {
   compresFiletoFolder("/home/eduard/Documents/Edu_basquet.pdf", "/home/eduard");
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }

 }

}

Veamos FileUtils.java



package utils;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.net.URLDecoder;
import java.security.CodeSource;

public class FileUtils {

 /**
  * Folder that contains jar file or folder that contains project folder
  * @return
  * @throws Exception
  */
 public static String getJarContainingFolder() throws Exception {
  Class<?> aClass=MethodHandles.lookup().lookupClass();
  CodeSource codeSource = aClass.getProtectionDomain().getCodeSource();

  File jarFile;

  if (codeSource.getLocation() != null) {
   jarFile = new File(codeSource.getLocation().toURI());
  } else { // It is not a jar file
   String path = aClass.getResource(aClass.getSimpleName() + ".class").getPath();
      String jarFilePath = path.substring(path.indexOf(":") + 1, path.indexOf("!"));
      jarFilePath = URLDecoder.decode(jarFilePath, "UTF-8");
      jarFile = new File(jarFilePath);
  }
  String s=jarFile.getParentFile().getAbsolutePath();
  System.out.println("S------>:" + s);
  if (s.endsWith(File.separator+"target")) { // Maven target directory for compiled classes
   s=s.substring(0, s.lastIndexOf(File.separator));
   s=s.substring(0, s.lastIndexOf(File.separator));
  } 
  return s;
 }
 
 public static byte[] readFile(String fileName) throws IOException {
  File file = new File(fileName);//filename should be with complete path
  FileInputStream fis = new FileInputStream(file);
  byte[] b = new byte[ (int) file.length()];
  fis.read(b);
  fis.close();;
  return b;
 }
 
 public static void writeToFile(String fileName, String myString) throws IOException {
  BufferedWriter writer = new BufferedWriter( new FileWriter( fileName));
  writer.write( myString);
  // do stuff 
  writer.close();
 }
 
 /**
  * test in main class
  * @param args
  */
 public static void main(String[] args) {
  try {
   System.out.println(getJarContainingFolder());
   System.out.println(System.getProperty("java.class.path"));
   System.out.println(System.getProperty("user.dir"));
   byte[] b=readFile("/home/eduard/Audit.0.log");
   String sb=new String(b);
   System.out.println(sb);
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }

 }

}

Y por último PropertiesUtils.java



package utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;

import java.util.Properties;

public class PropertiesUtils {
 
 // Valid only in web
 //public static String ResourcesPath=Thread.currentThread().getContextClassLoader().getResource("").getPath();
 
 
 /**
  * The properties path is referred relatively to resources path
  * @param filePath
  * @return
  * @throws FileNotFoundException
  * @throws IOException
  */
 public static Properties getRelativeProperties(String filePath) throws FileNotFoundException, IOException {
  Properties properties = new Properties();
       
  //String path = ResourcesPath + filePath;
  //System.out.println("PROPERTIES.PATH=" + path);
  //properties.load(new FileInputStream(path));
  
  
  System.out.println(filePath);
  //URL url = ClassLoader.getSystemResource("/resources/" + filePath);
  //URL url = ClassLoader.getSystemResource("/src/main/resources/" + filePath);+
  URL url = ClassLoader.getSystemResource(filePath);
  System.out.println(url);
  properties.load(url.openStream());
  
  
  for(Object o: properties.keySet()) System.out.println(o.toString() + "-->"+ properties.getProperty(o.toString()));
  
  return properties;
 }
 
 /**
  * Leemos la propiedades de una ruta absoluta.
  * OJO: Si queremos leer un fichero de propiedades "file.properties" que se encuentra 
  *      en la misma carpeta que el proyecto (o el jar ejecutable) :
  *   
  *      final File f = new File(PropertiesUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath());
  *      
  *      String suffix=File.separator +"..";
     *      //myFile=f.getAbsolutePath()+ "/../../../file.properties" ;
     *      myFile=f.getAbsolutePath()+ StringUtils.repeat(suffix, 3) + File.separator + file.properties" ;
     *      Properties myProps=PropertiesUtils.getAbsoluteProperties(myFile);
     *      
  * @param filePath
  * @return
  * @throws FileNotFoundException
  * @throws IOException
  */
 public static Properties getAbsoluteProperties(String filePath) throws FileNotFoundException, IOException {
  Properties properties = new Properties();
       
  //String path = ResourcesPath + filePath;
  System.out.println(filePath);
  properties.load(new FileInputStream(filePath));
  
  
  
  
  for(Object o: properties.keySet()) System.out.println(o.toString() + "-->"+ properties.getProperty(o.toString()));
  
  return properties;
 }
 
 /**
  * Gets the folder where resides the executable jar
  * @return
  */
 /**
 public static String getJarFolderPath() {
  
  final File f = new File(PropertiesUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath());
     String suffix=File.separator +"..";
     //jarFolder=f.getAbsolutePath()+ "/../../../"file.properties" ;
     String jarFolder=f.getAbsolutePath()+ StringUtils.repeat(suffix, 3) + File.separator;
     return jarFolder;
 }
 */
 public static Properties getRelativeFromJarFileProperties(String filePath) throws Exception {
  Properties properties = new Properties();
  
  //String myPath=getJarFolderPath()+filePath;
  String myPath=FileUtils.getJarContainingFolder() + File.separator + filePath;
  System.out.println(myPath);
  //System.out.println(PropertiesUtils.class.getResource(PropertiesUtils.class.getSimpleName() + ".class").getPath());
  //System.out.println(System.getProperty("user.dir"));
  properties.load(new FileInputStream(myPath));
  
  for(Object o: properties.keySet()) System.out.println(o.toString() + "-->"+ properties.getProperty(o.toString()));
  
  return properties;
 }
 
 
 public static void saveAbsoluteProperties(Properties properties, String filePath, String comments) throws FileNotFoundException, IOException {
  //String path = ResourcesPath + filePath;
  properties.store(new FileOutputStream(filePath), comments);
 }
 
 public static void saveRelativeFromJarFileProperties(Properties properties, String filePath, String comments) throws Exception {
  String myPath=FileUtils.getJarContainingFolder() + File.separator + filePath;
  System.out.println(myPath);
  properties.store(new FileOutputStream(myPath), comments);
 }
 
 public static void main(String[] args) throws FileNotFoundException, IOException{
  //String myFile="properties/last_fac.properties";
  String myFile="properties/application.properties";
  Properties myProps=getRelativeProperties(myFile);
  myProps.setProperty("A", "9999.888");
  myProps.setProperty("J", "1111.222");
  //for(Object o: myProps.keySet()) System.out.println(o.toString() + "-->"+ myProps.getProperty(o.toString()));
  //String myFile2="/home/eduard/last_fac2.properties";
  //saveAbsoluteProperties (myProps,myFile2, "ultima actualizacion");
  //myFile="../kk.properties";
        
         /*
               ws/pr/tg/cl/file  
         myFile="../../../../kk.properties";
         Properties myProps1=getRelativeProperties(myFile);
         System.out.println(myProps1.getProperty("prop2"));
         */
  /*
      System.out.println("-------------------------");
         //myFile="kk.properties";
      myFile="";
         String prefix="../";
         for (int i=0; i<15; i++) {
          System.out.println(myFile);
          URL url = ClassLoader.getSystemResource(myFile);
          System.out.println(url);
          System.out.println("-------------------------");
          myFile=prefix+myFile;
         }
        */
  /*
        final File f = new File(PropertiesUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath()); 
        System.out.println(f.getAbsolutePath());
        myFile=f.getAbsolutePath();
        String sufix="/..";
        for (int i=0; i<15; i++) {
      System.out.println(myFile);
      URL url = new URL("file:"+myFile);
      System.out.println(url);
      url=new URL("file:"+myFile+"/kk.properties");
      System.out.println(url);
      System.out.println("-------------------------");
      myFile=myFile+sufix;
     }
     */
  System.out.println("----------------------------------------------");
  final File f = new File(PropertiesUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath()); 
        System.out.println(f.getAbsolutePath());
        String suffix=File.separator + "..";
        myFile=f.getAbsolutePath();
        for (int i=0; i<10; i++) {
      System.out.println(myFile);
      String propFile=myFile + File.separator + "kk.properties";
      System.out.println(propFile);
      try {
       Properties myPrp=getAbsoluteProperties(propFile);
       System.out.println(myPrp.getProperty("prop1"));
      } catch (Exception e) {
       e.printStackTrace();
      }
      System.out.println("-------------------------");
      myFile=myFile+suffix;
     }
  
 }
}

4. Ejecutar la aplicación 

Ya no vale con seleccionar la clase ejecutable y darle "Run-As -> Java Application"  (no funciona)

Para ejecutar la aplicación con Eclipse y Maven hay que seguir estos pasos:

4.1 Boton derecho sobre el nombre del proyecto
4.2 Run as
4.3 Maven build...
4.4 Goals -> "clean javafx:run"

Y en mi caso tenemos esta ejecución



5. Empaquetar y distribuir


5.1 Boton derecho sobre el nombre del proyecto
5.2 Run as
5.3 Maven build...
5.4 Goals -> "clean install"

Y me genera la carpeta "MiCarpeta" dentro de "target" que contiene el jar (MiJar.jar) y la carpeta "lib" con todas las librerías en forma de ficheros ".jar"

6. Ejecutar el jar

Tener en la variable de entorno path la ruta a la carpeta "bin" del openjdk13 e ir a la carpeta "MiCarpeta" y ejecutar "java -jar MiJar.jar" y a funcionar (salvo que el path tenga la ruta a java de otra versión anterior, en cuyo caso habrá que copiar el ejecutable java (java o java,exe) a java_ximo (o java_ximo.exe) i ejecutar "java_ximo -jar MiJar.jar". Hay que tener en cuenta que no hace falta instalarlo ni en windows ni en linux, se puede copiar el OpenJdk13 a una carpeta y enrutarlo con el path.

7. Posteriores empaquetados y ejecuciones en Eclipse

Si ya se han ejecutado estas opciones , selecionar "Maven build" en vez de "Maven build.."
Si se quiere borrar o modificar algunas de las configuraciones del build se hace:

7.1 Boton derecho sobre el nombre del proyecto
7.2 Run as
7.3 Run Configurtations
7.4 Selecionar la configuracion deseada y modificarla o borrarla.




JavaFX (2) Empaquetar/distribuir la aplicación (1/2)

1. Introducción

He creado un proyecto maven en Eclipse, al final lo he hecho de este modo:

New->Maven->Maven Project -> marcar la casilla de "create simple project (skip archeype selection)


Y completamos los campos (observar que se crea el proyecto JavaFX02 y vamos a mostrar el JavaFX01)


Al final después de crear todas las clases y dejar el proyecto operativo vemos como lo muestra Eclipse


2. pom.xml (el fichero mas importante)

Según lo visto en una entrada anterior creamos este fichero pom.xml actualizado a las nuevas versiones que aparecen en maven. Con esto conseguimos:

1. Empaquetar los ficheros a la carpeta "target/MiCarpeta"
2. En esta carpeta se guarda:
    2.1 El fichero jar "MiJar.jar"
    2.2 La carpeta "lib" que contiene todas las librerías (jars)
3. Para ejecutar "MiJar.jar" hay que tener java13 y dar


java -jar MiJar.jar

#java_ximo -jar MiJar.jar

Donde java_ximo representa una copia de java.exe para el caso que se tenga una version de java distinta instalada. OJO: Hay que darle la ruta del "jdk13.02/bin" a la variable de entorno "PATH"

Veamos el fichero:


  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
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>ximodante</groupId>
    <artifactId>JavaFX01</artifactId>
    <packaging>jar</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>13</maven.compiler.source>
        <maven.compiler.target>13</maven.compiler.target>
    </properties>
    <dependencies>
      <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-controls</artifactId>
        <version>14</version>
     </dependency>
        
     <dependency>
       <groupId>org.openjfx</groupId>
       <artifactId>javafx-fxml</artifactId>
       <version>14</version>
     </dependency>
        
     <!-- https://stackoverflow.com/a/52654791/7704658 -->
     <dependency>
       <groupId>org.openjfx</groupId>
       <artifactId>javafx-graphics </artifactId>
       <version>14</version>
       <classifier>win</classifier>
     </dependency>
     
     <dependency>
       <groupId>org.openjfx</groupId>
       <artifactId>javafx-graphics </artifactId>
       <version>14</version>
       <classifier>linux</classifier>
     </dependency>
     
     <dependency>
       <groupId>org.openjfx</groupId>
       <artifactId>javafx-graphics </artifactId>
       <version>14</version>
       <classifier>mac</classifier>
     </dependency>
        
     <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
     <!--  
     <dependency>
       <groupId>commons-io</groupId>
       <artifactId>commons-io</artifactId>
       <version>2.6</version>
     </dependency>
     --> 
        
     <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-compress -->
     <!-- 
     <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-compress</artifactId>
       <version>1.20</version>
     </dependency>
     -->
     <!-- https://mvnrepository.com/artifact/org.tukaani/xz -->
     <!-- 
     <dependency>
       <groupId>org.tukaani</groupId>
       <artifactId>xz</artifactId>
       <version>1.8</version>
     </dependency>
     -->
       
    </dependencies>
    
    <build>
     <plugins>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
         <version>3.8.1</version>
         <configuration>
           <release>13</release>
         </configuration>
       </plugin>
            
       <plugin>
         <groupId>org.openjfx</groupId>
         <artifactId>javafx-maven-plugin</artifactId>
         <version>0.0.3</version>
         <configuration>
           <launcher>launcher</launcher>
           <mainClass>ximodante.JavaFX01.App</mainClass>
         </configuration>
       </plugin>
            
       <!--https://www.baeldung.com/learn-spring-security-course  -->
       <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.1.0</version>
        <executions>
          <execution>
            <id>copy-resources</id>
            <phase>validate</phase>
            <goals>
              <goal>copy-resources</goal>
            </goals>
            <configuration>
              <outputDirectory>${basedir}/target/MiCarpeta</outputDirectory>
              <resources>
                <resource>
                  <directory>resources</directory>
                  <filtering>true</filtering>
                </resource>
              </resources>
            </configuration>
          </execution>
        </executions>
      </plugin>
            
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>3.1.2</version>
        <executions>
          <execution>
            <id>copy-dependencies</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
              <outputDirectory>
                ${project.build.directory}/MiCarpeta/lib
              </outputDirectory>
            </configuration>
          </execution>
        </executions>
      </plugin>

     <plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-jar-plugin</artifactId>
       <version>3.2.0</version>
       <configuration>
         <archive>
           <manifest>
             <addClasspath>true</addClasspath>
             <classpathPrefix>lib/</classpathPrefix>
             <mainClass>
                   ximodante.JavaFX01.NewMain
             </mainClass>
           </manifest>
           <manifestEntries>
             <Class-Path>.</Class-Path>
           </manifestEntries>
         </archive>
         <finalName>MiCarpeta/MiJar</finalName>
       </configuration>
     </plugin>
     <!-- fin -->
            
    </plugins>
  </build>
</project>

Lineas 14-24: Dependencias del javafx
Lineas 26-46: Se dan las dependencias para cada sistema operativo (linux, windows y mac) según dice José Pereda.
Líneas 48-72: Otras librerías que hagan falta como apache-commons etc (en este caso no ha hecho falta y se han comentado)
Línea 77-88: Compilador de maven (imprescindible)
Línea 87-95: javafx-maven-plugin (imprescindible si quieres ejecutar la aplicación desde Eclipse) y para crear una imágen (con todos los problemas que ello da)
Líneas 97-161: Para empaquetar y distribuir la aplicaión dentro de la carpeta "target/MiCarpeta" según una entrada anterior
Línea 151: La clase a ejecutar. Muy Importante

JavaFX (1) Mi primera toma de contacto. Muchos problemas y mucho google para solucionarlos!

1. Introdución


Me hace falta realizar una pequeña aplicación de escritorio que funcione tanto en Windows como en Linux.
Parece ser que javaFX és una de las pocas opciones que me quedan, pero he tenido un complicado camino para que funcionase.

2. Pasos que he seguido

He seguido las instrucciones que indica en la web de la comunidad  pero al final he tenido que descartar algunas opciones. Veamos resumidamente los pasos, por tanto merece la pena que te apoyes en la página oficial como aclaración y detalle:

1. Crear un proyecto maven y seleccionar el arquetipo "javafx-archetype-fxml" (ya que el arquetipo "javafx-archetype-simple" da muchos problemas) Te deja meter la versión 0.05

2. En fichero maven "pom.xml" selecciona el JDK 14, pero el plugin "javafx-maven-plugin", seleccionar la versión "0.0.3" (pues la versión "0.0.4" da muchos problemas)

3. Al final me he enterado que un proyecto "modular" es el que tiene el fichero "module-info.java" que cualga directamente de la carpeta "src/main/java".

4. A veces el pom.xml se queja de que no existe el fichero MANIFEST.MF, para no de el error, he creado este fichero en blanco dentro de la carpeta "src/main/resources/META-INF", y ya no da la lata.

5. Ejecutar el proyecto: Tal y como se dice le damos al boton derecho encima del nombre del proyecto y "Run As" -> Maven build .. y del damos a goals: "clean javafx:run". Y parece que funciona.

6. Crear una imagen: Igual que antes le damos al boton derecho encima del nombre del proyecto y "Run As" -> Maven build .. y del damos a goals: "clean javafx:jlink".... pero "con la iglesia hemos topado amigo Sancho...", veamos por qué:

6.1 Si utilizamos librerias regulares como apache-commons, ya no deja hacer la imagen y sale este error


[DEBUG] Executing command line: [/usr/java/jdk-13.0.2/bin/jlink, --module-path, /home/eduard/WorkspaceFX/JavaFX01/target/classes:/home/eduard/.m2/repository/commons-io/commons-io/2.6/commons-io-2.6.jar:/home/eduard/.m2/repository/org/apache/commons/commons-compress/1.20/commons-compress-1.20.jar:/home/eduard/.m2/repository/org/openjfx/javafx-base/14/javafx-base-14-linux.jar:/home/eduard/.m2/repository/org/openjfx/javafx-controls/14/javafx-controls-14-linux.jar:/home/eduard/.m2/repository/org/openjfx/javafx-fxml/14/javafx-fxml-14-linux.jar:/home/eduard/.m2/repository/org/openjfx/javafx-graphics/14/javafx-graphics-14-linux.jar, --add-modules, ximodante.JavaFX01, --output, /home/eduard/WorkspaceFX/JavaFX01/target/image, --compress, 2, --launcher, launcher=ximodante.JavaFX01/ximodante.JavaFX01.App]
Error: automatic module cannot be used with jlink: org.apache.commons.io from file:///home/eduard/.m2/repository/commons-io/commons-io/2.6/commons-io-2.6.jar
[ERROR] Command execution failed.

  O sea no podemos utilizar librerías automáticas como apache-commons (que son aquellas que parece ser toman las rutas del classpath y no del manifest??). Por tanto no podemos hacer nada ya

6.2 Si no utilizamos estas librerias y conseguimos que funcione el dichoso "clean javafx:jlink", nos genera una carpeta "image" en la carpeta  "target" que no hay quien se aclare ppara poder utilzar dicha imagen. para ello hay que modificar el "pom.xml" y meter al menos una entrada "launcher" tal y como se indica en rojo. al menos crea un fichero "mylauncher" que si cliclamos sobre él, ejecuta la aplicación. Ver read-me del github del javafx-maven-plugin


<build>
  <plugins>

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.8.1</version>
      <configuration>
        <release>13</release>
      </configuration>
    </plugin>
           
            
    <plugin>
      <groupId>org.openjfx</groupId>
       <artifactId>javafx-maven-plugin</artifactId>
       <version>0.0.3</version> <!--version 0.0.4 doesn't work -->
       <configuration>
          <launcher>mylauncher</launcher>
          <mainClass>ximodante.JavaFX01.App</mainClass>
       </configuration>
    </plugin>

  </plugins>
</build>


6.3 Ya tenemos una imagen que parece que funciona, pero con la restricción de no usar librerias regulares.... Pero si la hemos hecho con linux... NO FUNCIONA CON WINDOWS. Cabreo que he cogido!

6.4 Estoy trabajando con openjdk 13.02, pero he tenido que instalar el Openjdk 11, pues a veces daba algún problema. Pero una vez instalado la versión 11, aunque utilizaba la 13, ya no he tenido mas problemas

3. En busca de soluciones

Hay un español llamado José Pereda Llamas que sabe muchísimo de todo esto. Tiene algunas intervenciones en stackoverflow  que són lujo y vale la pena verlas. Os adelanto algunas:

Package a non modular java application. -> Muy bueno pues explica las distintas forma de empaquetar/distribuir aplicaciones javafx.

JavaFX application runs fine when running Main in IntelliJ, built jar doesn't run -> Explica errores comunes que aparecen al intentar empaquetar o lincar una aplicacion javaFX

Error: “Package is declared 'javafx.beans.value' in module 'foo.bar'” -> Explica diferentes manera de empaquetar una aplicación con graddle.

Maven Shade JavaFX runtime components are missing -> Explica como empaquetar las librerias para windows, lunix y mac en un jar. Muy importante

Este señor tiene muchas intervenciones en StackOverflow, y buscando por todas partes he encontrado una solución que parece que soluciona los problemas. Se ve en la próxima entrada



jueves, 5 de marzo de 2020

Ubuntu CUPS - configuración de impresoras

1.Mediante el interfase de Ubuntu


Se puede añadir una impresora delas siguientes maneras:

a. Apretando en esta zona y después indicar imoresoras y aparece esta pantalla

A continuación añadir



Inidicar la dirección del servidor de impresoras (en este caso 192.167.27.12) que es la IP de mi impresora. Y seleccionar Impresora Jet-Direct mediante doble click y predira el controlador, en mi caso Konica Minolta C451 PS(P) y a funcionar



2. Mediante CUPS (http)

Entrar en un navegador con http://localhost:631 





Ahora es muy importante el IDENTIFICARTE

Dar esta dirección   http://localhost:631/admin/login

Y te pide usuario y contraseña (y le daras un unsuario administrativo del grupo ldp)

Ahora ya puedes añadir impresora (tipo  AppSocket/HP Direct)

Inidcar la dirección como se indica y a partir de ahí seleccionar controladores etc.