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.