JavaFx runnable JAR export is not working - java

I've made a simple dictionary using JavaFX. I've used a SQLite Database and some pictures into my application. I exported the application as a runnable JAR file using e(fx) Eclipse. I followed the steps described here - https://wiki.eclipse.org/Efxclipse/Tutorials/Tutorial1.
After exporting I opened the .JAR file. It opened successfully but wasn't working properly. It wasn't showing the results from the database and images.
When I ran the application into Eclipse workspace before building & exporting, it worked fine.
Where is the problem? How do I fix it?
Here is the code for the Controller Class function:
package imran.jfx.application;
import java.io.File;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
public class Application_Controler implements Initializable{
#FXML
private HBox hBox;
#FXML
private Label searchLabel;
#FXML
private TextField searchWord;
#FXML
private VBox vBox;
#FXML
private Text BanglaMeaning;
#FXML
private TextArea bnMeaningTxt;
#FXML
private Text bAcaMeaning;
#FXML
private ScrollPane bAcaMeaningImg;
#FXML
private Label footerLabel;
ResultSet result;
PreparedStatement doQuery;
Connection conn;
String query;
#Override
public void initialize(URL location, ResourceBundle resources) {
try
{
Class.forName("org.sqlite.JDBC");
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
String url="jdbc:sqlite:src/imran/ankurdb/meaning/bn_words.db";
try
{
conn = DriverManager.getConnection(url);
}
catch (SQLException e) {
e.printStackTrace();
}
}
#FXML
void showMeaning(ActionEvent event) throws Exception {
bnMeaningTxt.clear();
String text=searchWord.getText();
query = "select en_word,bn_word from words where en_word='"+text+"'";
doQuery = conn.prepareStatement(query);
result = doQuery.executeQuery();
int i=0;
while (result.next())
{
if(i==0)
{
bnMeaningTxt.appendText(result.getString(1) + "\t\t" + result.getString(2));
i++;
}
else
bnMeaningTxt.appendText(" , "+result.getString(2));
}
File file = new File("src/imran/bnacademy/meaning/"+text);
Image image = new Image(file.toURI().toString());
bAcaMeaningImg.setContent(new ImageView(image));
}
}

There are multiple problems here.
You are trying to create a database file inside your project. This is not going to work when you have packaged your project as a jar. You should give it a url outside your project. The database files should be placed always outside the project, so that when you package your project as a jar, they can still be created, read and written to.
If the images are present inside your jar, you cannot use io.File to load images. You need to use the class loader to load them instead.
Code
URL url = getClass().getResource("/imran/bnacademy/meaning/" + text);
Image image = new Image(url.toExternalForm());

Related

Creating user other from root in mysql from java

I am trying to make a new user in a Mysql database using java code but the code is not working. This is the Database class which initializes the database connection and creates a user, sets the password, etc.
package app;
import com.mysql.cj.jdbc.MysqlDataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
public class Database {
public static MysqlDataSource dataSource;
public static void InitializeData() {
dataSource = new MysqlDataSource();
dataSource.setUser("Quiz");
dataSource.setPassword("Give the quiz");
dataSource.setServerName("localhost");
dataSource.setPort(3306);
dataSource.setDatabaseName("QUIZDATA");
Connection con = Main.getConnection();
try {
Statement st2 = con.createStatement();
st2.execute("CREATE TABLE IF NOT EXISTS Subject1(Question VARCHAR, Option1 VARCHAR, Option2 VARCHAR, Option3 VARCHAR, Option4 VARCHAR, Answer VARCHAR)");
}
catch (SQLException e) {
e.printStackTrace();
}
}
}
And here is my Main class.
package app;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.stage.Stage;
import java.sql.Connection;
import java.sql.SQLException;
public class Main extends Application {
#Override
public void start(Stage stage) throws Exception
{
Parent scene = FXMLLoader.load(getClass().getResource("quiz.fxml"));
stage.setTitle("Quiz");
stage.setScene(new Scene(scene));
stage.show();
}
public static void main(String[] args)
{
launch(args);
Database.InitializeData();
}
public static Connection getConnection()
{
Connection con = null;
try
{
con = Database.dataSource.getConnection();
}
catch (SQLException e)
{
Alert alert = new Alert(Alert.AlertType.ERROR, "Database error", ButtonType.OK);
alert.showAndWait();
}
return con;
}
}
But when I am scanning for any new server in the Mysql workbench, it is not showing any new server.
Add:- When I am right clicking on the blank area(Mysql Workbench), there is a option to "to add connections from clipboard"(Although I don't know what it is doing), it is returning an error :- "Could not parse connection parameters from string "Give the quiz" " (which is the password)"
But when I am scanning for any new server in the Mysql workbench, it
is not showing any new server.
This is not related to your program. First, you need to make sure that your MySQL database is running and then try to execute your program.
Apart from this, although you will be able to run your program once you ensure that your MySQL server is up and running, your program has not been designed well e.g. you should consider the following:
MysqlDataSource dataSource should be marked as private and then you should have public getter for it
Connection getConnection() should be defined in your class Database
You should have constructors and field getters and setters in your class Database
Please note that the above-mentioned points are just a few recommendations and it is not a complete list. I recommend you understand OOPS concept well and apply it in all your programs.

Eclipse Rich Client Application Connect to database

i'm starting a new Eclipse RCP application and it's my first time and i have a problem , i want to display list of my available database(by the way i'm using nosql database(MongoDB)) but my code seems not to work, can anyone help please , can anyone point me to a good tutorial
thanks for your time and help guys.
package test2.parts;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.eclipse.e4.ui.di.Focus;
import org.eclipse.e4.ui.di.Persist;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCursor;
import org.eclipse.swt.widgets.Label;
public class SamplePart {
org.eclipse.swt.widgets.List list ;
private TableViewer tableViewer;
#Inject
private MPart part;
#PostConstruct
public void createComposite(Composite parent) {
parent.setLayout(new GridLayout(1, false));
Text txtInput = new Text(parent, SWT.BORDER);
txtInput.setMessage("Enter text to mark part as dirty");
txtInput.addModifyListener(e -> part.setDirty(true));
txtInput.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
list = new org.eclipse.swt.widgets.List(parent, SWT.BORDER);
tableViewer = new TableViewer(parent);
tableViewer.setContentProvider(ArrayContentProvider.getInstance());
tableViewer.setInput(createInitialDataModel());
tableViewer.getTable().setLayoutData(new GridData(GridData.FILL_BOTH));
}
#Focus
public void setFocus() {
tableViewer.getTable().setFocus();
}
#Persist
public void save() {
part.setDirty(false);
}
private List<String> createInitialDataModel() {
MongoClient mongoClient = new MongoClient("localhost", 27017);
ArrayList<String> dbs = new ArrayList<String>();
MongoCursor<String> dbsCursor = mongoClient.listDatabaseNames().iterator();
while (dbsCursor.hasNext()) {
list.add(dbsCursor.next());
}
return (List<String>) list;
}
}
The stack trace shows that the plug-in can't find the MongoClient class.
Eclipse plug-ins can only access code in other plug-ins or in jars included in the plug-in. They can't use jars which are just on the ordinary Java classpath.
So you will need to add the jar containing the MongoClient class in to your plugin and add it to the Bundle-Classpath in the MANIFEST.MF. You can do that in the MANIFEST.MF editor in the 'Classpath' section of the 'Runtime' tab.
You also need to include the jar in the build.properties file.

Program will not run when turned into .jar

I have tried many methods over the last few days with no success...I've trawled through various Stackoverflow entries and to no avail...I must be missing something.
I have tried across three different IDEs...IntelliJ, Eclispe and Netbeans.
The problem is when trying to turn my program into an executable jar it is unable to run (either by double clicking or running through command).
When executing the following on command:
java -jar D:\Computing\Programming\Java\Projects\JavaFXGameMenu\out\artifacts\JavaFXGameMenu_jar\JavaFXGameMenu.jar
I get: Error: Could not find or load main class root.Main
When i run the same but with javaw instead.. i get not error message, but nothing happens either.
I am predominately using IntelliJ as its a JavaFX application that I am building.
This is the project hierarchy:
When creating the Artifact I choose the following based upon other threads:
I then re run this using: Java -jar D:\Computing\Executables\JavaFXGameMenu.jar
I get the following issue:
I have put the relevant environment variables into my system and Path and I am using jre1.8.0_144.
Any help with tracking down what the problem could be is greatly appreciated
Code below...but this fully compiles and runs within IDE without errors...the problem is when its turned into a .jar and ran from command.
package root;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.Window;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
public class Main extends Application {
private double width = 1920;
private double height = 1080;
private Parent createContent(){
Pane root = new Pane();
root.setPrefSize(width, height); //W:860 H:600
ImageView imgLogo = null;
ImageView bottomlogo = null;
MenuItem newGame = new MenuItem("NEW GAME");
MenuItem continueGame = new MenuItem("CONTINUE");
MenuItem friends = new MenuItem("FRIENDS");
MenuItem settings = new MenuItem("SETTINGS");
MenuItem store = new MenuItem("STORE");
MenuItem exit = new MenuItem("EXIT");
try(InputStream is = Files.newInputStream(Paths.get("src/resources/Images/dark.jpg"))) {
ImageView img = new ImageView(new Image(is));
img.setFitWidth(width);
img.setFitHeight(height);
root.getChildren().add(img);
} catch (IOException e){
System.out.println("Couldn't Load Image");
}
try(InputStream is = Files.newInputStream(Paths.get("src/resources/Images/logo.png"))) {
imgLogo = new ImageView(new Image(is));
imgLogo.setX(1000);
imgLogo.setY(100);
imgLogo.setFitWidth(600);
imgLogo.setFitHeight(300);
} catch (IOException e){
System.out.println("Couldn't Load Image");
}
try(InputStream is = Files.newInputStream(Paths.get("src/resources/Images/SteamAgony.png"))) {
bottomlogo = new ImageView(new Image(is));
bottomlogo.setX(100);
bottomlogo.setY(800);
bottomlogo.setFitHeight(200);
bottomlogo.setFitWidth(200);
bottomlogo.setOpacity(0.7);
} catch (IOException e){
System.out.println("Couldn't Load Image");
}
MenuBox menu = new MenuBox(
newGame,
continueGame,
friends,
settings,
store,
exit);
menu.setTranslateX(width / 3.4);
menu.setTranslateY(height / 2.5);
settings.setOnMouseClicked(event -> new SceneCreator().createScene(200,300));
exit.setOnMouseClicked( event -> Platform.exit());
root.getChildren().addAll(menu, imgLogo, bottomlogo);
return root;
}
#Override
public void start(Stage primaryStage) throws Exception{
Scene scene = new Scene(createContent());
primaryStage.setScene(scene);
primaryStage.initStyle(StageStyle.UNDECORATED);
primaryStage.show();
}
#Override
public void stop(){
//TODO
}
public static void main(String[] args) {
launch(args);
}
}
The error is at Main.createContent line 102. Maybe you forgot to initialize the child node (I'm not really familiar with JavaFX).
As #cedrikk mentioned, the problem is related to your code in Main.createContent.
You said the problem is when trying to run the jar as an executable -
did you try to run it within the IDE? If not - you should try to, and while at it - debug it to help you find the problem. Just right click your Main class and choose debug.
Regarding running it with javaw, the reason you got no error messages is because javaw executes java programs without a console - where you would normally get error messages unless using some logging solution.
You are adding a null element as a child of a Pane, causing the null pointer issue you are facing, if you use the debugger you'll be able to find where the variable that shouldn't be null is being set to null.
Edit - after code added
You are seeing 2 fields in try catches (imageLogo, bottomLogo), and adding them even if they fail, which adds nulls, causing the error.
You use a relative path for the images, this is probably the issue, are you running the jar from the project root? If not you could put the absolute path, but using resources would be more reliable, and allow the jar to run on different computers.
The problem was down to declaring inputStreams.
This works for both in IDE and running from jar:
String bgImg = "root/resources/dark.jpg";
URL bgImgPath = Main.class.getClassLoader().getResource(bgImg);
ImageView img = new ImageView(new Image(bgImgPath.toExternalForm()));
img.setFitWidth(width);
img.setFitHeight(height);
root.getChildren().add(img);
Compared to what I had before:
try(InputStream is = Files.newInputStream(Paths.get("src/resources/Images/dark.jpg"))){
ImageView img = new ImageView(new Image(is));
img.setFitWidth(width);
img.setFitHeight(height);
root.getChildren().add(img);
}catch (IOException e) {
System.out.println("Could not load");
}
The changes to the paths, were from where I tried adding the resource folder to the root folder instead of within src.

java.sql import not working

My .getTables and .prepareStatement are not working. I thought I only had to import the java.sql.* for these to work. Please let me know what else I need to do. Thank you for your time. It says "cannot find symbol" next to both lines and will not compile.
import edu.lcc.citp.inventory.Product;
import java.sql.DriverManager;
import javax.jms.Connection;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import javax.jms.JMSException;
public class DatabaseProductDao implements DataAccessObject<Product> {
Connection con;
public DatabaseProductDao() throws SQLException, JMSException, ClassNotFoundException {
Class.forName("cockeb.org.apache.derby.jdbc.ClientDriver");
try (Connection con = (Connection) DriverManager.getConnection("jdbc:derby://localhost:1527/store;create=true")) {
boolean exists = con.getMetaData().getTables(null, null, "PRODUCT", null).next();
if (exists) {
System.out.println("Table Exists");
} else {
String createDml = "CREATE TABLE PRODUCT (UPC VARCHAR(25), SHORT_DETAILS VARCHAR(50), LONG_DETAILS VARCHAR(5000), PRICE DECIMAL(10,2), STOCK INTEGER, PRIMARY KEY (UPC))";
PreparedStatement createStatement = con.prepareStatement(createDml);
createStatement.execute();
}
} catch (SQLException e) {
System.out.println("Can Not Connect At This Time");
}
}
The problem is with imports.
You imported javax.jms.Connection which is obiously wrong. Just delete it.
What you wanted is Connection class from java.sql (java.sql.Connection) package.
Also I do not suggest to use wildcards (.*) in import but pick specific class you actually use. In your case:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
You need to add the following imports
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
instead of the one you are using
I'd suggest that you remove these lines:
import javax.jms.Connection;
import javax.jms.JMSException;
...as it's probably not the Connection class that you actually intended on importing. Your java.sql.* import should grab the correct one once you remove the lines above.
Some of your imports are wrong. You need below to make it work.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Connection;
One step ahead I would like to suggest you to have a separate class to establish the database connection. This way you don't need to repeat the same code again.
Sample code. (Do changes for this as appropriate.)
for instance have a DatabaseCon.java class in your project
package classes;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class DatabaseCon {
private static Connection c;
private static void connect()
throws Exception {
Class.forName("com.mysql.jdbc.Driver").newInstance();
String url = "db_url/db";
c = DriverManager.getConnection(url, "username", "pass");
}
public static PreparedStatement prepareState(String sql)
throws Exception {
if (c == null) {
connect();
}
return c.prepareStatement(sql);
}
}
This can then be called by
public void yourMethod() {
PreparedStatement p = null;
try {
p = DatabaseCon.prepareState("Your_query");
............
} catch (Exception e) {
//catch it
} finally {
//do the final stuff
}
}
Note This way is good if it is a fairly big project as you've mentioned.
You have imported a few wrong classes for use.
import java.sql.DriverManager;
import javax.jms.Connection;
import java.sql.*;
import javax.jms.JMSException;
The jms imports are of no use; you have imported them in vain, which is causing issues in your program.
The main import required is java.sql.*,
the application will work correctly if you just remove the jms imports.
But, the best practice to import classes is to specify the specific class from which you are using the element/method.
See here for the reason Single import vs package import

connecting scenebuilder UI fxml with javafx application

I have designed a UI in javafx scene builder, which has a simple button in stackpane.And I have named the controller class as simplecclass. I have saved the fxml as simple.fxml.
I have created a controller class in netbeans, which simply prints some msg on clicking the button.
In the NewFXBuilder java , I have loaded simple.fxml. Please find below the NewFXBuilder.java code.
package javafxapplication2;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.fxml.FXMLLoader;
public class NewFXbuilder extends Application {
#Override
public void start(Stage primaryStage) {
try {
StackPane page = (StackPane) FXMLLoader.load(NewFXbuilder.class.getResource("simple.fxml"));
Scene scene = new Scene(page);
primaryStage.setScene(scene);
primaryStage.setTitle("FXML is Simple");
primaryStage.show();
} catch (Exception ex) {
Logger.getLogger(NewFXbuilder.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String[] args) {
Application.launch(NewFXbuilder.class, (java.lang.String[])null);
}
}
My simple.fxml,simplecclass.java and NewFXbuilder.java all resides in the same folder javafxapplication2.
while running NewFXBuilder.java, but it gives me the following error.
javafxapplication2.NewFXbuilder start
SEVERE: null
javafx.fxml.LoadException: java.lang.ClassNotFoundException: simplecclass
javafxapplication2.NewFXbuilder start SEVERE: null
javafx.fxml.LoadException: java.lang.ClassNotFoundException:
simplecclass
Looks like a problem in the FXML file. Make sure you import simplecclass in the FXML file.
The mistake I did was forgotten to add java packagename in the controller class name field in scene builder. It should have been packagename.simplecclass but I gave simplecclass alone,which is a mistake.

Categories