Jar file with openCV and javafx - java

I made a rubiks cube application which includes a cube detection system, As im getting closer to wrapping up the project I wanted to make a JAR file. I get errors when running the JAR file and it really sucks because I can only run the project in IntelliJ(IDE).
I face two problems:
1) I cant get the JAR to link openCV properly
2)I have a problem loading an FXML file(this will occur assuming it did not crash while trying to load openCV.
For case 1 here is the code and errors:
static {
// try {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// } catch (UnsatisfiedLinkError e) {
// System.err.println("Could not find OpenCV Library!");
// }
}
and the error message:
Exception in thread "JavaFX Application Thread" Exception in thread "main" java.lang.UnsatisfiedLinkError: no opencv_java342 in java.library.path:
Now If i remove the try catch comments i get this error:
static {
try {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
} catch (UnsatisfiedLinkError e) {
System.err.println("Could not find OpenCV Library!");
}
}
#Override
public void start(Stage primaryStage) throws Exception {
//Loader
FXMLLoader loader = new FXMLLoader(main.class.getResource("FXML_layouts\\MainScreen.fxml"));
Scene scene = new Scene(loader.load());
((mainController)loader.getController()).setStage(primaryStage);
primaryStage.setScene(scene);
primaryStage.show();
}
Error:
Could not find OpenCV Library!
Exception in Application start method
java.lang.reflect.InvocationTargetException
....
Caused by: java.lang.IllegalStateException: Location is not set.
Here is my file structure:
and here is my artifact config:

Just go with the steps below:
Put the opencv_java342.dll in a folder let call it dll_libs in a
drive e.g C:\dll_libs
Then go to Environment Variable -> Edit path -> put C:\dll_libs ->
Apply -> OK
Restart your IDE
OR: Just put the opencv_java342.dll file in the C:\Windows\System32 folder
And it is : )
Update (for your second question): If you want to give the executable package to someone else to run the program, there are almost 2 ways:
Let them to create the environment manually, just as the answer to
your question.
Do the job programmatically, just within your code write a function
which set the .dd environment variable on the program startup, and
then load the lib.
If you choose the second one, here I will give an example code to refere to:
public static void loadOpenCVLib() throws Exception {
File file = new File(OpenCVUtil.class.getProtectionDomain().getCodeSource().getLocation().getPath());
File opencv_libs = new File("oc_lib"); // this path is where is the lib going to copy to
String model = System.getProperty("sun.arch.data.model");
String localLibPath; // this is the path inside your program resource
if (model.equals("64")) {
localLibPath = "oc_lib/64bit";
} else {
localLibPath = "oc_lib/x86";
}
if (file.isFile()) { // when run from jar
JarFile jar = new JarFile(file);
if (!opencv_libs.exists() || !opencv_libs.isDirectory()) {
try {
JarUtils.copyResourcesToDirectory(jar, localLibPath, opencv_libs.getAbsolutePath());
} catch (Exception e) {
throw new IOException("Failed to create load opencv libs!!");
}
} else {
String[] list = opencv_libs.list();
if (list != null && list.length != 2) {
try {
JarUtils.copyResourcesToDirectory(jar, localLibPath, opencv_libs.getAbsolutePath());
} catch (Exception e) {
throw new IOException("Failed to create load opencv libs!!");
}
}
}
} else { // when run from IDE
File libPath = new File(OpenCVUtil.class.getResource("/"+localLibPath).getFile());
if (!opencv_libs.exists() || !opencv_libs.isDirectory()) {
boolean isDone = opencv_libs.mkdir();
if (!isDone && !opencv_libs.exists()) {
throw new IOException("Failed to create load opencv libs!!");
}
try {
FileUtils.copyDirectory(libPath, opencv_libs);
} catch (IOException e) {
throw new IOException("Failed to create load opencv libs!!");
}
} else {
String[] list1 = opencv_libs.list();
String[] list2 = libPath.list();
boolean contentEquals = list1 != null && list2 != null && list1.length == list2.length;
if (contentEquals) {
try {
FileUtils.copyDirectory(libPath, opencv_libs);
} catch (IOException e) {
throw new IOException("Failed to create load opencv libs!!");
}
}
}
}
System.setProperty("java.library.path", opencv_libs.getAbsolutePath());
Field sys_paths = ClassLoader.class.getDeclaredField("sys_paths");
sys_paths.setAccessible(true);
sys_paths.set(null, null);
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// it is for the ffmpeg name
String[] list = opencv_libs.list();
assert list != null;
String ffmpeg_dll_file_name = null;
for (String s : list) {
if (s.contains("ffmpeg")) {
ffmpeg_dll_file_name = s.substring(0, s.indexOf("."));
}
}
System.loadLibrary(ffmpeg_dll_file_name);
}
Hope it can help!!

