I am writting a library to ease the development of JavaFX application, and in order to make it usable with Java modular system, I need to get the URL of the FXML file in another java module (the client module) and pass it to FXMLLoader in my library (the library module).
So to sum:
I need to get the resource URL of an FXML file in the client module to be read in the library module.
I tried:
Accessing resource files from external modules
Load a Resource from another Module in Java (With Maven)
My latest attempt:
private void addController(ControllerInfo info, Class<? extends SimpleController> controllerClass) throws IOException {
String filename = info.FXMLFile();
if (!filename.startsWith("/"))
filename = "/" + filename;
ModuleReference ref=ModuleLayer.boot().configuration().findModule(moduleName).map(ResolvedModule::reference).get();
ModuleReader resReader=ref.open();
URL url = resReader.find(filename).get().toURL();
controllerClasses.put(info.Id(), controllerClass);
info.Type().getAction().addController(info, url, controllerClass);
}
In the client module I have placed my resources inside a io/github/ossnass/languageexample folder in the resources folder, and the module-info.java looks like this:
module languageExample {
requires javafx.controls;
requires javafx.fxml;
requires simplefx;
opens io.github.ossnass.languageexample.gui to javafx.fxml;
opens io.github.ossnass.languageexample to simplefx;
exports io.github.ossnass.languageexample.app;
}
The FXML contoller class:
#ControllerInfo(Id = "LangMain", FXMLFile = "/io/github/ossnass/languageexample/langexample.fxml", Type = ContollerType.SINGLE_INSTANCE_ON_STARTUP)
public class LangExampleMain extends SimpleController {
#Override
protected void userInit() {
}
#Override
protected void onStageShowUser() {
}
#FXML
private Button btnMessage;
#FXML
void btnMessageClick(ActionEvent event) {
QuickActions.showInfoMessage(null,
resources.getString("InfoHeader"),
resources.getString("InfoBody"),
this);
}
}
I get the following error:
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.get(Optional.java:148)
at io.github.ossnass.fx.ControlMaster.addController(ControlMaster.java:179)
at io.github.ossnass.fx.ControlMaster.findControllers(ControlMaster.java:198)
at io.github.ossnass.fx.ControlMaster.initControlMaster(ControlMaster.java:134)
at io.github.ossnass.languageexample.app.Main.start(Main.java:11)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:277)
... 1 more
The URL path to the resource file is :/io/github/ossnass/languageexample/langexample.fxml
Please notice that I am using Maven and I put the FXMLs in the resources dir.
The library I am developing can be found at SimpleFX
I was able to solve the problem using ClassGraph library with some help of how to properly make the URL from VGR
The following bit of code solved all (Java 8 and Java 9+ with modular system):
public static Resource getRescoure(String urlStr) {
try (ScanResult scan = new ClassGraph().scan()) {
if (urlStr.startsWith("/"))
urlStr = urlStr.substring(1);
ResourceList rl = scan.getResourcesWithPath(urlStr);
if (rl.size() > 0)
return rl.get(0);
return null;
}
}
Related
I have a jar file which contains only testcase.class files. I need to parse that and find all the classes defined in that jar file and need to generate one report. I tried to do it with the reflection concept in Java. Some how, when loading a class is fine, but trying to get the declared methods of it, I am getting the following error. (Note class is loaded, I am able to get the name and canonical name of the loaded class but I error at trying to get declared methods).
for (String clazz: classes) {
String className = clazz.replaceAll("/",
".").replaceAll(".class","");
try {
URL url = file.toURI().toURL();
URL[] urls = new URL[]{url};
URLClassLoader cl = new URLClassLoader(urls);
Class cls = cl.loadClass(className);
System.out.println("##############################");
cls.getDeclaredMethods();
//clazzes.add(getClassObject(cls));
//break;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
Exception in thread "main" java.lang.NoClassDefFoundError: javax/mail/Authenticator
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:555)
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:458)
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:452)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:451)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at com.springboot.example.springBootExample.service.JarParserService.getTypes(JarParserService.java:99)
at com.springboot.example.springBootExample.service.JarParserService.constructPackages(JarParserService.java:86)
at com.springboot.example.springBootExample.service.JarParserService.getClassTypes(JarParserService.java:78)
at com.springboot.example.springBootExample.service.JarParserService.scanJar(JarParserService.java:61)
at com.springboot.example.springBootExample.service.JarParserService.getAllPackages(JarParserService.java:34)
at com.springboot.example.springBootExample.service.FindClassesFromJarService.parseJar(FindClassesFromJarService.java:61)
at com.springboot.example.springBootExample.service.FindClassesFromJarService.main(FindClassesFromJarService.java:31)
Caused by: java.lang.ClassNotFoundException: javax.mail.Authenticator
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:476)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 17 more
Process finished with exit code 1
I am writing a java web application which needs to load a native C++ dll via java source code. I have placed the dll called "myCPPlibrary.dll" and all the dependent DLLs at the same directory.
My function addLibraryPath ensures to add the path at which DLLs are located to add to java library path.
I was expecting this to work as main dll and dependent DLLs are all located in the same dir.
public class Test
{
public static void addLibraryPath(String pathToAdd) throws Exception
{
final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
usrPathsField.setAccessible(true);
//get array of paths
final String[] paths = (String[])usrPathsField.get(null);
//check if the path to add is already present
for(String path : paths) {
if(path.equals(pathToAdd)) {
return;
}
}
//add the new path
final String[] newPaths = Arrays.copyOf(paths, paths.length + 1);
newPaths[newPaths.length-1] = pathToAdd;
usrPathsField.set(null, newPaths);
}
static
{
try {
addLibraryPath("C:\\mydirA\\mydirB\\");
} catch (Exception aE) {
aE.printStackTrace();
}
// DLL name is myCPPlibrary.dll
System.loadLibrary("myCPPlibrary");
}
}
However , i still get
java.util.ServiceConfigurationError: com.test.wms.server.myfactory: could not be instantiated: java.lang.UnsatisfiedLinkError: C:\\mydirA\\mydirB\\\myCPPlibrary.dll: Can't find dependent libraries
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:363)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:307)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
Caused by: java.lang.UnsatisfiedLinkError: C:\\mydirA\\mydirB\\\myCPPlibrary.dll: Can't find dependent libraries
at java.base/java.lang.ClassLoader$NativeLibrary.load0(Native Method)
at java.base/java.lang.ClassLoader$NativeLibrary.load(ClassLoader.java:2442)
at java.base/java.lang.ClassLoader$NativeLibrary.loadLibrary(ClassLoader.java:2498)
at java.base/java.lang.ClassLoader.loadLibrary0(ClassLoader.java:2694)
at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2659)
at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:830)
... 31 common frames omitted
I'm using the Processing library in a simple Java project and I tried to make 3D but I got errors, this is my code :
package fr.ayfri;
import processing.core.PApplet;
import processing.core.PConstants;
public class Main extends PApplet {
public void settings() {
size(1600, 900, PConstants.P3D); // <--- P3D this tells Processing to work with 3D
}
public void draw() {
background(140, 190, 255);
}
public static void main(String[] args) {
String[] processingArgs = { "Main" };
Main main = new Main();
PApplet.runSketch(processingArgs, main);
}
}
But when I run the code I get this error :
java.lang.NoClassDefFoundError: com/jogamp/opengl/GLCapabilitiesImmutable
at processing.opengl.PGraphicsOpenGL.createPGL(PGraphicsOpenGL.java:712)
at processing.opengl.PGraphicsOpenGL.<init>(PGraphicsOpenGL.java:569)
at processing.opengl.PGraphics3D.<init>(PGraphics3D.java:35)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481)
at processing.core.PApplet.makeGraphics(PApplet.java:2266)
at processing.core.PApplet.createPrimaryGraphics(PApplet.java:2345)
at processing.core.PApplet.initSurface(PApplet.java:10983)
at processing.core.PApplet.runSketch(PApplet.java:10922)
at fr.ayfri.Main.main(Main.java:20)
Caused by: java.lang.ClassNotFoundException: com.jogamp.opengl.GLCapabilitiesImmutable
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 13 more
java.lang.RuntimeException: com/jogamp/opengl/GLCapabilitiesImmutable
at processing.core.PApplet.makeGraphics(PApplet.java:2299)
at processing.core.PApplet.createPrimaryGraphics(PApplet.java:2345)
at processing.core.PApplet.initSurface(PApplet.java:10983)
at processing.core.PApplet.runSketch(PApplet.java:10922)
at fr.ayfri.Main.main(Main.java:20)
Process finished with exit code 1
So I just don't know how to make this works ?
P3D uses OpenGL behind the scenes and you need to link against the native libraries.
In this case it's the jogl and gluegen-rt libraries present in Processing/Java/core/libraries: simply copy the correct jars for your platform (or all if you want to run the project on multiple platforms) and add them to the build path.
Here's an eclipse OSX example:
To enable https in my spring-boot app I did the following.
#Bean
#Inject
public EmbeddedServletContainerCustomizer containerCustomizer() throws FileNotFoundException
{
final String absoluteKeystoreFile = ZenoTuringServiceApp.class.getClassLoader().getResource("test.jks").getFile();
return (ConfigurableEmbeddedServletContainer factory) -> {
TomcatEmbeddedServletContainerFactory containerFactory = (TomcatEmbeddedServletContainerFactory) factory;
containerFactory.addConnectorCustomizers((TomcatConnectorCustomizer) (Connector connector) -> {
connector.setSecure(true);
connector.setScheme("https");
connector.setAttribute("keystoreFile", absoluteKeystoreFile);
connector.setAttribute("keystorePass", "test");
connector.setAttribute("keystoreType", "JKS");
connector.setAttribute("clientAuth", "false");
connector.setAttribute("sslProtocol", "TLS");
connector.setAttribute("SSLEnabled", true);
});
};
}
If I run it using mvn spring-boot:run it works as expected.
But when I run using the executable jar with java -jar target/xxx-xxx-service-0.1.17-SNAPSHOT.jar I get the FileNotFoundException.
Caused by: org.apache.catalina.LifecycleException: service.getName(): "Tomcat"; Protocol handler start failed
at org.apache.catalina.connector.Connector.startInternal(Connector.java:993)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 18 common frames omitted
Caused by: java.io.FileNotFoundException: /private/var/folders/wl/xxx77_523z44yjdgx2y7xxxc217h/T/tomcat.8061417798873093914.8091/file:/Users/xxx/Work/Himalay/xxx/xxx-xxx-service/target/xxx-xxx-service-0.1.17-SNAPSHOT.jar!/test.jks (No such file or directory)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at org.apache.tomcat.util.net.jsse.JSSESocketFactory.getStore(JSSESocketFactory.java:433)
at org.apache.tomcat.util.net.jsse.JSSESocketFactory.getKeystore(JSSESocketFactory.java:339)
at org.apache.tomcat.util.net.jsse.JSSESocketFactory.getKeyManagers(JSSESocketFactory.java:597)
The comments above and this code helped me..
// support loading the JKS from the classpath (to get around Tomcat limitation)
private static File getTuringKeyStoreFile() throws IOException {
ClassPathResource resource = new ClassPathResource("test.jks");
// Tomcat won't allow reading File from classpath so read as InputStream into temp File
File jks = File.createTempFile("ssl_keystore", ".jks");
InputStream inputStream = resource.getInputStream();
try {
FileUtils.copyInputStreamToFile(inputStream, jks);
} finally {
IOUtils.closeQuietly(inputStream);
}
return jks;
}
Reference: https://github.com/robinhowlett/everything-ssl
I'm working on a tow projects , EJB project (where i have all my EJB Remote) and the other project is a simple java application with main method. but when i try to lookup an EJB statless and remote via JNDI , it doesn't work.
Really i used many way but no good results.
this is the code and the consol error .
1) My Ejb project when i clean and install it , it gives me a jar file.
2) I use Jboss EAP6.
3) i have a jndi.properties insid of src/main/ressouces where i have this :
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url = localhost:1099
PersonalFactory.java (EJB of the EJB project)
import javax.ejb.Remote;
import javax.ejb.Stateless;
import com.lazrak.common.logging.CommonLogger;
import com.lazrak.remotes.IPersonFactoryRemote;
#Remote(IPersonFactoryRemote.class)
#Stateless
public class PersonFactory implements IPersonFactoryRemote
#Override
public void findMe() {
System.out.println("I'am inside of the method findMe");
}
MyMainClass.java (where i have the main method and it is in the second java project)
All import ...
public class MyMainClass {
public static void main(String[] args) throws Exception {
System.out.println("Main start ");
invokeStatelessBean();
}
private static void invokeStatelessBean(){
Hashtable props = new Hashtable();
props.put(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
props.put(Context.URL_PKG_PREFIXES,"org.jboss.ejb.client.naming");
props.put(Context.PROVIDER_URL,"jnp://localhost:1099");
InitialContext context = null;
try {
context = new InitialContext(props);
} catch (NamingException e) {
System.out.println("Faild to add properties to InitialContext"+e.getMessage());
}
try {
final IPersonFactoryRemote statelessRemoteCalculator = (IPersonFactoryRemote) context
.lookup("ejb:"+moduleName+"/"+PersonFactory.class.getSimpleName();+"/"+IPersonFactoryRemote.class.getName());
} catch (NamingException e) {
System.out.println("EJB Remot doesn't been fined\n"+e.getMessage());
}
}
}
when i run my main application , it gives me that :
Main start
enter 2014-09-26 15:57:26,098 DEBUG org.jboss.logging - InitialContextFactory.java:64 - Logging Provider: org.jboss.logging.Log4jLoggerProvider
Exception in thread "main" java.lang.NoClassDefFoundError: org/jboss/remoting3/spi/ConnectionProviderFactory
at org.jboss.naming.remote.client.InitialContextFactory.<clinit>(InitialContextFactory.java:99)
at org.jboss.naming.remote.client.InitialContextFactory.<clinit>(InitialContextFactory.java:99)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:270)
at com.sun.naming.internal.VersionHelper12.loadClass(VersionHelper12.java:72)
at com.sun.naming.internal.VersionHelper12.loadClass(VersionHelper12.java:61)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:671)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:307)
at javax.naming.InitialContext.init(InitialContext.java:242)
at javax.naming.InitialContext.<init>(InitialContext.java:216)
at RemoteEJBClient.invokeStatelessBean(RemoteEJBClient.java:42)
at RemoteEJBClient.main(RemoteEJBClient.java:18)
Caused by: java.lang.ClassNotFoundException:
org.jboss.remoting3.spi.ConnectionProviderFactory
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
... 11 more
props.put(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
props.put(Context.URL_PKG_PREFIXES,"org.jboss.ejb.client.naming");
props.put(Context.PROVIDER_URL,"jnp://localhost:1099");
Those properties are used for connecting to an older jboss version.. For eap 6, you have to use remoting instead of jnp.
HereĀ“s a tutorial that will show you how to connect
http://www.mastertheboss.com/jboss-server/jboss-as-7/jboss-as-7-remote-ejb-client-tutorial