Using Processing libraries - in a Java file in a Processing sketch? - java

Somewhat of a followup to How to use public class frome .java file in other processing tabs?; using the example from Usage class from .java file - is there a full doc for that? - Processing 2.x and 3.x Forum, I have this:
/tmp/Sketch/Sketch.pde
// forum.processing.org/two/discussion/3677/
// usage-class-from-java-file-is-there-a-full-doc-for-that
Foo tester;
void setup() {
size(600, 400, JAVA2D);
smooth(4);
noLoop();
clear();
rectMode(Foo.MODE);
fill(#0080FF);
stroke(#FF0000);
strokeWeight(3);
tester = new Foo(this);
tester.drawBox();
}
/tmp/Sketch/Foo.java
import java.io.Serializable;
//import peasy.org.apache.commons.math.geometry.Rotation;
//import peasy.org.apache.commons.math.geometry.Vector3D;
import processing.core.PApplet;
import processing.core.PGraphics;
public class Foo implements Serializable {
static final int GAP = 15;
static final int MODE = PApplet.CORNER;
final PApplet p;
Foo(PApplet pa) {
p = pa;
}
void drawBox() {
p.rect(GAP, GAP, p.width - GAP*2, p.height - GAP*2);
}
}
The example runs fine as is - but if I uncomment the import peasy.org... lines, then compilation fails with:
The package "peasy" does not exist. You might be missing a library.
Libraries must be installed in a folder named 'libraries' inside the 'sketchbook' folder.
Of course, I do have PeasyCam installed, under /path/to/processing-2.1.1/modes/java/libraries/peasycam/ - and it works fine, if I do a import peasy.*; from a .pde sketch.
I guess, this has something to do with paths - apparently pure Java files in a sketch, do not refer to the same library paths as .pde files in a sketch.
Is it possible to get this sketch to compile with the import peasy.org... lines (other than, I guess, copying/symlinking the peasycam library in the sketch folder, here /tmp/Sketch/ <--- EDIT: just tried symlinking as described, it doesn't work; the same error is reported)?

This is where you learn that Processing isn't actually Java, it just has a similar(ish) syntax and can run its code in the JVM by aggregating all .pde files into a single class that can be compiled for running on the JVM. Processing has its own rules for dealing with imports and the like.
Why not just do this entirely in Processing instead?
class Foo {
static int MODE = ...;
static int GAP = ...;
PApplet sketch;
public Foo(PApplet _sketch) {
sketch = _sketch;
...
}
void drawBox() {
sketch.rect(GAP, GAP, p.width - GAP*2, p.height - GAP*2);
}
...
}
and then make sure to have that in a file Foo.pde or something in the same dir as your sketch, with your sketch loading in the peasy library through the regular Processing import mechanism?

Ok, thanks to #MikePomaxKamermans answer, especially "by aggregating all .pde files into a single class", I simply tried importing peasy in the .pde file before the first reference to foo; that is, in /tmp/Sketch/Sketch.pde I now have:
// forum.processing.org/two/discussion/3677/
// usage-class-from-java-file-is-there-a-full-doc-for-that
import peasy.*; // add this
Foo tester;
...
... and then the sketch compiles without a problem (but note: while this approach works for this example, it somehow didn't work in the original problem that drove me to post the question).

Related

Soap Webservice Client for JAVAFX Application

I am trying to call the webservice for my application. If I call it in a sample project it is working perfectly fine. But when I merge it with My Java FX it is giving me so many errors. Web Service Client is auto generated using the Eclipse. I am trying to call the Methods only. Can Anyone help me?
Error: **Correction** I have edited it and I am using now JAVASE-15 and JVAFX-SDK 11.0.2
The package javax.xml.namespace is accessible from more than one module: java.xml, jaxrpc
Correction Update 2: I have removed Java.xml dependencies and module-info file as well.
but the new error is this
**Error: Could not find or load main class gload.Main
Caused by: java.lang.NoClassDefFoundError: javafx/application/Application**
and IF I keep the module info file it shows:
**Error occurred during initialization of boot layer
java.lang.module.FindException: Module javafx.graphics not found, required by gload**
Model:
package gload.model;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.swing.JOptionPane;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.datacontract.schemas._2004._07.PE_PPER_MyPdmWebServiceClient_Data.CustomerItem;
import org.datacontract.schemas._2004._07.PE_PPER_MyPdmWebServiceClient_Data.Result;
import org.tempuri.IService;
import org.tempuri.ServiceLocator;
public class PdmData
{
public String scode;
public boolean state = false;
public static String CdfFile;
public static String pdflocation;
public static String Custom_Ci;
public static String Generic_Ci;
public static String Mp_ref;
public static String Interface;
public static String Comments;
public static String PersoAppli;
public static String Code;
public static String Revision;
public static String Customer_Name;
public static String Customer_reference;
public static String getCode() {
return Code;
}
public static void setCode(String code) {
Code = code;
}
public static String getRevision() {
return Revision;
}
public static void setRevision(String revision) {
Revision = revision;
}
public static String getCustomer_Name() {
return Customer_Name;
}
public static void setCustomer_Name(String customer_Name) {
Customer_Name = customer_Name;
}
public static String getCustomer_reference() {
return Customer_reference;
}
public static void setCustomer_reference(String customer_reference) {
Customer_reference = customer_reference;
}
public static String getPersoAppli() {
return PersoAppli;
}
public static void setPersoAppli(String persoAppli) {
PersoAppli = persoAppli;
}
public static String getGeneric_Ci() {
return Generic_Ci;
}
public static void setGeneric_Ci(String generic_Ci) {
Generic_Ci = generic_Ci;
}
public static String getCdfFile() {
return CdfFile;
}
public static void setCdfFile(String cdfFile) {
CdfFile = cdfFile;
}
public static String getPdflocation() {
return pdflocation;
}
public static void setPdflocation(String pdflocation) {
PdmData.pdflocation = pdflocation;
}
public String Cdffile(String reference) {
ServiceLocator locator = new ServiceLocator(); -------->Web Service Locator and call
try {
IService basicHttpBinding_IService = locator.getBasicHttpBinding_IService();
Result result = basicHttpBinding_IService.getFilebyDcode(reference);
//To download the files
String link = result.getLocation();
System.out.println(link);
File out = new File("C:\\TempDownload\\" + reference +".zip"); //Creating a zip file to store the contents of download file
new Thread(new Download(link,out)).start();
//To Unzip the file
Path source = Paths.get("C:\\TempDownload\\" + reference +".zip");
Path target = Paths.get("C:\\TempDownload\\Unzip");
try {
unzipFolder(source, target);
System.out.println("Done");
} catch (IOException e) {
e.printStackTrace();
}
//Creating a File object for directory
File directoryPath = new File("C:\\TempDownload\\Unzip\\Pre Ppc" + reference + "A_Released");
//List of all files and directories
String[] contents = directoryPath.list();
System.out.println("List of files and directories in the specified directory:");
FilenameFilter pdffilter = new FilenameFilter() {
public boolean accept(File dir, String name) {
String lowercaseName = name.toLowerCase();
if (lowercaseName.endsWith(".pdf")) {
return true;
} else {
return false;
}
}
};
String[] contents1 = directoryPath.list(pdffilter);
for(String fileName : contents1) {
System.out.println(fileName);
setCdfFile(fileName);
setPdflocation(directoryPath.toString());
}
//To extract the Data From PDF
File file = new File(getPdflocation() + "\\" + getCdfFile());
//FileInputStream fis = new FileInputStream(file);
PDDocument document = PDDocument.load(file);
PDFTextStripper pdfReader = new PDFTextStripper();
String docText = pdfReader.getText(document);
System.out.println(docText);
document.close();
//To extract details from document
String CI_Ref = "CI Ref";
int pos ;
pos = docText.indexOf(CI_Ref);
setGeneric_Ci(docText.substring(pos+7 , pos+15));
System.out.println("Generic CI: " + getGeneric_Ci());
//To get Details of CI
CustomerItem customerItem = basicHttpBinding_IService.getCiDetails(getGeneric_Ci());
setPersoAppli(customerItem.getPersoAppli());
setCode(customerItem.getCode());
setRevision(customerItem.getRevision());
setCustomer_Name(customerItem.getCustomerName());
setCustomer_reference(customerItem.getCustomerReference());
}catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null, "Unable to reach Service : " + e.getMessage());
}
return getPersoAppli();
}
Module info file
module gload {
requires javafx.controls;
requires javafx.fxml;
requires java.desktop;
requires java.rmi;
requires java.base;
requires axis;
requires jaxrpc;
requires org.apache.pdfbox;
opens gload;
opens gload.views.main;
opens gload.utils;
opens gload.model;
opens gload.controllers;
opens org.tempuri;
opens org.datacontract.schemas._2004._07.PE_PPER_MyPdmWebServiceClient_Data;
}
and IF I keep Jaxrpc in classpath instead of module path I get error like this Description
The type javax.xml.rpc.ServiceException cannot be resolved. It is indirectly referenced from required .class files
OK, this won't really be an answer, more pointers to related issues and potential approaches to come up with solutions. But I'll post it as an answer as it is likely better to do that than lots of comments.
Unfortunately, you have multiple errors and issues, so I'll try to deal with some of them seperately.
According to:
Java FX Modular Application, Module not found (Java 11, Intellij)
The error:
Error occurred during initialization of boot layer
java.lang.module.FindException:
Module X not found, required by Y
can occur when --module-path is wrong and the module can't be found. Probably, that is at least one of your issues. The linked answer is for Idea and I don't use Eclipse, so I don't know how to resolve the issue in Eclipse, but perhaps you could do some research to find out.
Regarding:
The package javax.xml.namespace is accessible from more than one module
there is some info on what is going on here:
Eclipse is confused by imports ("accessible from more than one module").
This fix appears tricky to me. Please review the linked questions and solutions. It looks like either you need to either
Forego Java 9+ modularity OR
Manage your dependencies to not include the violating transitive dependency OR
Change to a library that doesn't rely on the broken library (probably the preferred solution in this case).
The broken library causing this issue is likely the version of jaxrpc you are using. My guess is that some of the relevant XML libraries were only added to standard Java in Java 9, but the jaxrpc library you are using was developed prior to that. So, jaxrpc either includes the XML libraries in its classes or makes use of a transitive library that does the same. This causes a conflict because the XML libraries can only be included once in the project.
Further info on your issues is in this answer:
Eclipse can't find XML related classes after switching build path to JDK 10
The info is so ugly . . . you could read the answer, it may either help or discourage you.
Some things you could do to help resolve the situation
What should be done about this is kind of tricky and will depend on your skill level and how or if you can solve it. I'll offer up some advice on some things you could do, but there are other options. You know your application better than I so you may be able to come up with better solutions for your application.
I'd advise separating these things out, just as a way of troubleshooting, get a project which works with all of the JavaFX components and one which works with all of the SOAP components and make sure they build and do what you want. Then try to combine the two projects either by integrating them into one project or running them in separate VMs with communication between the two (e.g. via an added REST API, though that is a much more complicated solution, so think hard about that before attempting it).
Also, upgrade to the latest version of JavaFX. I don't think it will fix your issue, but it can't hurt and it is possible some refinements in recent JavaFX versions may have done some things which might help ease some of your issues (though not all of them, as some of your issues stem from jaxrpc usage in a modular project, which is unrelated to JavaFX).
Also, and probably more importantly, consider using a different SOAP client framework that interacts better with modular Java 9+ than the broken implementation that jaxrpc appears to have.
In terms of whether you should make your application modular or not (include a module-info or not), I don't really know the best approach for you. Certainly, whichever way you choose you will run into issues. But, the issues and how to resolve them will be different depending on the chosen solution path (as I guess you have already discovered during the course of your investigation for the question).
If necessary, isolate the issues down to single separate issues. If you need help in resolving each separate issue post new questions that feature minimal reproducible example code to replicate the issue. Mind if you do so, that the code is absolutely minimal and also complete so that it replicates and asks about only one issue, not a combination of more than one and that the questions are appropriate tagged - e.g. if the question is about jaxrpc and modularity it should include jaxrpc and modular tags and no JavaFX code or tags (and vice versa) and certainly on pdf code or dependencies anywhere if that isn't part of the problem.

JUnit Test not finding parent class in same package

Im in IntellijIdea, trying to extract some logic from my tests to be reused in others. The problem is everytime I create another class (in the same test package); the test runs fine, but then stops finding the other file, throwing a 'java: cannot find symbol' error. It seems to happen whenever I make changes to the orginal file. It's the same for any new class I try to create, not just the abstract parent class in this example.
I've searched similar questions here, and because the test works at first this seemed promising IntelliJ can't find classes in same package when compiling. But, there were no scripts excepted when I checked.
Currently I'm running my unit tests by just right clicking my tests folder and selecting 'Run all tests', or just running the individual test the same way.
I would be very grateful for any insights.
EDIT: Thanks for fixing the image formatting issue for me.
I also added the source code for the two classes as requested. I still feel like leaving the images is a good idea though, as I mainly meant to communicate the project structure and errors. Also, I want to stress that the problem is code independend I would say, since it persists with any two files.
Note that nonsensical line 51 of the InfoTest ("line = line;") was added to replicate the error. Any change to the original class causes any other class in the package to not be found. You can even see it's not present in the image showing the test running fine.
Extracted class:
package CommandProcessing;
import GameLogic.Game;
import org.junit.jupiter.api.BeforeEach;
import java.lang.reflect.Field;
import static org.junit.jupiter.api.Assertions.fail;
public abstract class InputSimulator {
protected Game game;
protected CommandParser commandParser;
#BeforeEach
void setUp() {
game = new Game();
try {
Class<?> gameClass = game.getClass();
Field cmdField = gameClass.getDeclaredField("commandParser");
cmdField.setAccessible(true);
commandParser = (CommandParser)cmdField.get(game);
} catch (Exception e){
fail(e);
}
}
protected void simulateInput(String input){
commandParser.handleInput(input);
}
class InputTestCase {
private String input;
private String expected;
public InputTestCase(String input, String expected){
this.input = input;
this.expected = expected;
}
public String getInput() { return input; }
public String getExpected() { return expected; }
}
}
Original class:
package CommandProcessing;
import Database.*;
import GameLogic.Game;
import Ship.*;
import IOHandler.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Field;
import java.util.ArrayList;
import static org.junit.jupiter.api.Assertions.*;
class InfoTest extends InputSimulator {
private final InputTestCase[] testCases =
{
new InputTestCase("info cpit", "Cockpit - health: 100.0, shields: 100.0"),
new InputTestCase("info engi", "Engine - health: 100.0, shields: 100.0"),
new InputTestCase("info shld", "Shields - health: 100.0, shields: 100.0"),
new InputTestCase("info weap", "Weapons - health: 100.0, shields: 100.0"),
new InputTestCase("info tank", "FuelTank - health: 100.0, shields: 100.0"),
new InputTestCase("info carg", "CargoBay - health: 100.0, shields: 100.0")
};
#Test
void printPartsOnInfo() {
simulateInput("info");
ArrayList<String> expected = new ArrayList<String>();
expected.add(game.dbAccess().getMessage(Message.Info));
for(PartType part : PartType.values()){
String partString = part.toString();
expected.add(partString);
}
ArchiveAccess archiveAccess = game.getArchiveAccess();
ArrayList<String> lines = archiveAccess.getOutput();
assertEquals(expected, lines);
}
#Test
void printPartDetails() {
for (InputTestCase testCase : testCases) {
simulateInput(testCase.getInput());
ArchiveAccess archiveAccess = game.getArchiveAccess();
String line = archiveAccess.lastOutput();
line = line;
assertEquals(testCase.getExpected(), line);
}
}
}
All errors:
Test running fine the first time:
No Excludes:
So, the problem was that the test root folder was in my source folder!
I actually had the right answer at one time, but read it badly:
How to create a test directory in Intellij 13?.
The test root folder should be next to a main folder which should be the one marked as the source root, not their parent 'src' folder. I had marked this parent directory as the source root - that is to say, the default source root was already called 'src' and I managed to put my test root folder in it, a project structure suspiciously hard to replicate as it would turn out. I got confused because of the naming.
It's a mystery to me how I got it to work in the first place, because when I tried to reproduce the problem it required some detours to get my test root inside my source root. And even then the tests couldn't even find the JUnit package at runtime (they did compile fine though).

class "Scanx" does not match the trust level of other classes in the same package

I'm attempting to use some other jar files that have functions I'd like to access. The are public, and I have sample code I built my test app from. It appears to be signing related (ie they are signed, mine was self-signed).
When I attempt to load the applet in a webpage I am asked if I wish to block or unblock. If I tell it to unblock I get the following error:
class "Scanx" does not match the trust level of other classes in the same package.
I've read at least a dozen different articles but they either don't apply or exceed my ability to understand at my current level of Java coding knowledge.
I'd really appreciate any thoughts on how to get past this so I can test & complete my java applet? Code is below:
<html><body>
<applet id=scanx name=scanx code="Scanx.class" height="600" width="600" archive="./Scanx.jar,./ij.jar,./plugin.jar,./twain.jar"></applet>
<script type="text/javascript">
function scanit()
{
document.scanx.getScan();
}
</script>
<input type=button onclick="scanit();">
</body></html>
Here's my java code, which I compile into a jar using "jar cvf Scanx.jar Scanx.java" ...
package uk.co.mmscomputing.device.twain.applet;
import javax.swing.JApplet;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.awt.image.RasterFormatException;
import javax.imageio.ImageIO;
import netscape.javascript.*;
import java.io.File;
import uk.co.mmscomputing.device.scanner.Scanner;
import uk.co.mmscomputing.device.scanner.ScannerListener;
import uk.co.mmscomputing.device.scanner.ScannerDevice;
import uk.co.mmscomputing.device.scanner.ScannerIOException;
import uk.co.mmscomputing.device.scanner.ScannerIOMetadata;
public class xScanx extends JApplet implements ActionListener, ScannerListener{
int index = 0;
String filename;
Scanner scanner;
public Scanx(){
}
public Scanx(String title, String[] argv){
init();
}
public void init(){
scanner=Scanner.getDevice();
scanner.addListener(this);
// scanner.select("TWAIN_32 Sample Source");
}
public void getScan()
{
try{
scanner.acquire();
}catch(ScannerIOException se){
se.printStackTrace();
}
}
public void actionPerformed(ActionEvent evt){
/*
try{
if(evt.getSource()==acquireButton){
scanner.acquire();
}else if(evt.getSource()==selectButton){
scanner.select();
}else if(evt.getSource()==cancelButton){
scanner.setCancel(true);
}
}catch(ScannerIOException se){
se.printStackTrace();
}
*/
}
public void update(ScannerIOMetadata.Type type, ScannerIOMetadata metadata){
if(type.equals(ScannerIOMetadata.ACQUIRED)){
BufferedImage image=metadata.getImage();
System.out.println("Have an image now!");
try{
ImageIO.write(image, "jpg", new File(filename+index+".jpg"));
index++;
// new uk.co.mmscomputing.concurrent.Semaphore(0,true).tryAcquire(2000,null);
}catch(Exception e){
e.printStackTrace();
}
}else if(type.equals(ScannerIOMetadata.NEGOTIATE)){
ScannerDevice device=metadata.getDevice();
}else if(type.equals(ScannerIOMetadata.STATECHANGE)){
System.err.println(metadata.getStateStr());
}else if(type.equals(ScannerIOMetadata.EXCEPTION)){
metadata.getException().printStackTrace();
}
}
public static void main(String[] argv){
try{
new Scanx("Twain Applet Example [2007-11-02]", argv);
}catch(Exception e){
e.printStackTrace();
}
}
}
The reported error message looks similar to the error when having two classes in the same package with different signatures. This has been illegal since back in the nineties. One of the differences is that the fully qualifies class name should be reported (it is about packages). It may be the case that the class is in fact in a default package, never a good idea. That would typically because the package name was added later, but an old class file that has hung around is being used.
The applet tag looks a bit wrong. code="Scanx.class" should have the package name in, which further suggests a stale class file. plugin.jar appears to be part of the PlugIN, so shouldn't be included when run in the plugin (but it will be necessary when compiling the code).
Then you say 'I compile into a jar using "jar cvf Scanx.jar Scanx.java"'. A little bit confusing. You should compile the .java file into a .class with javac. Then use jar to create the jar. The files you want should be .class not .java and should include the package name. If you look at the jar as a zip, it should have classes inside with directory paths matching package names (IIRC, jar tf Scanx.jar should list the files).

Post data from Matlab to Pachube (Cosm) using Java Methods

I am using JPachube.jar and Matlab in order to send data to my datastream. This java code works on my machine:
package smartclassroom;
import Pachube.Data;
import Pachube.Feed;
//import Pachube.FeedFactory;
import Pachube.Pachube;
import Pachube.PachubeException;
public class SendFeed {
public static void main(String arsg[]) throws InterruptedException{
SendFeed s = new SendFeed(0.0);
s.setZainteresovanost(0.3);
double output = s.getZainteresovanost();
System.out.println("zainteresovanost " + output);
try {
Pachube p = new Pachube("MYAPIKEY");
Feed f = p.getFeed(MYFEED);
f.updateDatastream(0, output);
} catch (PachubeException e) {
System.out.println(e.errorMessage);
}
}
private double zainteresovanost;
public SendFeed(double vrednost) {
zainteresovanost = vrednost;
}
public void setZainteresovanost(double vrednost) {
zainteresovanost = vrednost;
}
public double getZainteresovanost() {
return zainteresovanost;
}
}
but I need to do this from Matlab. I have tried rewriting example (example from link is working on my machine): I have compile java class with javac and added JPachube.jar and SendFeed.class into path and then utilize this code in Matlab:
javaaddpath('C:\work')
javaMethod('main','SendFeed','');
pachubeValue = SendFeed(0.42);
I get an error:
??? Error using ==> javaMethod
No class SendFeed can be located on Java class path
Error in ==> post_to_pachube2 at 6
javaMethod('main','SendFeed','');
This is strange because, as I said example from the link is working.
Afterwards, I decided to include JPachube directly in Matlab code and to write equivalent code in Matlab:
javaaddpath('c:\work\JPachube.jar')
import Pachube.Data.*
import Pachube.Feed.*
import Pachube.Pachube.*
import Pachube.PachubeException.*
pachube = Pachube.Pachube('MYAPIKEY');
feed = pachube.getFeed(MYFEED);
feed.updateDatastream(0, 0.54);
And I get this error:
??? No method 'updateDatastream' with matching signature found for class 'Pachube.Feed'.
Error in ==> post_to_pachube2 at 12
feed.updateDatastream(0, 0.54);
So I have tried almost everything and nothing! Any method making this work will be fine for me. Thanks for help in advance!
This done trick for me (answer from here)
javaaddpath('c:\work\httpcore-4.2.2.jar');
javaaddpath('c:\work\httpclient-4.2.3.jar');
import org.apache.http.impl.client.DefaultHttpClient
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.StringEntity
httpclient = DefaultHttpClient();
httppost = HttpPost('http://api.cosm.com/v2/feeds/FEEDID/datastreams/0.csv?_method=put');
httppost.addHeader('Content-Type','text/plain');
httppost.addHeader('X-ApiKey','APIKEY');
params = StringEntity('0.7');
httppost.setEntity(params);
response = httpclient.execute(httppost);
I would rather use built-in methods. Matlab hasurlread/urlwrite, which could work if all you wish to do is request some CSV data from Cosm API. If you do need to use JSON, it can be handled in Matlab via a plugin.
Passissing the Cosm API key, that can be done via key parameter like so:
cosm_feed_url = "https://api.cosm.com/v2/feeds/61916.csv?key=<API_KEY>"
cosm_feed_csv = urlread(cosm_feed_url)
However, the standard library methods urlread/urlwrite are rather limited. In fact, the urlwrite function is only designed for file input, and I cannot even see any official example of how one could use a formatted string instead. Creating a temporary file would reasonable, unless it's only a few lines of CSV.
You will probably need to use urlread2 for anything more serious.
UPDATE: it appears that urlread2 can be problematic.

Java Swing - How to double click a project file on Mac to open my application and load the file?

I have created a Mac Java Swing application, and i have set a file extension(*.pkkt) for it in the "Info.plist" file, so when double clicking that file it opens my application.
When i do that the program runs fine. Now i need to load the (*.pkkt) project in the program, but the file path is not passed as an argument to the main(...) method in Mac as happens in Windows Operating System.
After some search i found an Apple handling jar "MRJToolkitStubs" that has the MRJOpenDocumentHandler interface to handle such clicked files. I have tried using it to load that file by implementing that Interface in the main program class, but it is not working. The implemented method is never called at the program start-up.
How does this Interface run ?
------------------------------------------------- Edit: Add a Code Sample
Here is the code i am using :
public static void main( final String[] args ) {
.
.
.
MacOpenHandler macOpenHandler = new MacOpenHandler();
String projectFilePath = macOpenHandler.getProjectFilePath(); // Always Empty !!
}
class MacOpenHandler implements MRJOpenDocumentHandler {
private String projectFilePath = "";
public MacOpenHandler () {
com.apple.mrj.MRJApplicationUtils.registerOpenDocumentHandler(this) ;
}
#Override
public void handleOpenFile( File projectFile ) {
try {
if( projectFile != null ) {
projectFilePath = projectFile.getCanonicalPath();
System.out.println( projectFilePath ); // Prints the path fine.
}
} catch (IOException e) {}
}
public String getProjectFilePath() {
return projectFilePath;
}
}
As mentioned in the comment above "getProjectFilePath()" is always Empty !
On Java 9, use Desktop.setOpenFileHandler()
The proprietary com.apple.eawt packages have been removed from recent versions of Java and has been incorporated into various methods in the Desktop class. For your specific example:
import java.awt.desktop.OpenFilesHandler;
import java.awt.desktop.OpenFilesEvent;
import java.io.File;
import java.util.List;
public class MyOpenFileHandler implements OpenFilesHandler {
#Override
public void openFiles​(OpenFilesEvent e) {
for (File file: e.getFiles​()) {
// Do whatever
}
}
}
Then elsewhere, add this:
Desktop.getDesktop().setOpenFileHandler(new MyOpenFileHandler());
The OpenFilesEvent class also has a getSearchTerm() method. Say that a person used Spotlight on macOS to search for the word "StackOverflow", then decided to open up a document. With this method, can you determine that "StackOverflow" was the word they searched for, and choose to do something with that (perhaps highlight the first occurrence of the word).
You're going to want to use the Apple Java Extensions.
They should be included in any JDK that runs on Mac OS X, but the documentation is kind of hard to get. See this answer for more details.
Specifically, you'll want to make an OpenFilesHandeler.
This code snippet should work:
import com.apple.eawt.event.OpenFilesHandeler;
import com.apple.eawt.event.AppEvent;
import java.io.File;
import java.util.List;
class MacOpenHandler implements OpenFilesHandeler {
#Override
public void openFiles(AppEvent.OpenFilesEvent e) {
List<File> files = e.getFiles();
// do something
}
}
And somewhere:
import com.apple.eawt.Application;
...
MacOpenHandeler myOpenHandeler = new MacOpenHandeler();
Application.getApplication().setOpenFileHandler(myOpenHandeler);

Categories