Related

Files.delete did not delete the folder correctly

In the springboot project, after the files have been merged, they need to be deleted.
The main code for the merge method is:
// chunkFolder indicates the file storage folder path
Files.list(Paths.get(chunkFolder))
.filter(path -> path.getFileName().toString().contains(HYPHEN))
.sorted((p1, p2) -> {
String fileName1 = p1.getFileName().toString();
String fileName2 = p2.getFileName().toString();
int index1 = fileName1.indexOf(HYPHEN);
int index2 = fileName2.indexOf(HYPHEN);
return Integer.valueOf(fileName1.substring(0, index1)).compareTo(Integer.valueOf(fileName2.substring(0, index2)));
})
.forEach(path -> {
try {
Files.write(Paths.get(target), Files.readAllBytes(path), StandardOpenOption.APPEND);
} catch (IOException e) {
e.printStackTrace();
}
}
);
The delete method is:
public void deleteDirectory(Path targetPath) throws IOException {
Files.walk(targetPath).sorted(Comparator.reverseOrder()).forEach(path -> {
try {
Files.delete(path);
} catch (IOException e) {
e.printStackTrace();
}
});
}
In the windows environment test, delete the storage path after merging. However, the results show that the folder still exists, but cannot be accessed. If you stop the springboot project, the folder disappears.
This problem happens on Windows when you are not closing all the directory streams correctly. You must close all directory streams scanned in your code. The two examples you've shown can be fixed with try with resources:
try(Stream<Path> stream = Files.list( ... )) {
... your code
stream.xyz(...);
}
... plus same for Files.walk() in deleteDirectory. Check other similar calls in all code.
When this occurs the directory is in a strange state when viewed in Windows Explorer - visible but not accessible. Shutting down the VM clears up correctly and the folder disappears from Explorer.

Desktop.getDesktop().open(file) on Ubuntu not working

I have a Java application, and when I use java.awt.Desktop:
Desktop.getDesktop().open(file);
It works fine on Windows (opens a file in my default program), but on Ubuntu (with openJdk 13), the Java application gets stuck and I do not even get any log error or anything. I have to force quit the app in order to recover.
The file path it correct, otherwise I would actually get an Exception. Also, isDesktopSupported a isSupported(Action.OPEN) returns true.
What can I do? Can I check some system settings or logs? Or perhaps get some logs from java.awt.Desktop? Or does this not work on Ubuntu/Linux?
Are there any alternatives?
From here:
In order to use the API, you have to call java.awt.EventQueue.invokeLater() and call methods of the Desktop class from a runnable passed to the invokeLater():
void fxEventHandler() {
EQ.invokeLater(() -> {
Desktop.open(...);
});
}
I am just going to add an example function
private static void OpenFile(String filePath){
try
{
//constructor of file class having file as argument
File file = new File(filePath);
if(!Desktop.isDesktopSupported())//check if Desktop is supported by Platform or not
{
System.out.println("not supported");
return;
}
Desktop desktop = Desktop.getDesktop();
if(file.exists()) { //checks file exists or not
EventQueue.invokeLater(() -> {
try {
desktop.open(file);
} catch (IOException e) {
throw new RuntimeException(e);
}
});
}
}
catch(Exception e)
{
e.printStackTrace();
}
}

Desktop.getDesktop.open() in Java fails

I have this piece of code:
public void openSelectedFiles(MouseEvent mouseEvent){
ListView<String> listView = (ListView<String>) ((Node) mouseEvent.getSource())
.getScene().lookup("#listOfReferenceFiles");
String selectedFileString = listView.getSelectionModel().getSelectedItem();
System.out.println(Desktop.isDesktopSupported());
File fileToOpen = new File(selectedFileString);
System.out.println(fileToOpen.exists());
try {
Desktop.getDesktop().open(fileToOpen);
} catch (IOException e) {
e.printStackTrace();
}
}
I am using Java 8, and it seems to be working, until this line:
Desktop.getDesktop().open(fileToOpen);
It does not throw an exception, it just freezes my application. Is this a bug?
You must check first if desktop is allowed and if file exists to avoid this kind of problems:
//first check if Desktop is supported by Platform or not
if(!Desktop.isDesktopSupported()){
System.out.println("Desktop is not supported");
return;
}
Desktop desktop = Desktop.getDesktop();
// after check if file exists and open it
if(file.exists()) desktop.open(file);

javax.media.NoPlayerException: Cannot find a Player for wav files in jar

I use Java Media Framework 2.1.1 for playing sounds in my application. It works fine from IDE but once I make jar package. The Player objects cannot be initialized with exception:
javax.media.NoPlayerException: Cannot find a Player for :jar:file:...
I create players using javax.media.Manager.createPlayer(URL sourceURL) method. I suspect that the URL from jar is causing the problems.
Is there an alternative way how to construct the player with files from jar?
Code:
public SoundPlayer() {
urlExplosion = ResourceLoader.getInstance().getSoundResourceUrl(SoundResource.EXPLOSION);
urlTick = ResourceLoader.getInstance().getSoundResourceUrl(SoundResource.TICK);
urlWin = ResourceLoader.getInstance().getSoundResourceUrl(SoundResource.WIN);
}
public void initialize() throws ResourceLoadingException{
try {
explosionPlayer = Manager.createPlayer(urlExplosion);
explosionPlayer.realize();
tickPlayer = Manager.createPlayer(urlTick);
tickPlayer.realize();
winPlayer = Manager.createPlayer(urlWin);
winPlayer.realize();
} catch (NoPlayerException e) {
throw new ResourceLoadingException("Could not initialize the sound player",e);
} catch (IOException e) {
throw new ResourceLoadingException("Could not initialize the sound player",e);
}
isInitialized = true;
}
Note: the URLs are no null during runtime.
Error when run from command line: java -jar minesweeper.jar
Caused by: javax.media.NoPlayerException: Cannot find a Player for :jar:file:/path/to/app/minesweeper.jar!/my/package/minesweeper/gui/explosion.wav

Not possible to launch a file on a network using Java Desktop?

(I have a problem that I illustrated in this question but had no correct answers. I refined my problem and tried to edit the initial question to reflect that but I guess because of the way SO displays unanswered questions it lost momentum and there is no way to revive it. So I am posting my correct question again).
I have a file that resides on a shared network location :
"\\KUROSAVVAS-PC\Users\kuroSAVVAS\Desktop\New Folder\Warsaw Panorama.JPG"
(The spaces are there intentionally)
The following code :
import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
try {
String s = "\\\\KUROSAVVAS-PC\\Users\\kuroSAVVAS\\Desktop\\New Folder\\Warsaw Panorama.jpg";
File f = new File(s);
System.out.println(f.exists());
Desktop.getDesktop().open(f);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Prints to the console that the file exists (System.out.println(f.exists());) but throws this exception! :
java.io.IOException: Failed to open file:////KUROSAVVAS-PC/Users/kuroSAVVAS/Desktop/New%20%20%20%20%20Folder/Warsaw%20%20%20%20Panorama.jpg. Error message: The system cannot find the file specified.
at sun.awt.windows.WDesktopPeer.ShellExecute(WDesktopPeer.java:59)
at sun.awt.windows.WDesktopPeer.open(WDesktopPeer.java:36)
at java.awt.Desktop.open(Desktop.java:254)
at Test.main(Test.java:13)
Has anyone any idea why something like this may happen? I have tried everything from creating URIs to decoding them afterwards... Nothing works.
With java 7 you can do this
public static void main(String[] args) throws IOException {
String s = "\\\\KUROSAVVAS-PC\\Users\\kuroSAVVAS\\Desktop\\New Folder\\Warsaw Panorama.jpg";
Path p = Paths.get(s);
Desktop.getDesktop().browse(p.toUri());
}
Java 6 solution:
public static void launchFile(File file) {
if (!Desktop.isDesktopSupported())
return;
Desktop dt = Desktop.getDesktop();
try {
dt.open(file);
} catch (IOException ex) {
// this is sometimes necessary with files on other servers ie
// \\xxx\xxx.xls
launchFile(file.getPath());
}
}
// this can launch both local and remote files
public static void launchFile(String filePath) {
if (filePath == null || filePath.trim().length() == 0)
return;
if (!Desktop.isDesktopSupported())
return;
Desktop dt = Desktop.getDesktop();
try {
dt.browse(getFileURI(filePath));
} catch (Exception ex) {
ex.printStackTrace();
}
}
// generate uri according to the filePath
private static URI getFileURI(String filePath) {
URI uri = null;
filePath = filePath.trim();
if (filePath.indexOf("http") == 0 || filePath.indexOf("\\") == 0) {
if (filePath.indexOf("\\") == 0){
filePath = "file:" + filePath;
filePath = filePath.replaceAll("#", "%23");
}
try {
filePath = filePath.replaceAll(" ", "%20");
URL url = new URL(filePath);
uri = url.toURI();
} catch (MalformedURLException ex) {
ex.printStackTrace();
} catch (URISyntaxException ex) {
ex.printStackTrace();
}
} else {
File file = new File(filePath);
uri = file.toURI();
}
return uri;
}
This answer was on the bug report, but I've edited it to fix when there is a hash.
TL;DR of ZAMMBI's answer (+1 BTW). (Using Java 6)
This works, as expected
Desktop.getDesktop().open(new File("\\\\host\\path_without\\spaces.txt")); //works
This fails, due to a known Java bug:
Desktop.getDesktop().open(new File("\\\\host\\path with\\spaces.txt")); //fails <shakes fist>
This work-around works
Desktop.getDesktop().browse(new URI("file://host/path%20with/spaces.txt")) //works (note slash direction and escape sequences)
This work-around seems like it should work, but does not:
Desktop.getDesktop().browse((new File("\\\\host\\path with\\spaces.txt")).toURI());
This work-around works, and seems to be the most general form:
File curFile = new File("\\\\host\\path with\\or_without\\spaces\\local or network.txt");
Desktop.getDesktop().browse(new URI(curFile .toURI().toString().replace("file:////","file://")));
It seems that there is a bug when you try to access a resource on a network drive with spaces in the path. See this entry in Sun's bug database.
Since the bug is already a year old, I don't think you'll get a fix anytime soon. Try the latest VM. If that doesn't help, try to get the source for WDesktopPeer. Instead of encoding the path, try to keep it as it was (with backslashes and all) and put quotes around it. That might work.
[EDIT] Specifically, don't replace \ with /, do not prepend file:// and leave the spaces as they are (instead of replacing them with %20)

Categories

Resources