I have a NiFi processor, that uses the redislabs/luascript lib in order to load a lua script and execute it on a redis instance.
The thing is that I don't know where exactly to put the lua script in order to load it using the luascript lib. I've put it into the nifi_proc/src/main/resources/lua/name.lua, but I get an IOException.
I have a nifi controller service for connecting to redis and a processor that uses that service.
My project structure:
.
├── nifi-bundle-nar
│ └── target
├── nifi-redis_cservice
│ ├── src
│ └── target
├── nifi-redis_cservice-api
│ ├── src
│ └── target
├── nifi-redis_cservice-api-nar
│ └── target
├── nifi-redis_cservice-nar
│ └── target
├── redis-processors
│ ├── src
│ └── target
└── target
└── maven-shared-archive-resources
Any ideas?
Can you share more information about how the processor is interacting with the library? Are you passing in an InputStream, calling out to a executable, etc.?
Ensure your resource is in the JAR module of your processor's project, not the processor's NAR module or the parent (that includes both). You should be able to use getResourceAsStream("lua/name.lua") from a Class object that is in the processor's JAR file (such as the processor class itself). I'm not sure what you'd need to do with it after that, is it possible to share the source code or more details around it?
EDIT (reply to comments below): fromResource() uses LuaScript's classloader to get the resource, I wonder if it doesn't have access to the nifi-proc or controller service resources. It seems like, unless the user needs to specify the location of the script, that the controller service should be loading in the Lua script. So an alternative could be to use the controller service class to getResourceAsStream, read the whole thing into a String, and use fromSource instead of fromResource.
Related
I have created a simple Java9 service example with one service interface and two service implementations and one driver which uses the ServiceLoader. I was able to successfully execute the example with module-path but when I tried to execute the same with java -cp (classpath) I did not get any output, not even any error.
Directory structure
out
├── driver
│ ├── com
│ │ └── company
│ │ └── driver
│ │ └── driver.class
│ └── module-info.class
├── firstServiceImpl
│ ├── com
│ │ └── company
│ │ └── first
│ │ └── serviceImpl
│ │ └── FunImpl1.class
│ └── module-info.class
├── secondServiceImpl
│ ├── com
│ │ └── company
│ │ └── second
│ │ └── serviceImpl
│ │ └── FunImpl2.class
│ └── module-info.class
└── serviceInterface
├── com
│ └── company
│ └── service
│ └── Fun.class
└── module-info.class
command to compile
javac -d out --module-source-path src src/driver/driver.java src/firstServiceImpl/FunImpl1.java src/secondServiceImpl/FunImpl2.java src/serviceInterface/Fun.java
The above command compiles the code with a module-source-path.
command to run
java -cp out/driver:out/serviceInterface/:out/firstServiceImpl/ com.sunil.driver.driver
The above command runs the code with a classpath.
After compiling with module-source-path and run the code with classpath. I do not get any error or output.
Please help me understand why there is no output when run using classpath.
The way service-providers are located depends on if the service-providers are on the classpath or the modulepath. This is described in the documentation of ServiceLoader:
Deploying service providers as modules
A service provider that is developed in a module must be specified in a provides directive in the module declaration. The provides directive specifies both the service and the service provider; this helps to locate the provider when another module, with a uses directive for the service, obtains a service loader for the service. It is strongly recommended that the module does not export the package containing the service provider. There is no support for a module specifying, in a provides directive, a service provider in another module.
[...]
Deploying service providers on the class path
A service provider that is packaged as a JAR file for the class path is identified by placing a provider-configuration file in the resource directory META-INF/services. The name of the provider-configuration file is the fully qualified binary name of the service. The provider-configuration file contains a list of fully qualified binary names of service providers, one per line.
[...]
Basically, if you want to be able to load a service-provider no matter if it's placed on the classpath or modulepath you'll need to specify both a provides directive in the module-info.java file and add the appropriate provider-configuration file under META-INF/services. You also have to make sure you use the correct method for loading the service-providers:
ServiceLoader#load(Class,ClassLoader)
Locates providers in named modules (i.e. modulepath) and unnamed modules (i.e. classpath).
ServiceLoader#load(ModuleLayer,Class)
Only locates providers in named modules (i.e. modulepath).
I am trying to get a better understanding of how the new java module system works, especially when it comes to bundling together java packages to their respective modules.
I could not find a way of asking this question in an easy to understand way without tying it to a specific example.
If I have the following project structure:
.
└── src
└── main
└── java
├── module-info.java
└── org
└── lb
└── app
└── App.java
where module-info.java is:
module lb.module {}
and App.java is:
package org.lb.app;
public class App {
public static void main (String[] args) {
System.out.println("Hello, world!");
}
}
and then I run the command from the . directory:
javac -d build/classes $(find src/main/ -name "*.java")
which gives me the following result:
.
├── build
│ └── classes
│ ├── module-info.class
│ └── org
│ └── lb
│ └── app
│ └── App.class
└── src
└── ...
and finally I run the command:
java --module-path build/classes/ --module lb.module/org.lb.app.App
My questions are:
How does the javac tool knows that module-info.class should be in the root directory folder build/classes if there is no "package information" (e.g. like there are in normal java files), and not, for instance in a folder that mimics the original location (e.g. build/classes/src/main/java/module-info.class
I did not expect it to work, but it does. How does the JVM knows that the org.lb.app package belongs to the lb.module module? I purposefully "misnamed" the module, making it not have same name as the directory that contains it, and also did not export the package. It seems obvious for a human reader, but I want to understand what the java program assumes in order to bundle these two together.
Thank you.
I just spent a little while learning the hard way that Gradle can't make a working jar file if the directory (and thus jar file) is labeled something LIKE_THIS.
Does anyone know why this is? I'm just picking up Java and would like to know why. I've heard it's bad practice to label packages with capital letters as well.
EDIT:
If the directory is all caps, I'd get Error: Could not find or load main class src.main.java.HelloWorld but it would work perfectly fine if it's lableded something like_this.
EDIT:
My directory structure after fixing the label was just from a tutorial, but here it is:
alexanders-mbp:VALID_JAVA alexanderkleinhans$ tree
.
├── build
│ ├── classes
│ │ └── main
│ │ └── net
│ │ └── petrikainulainen
│ │ └── gradle
│ │ └── HelloWorld.class
│ ├── dependency-cache
│ ├── libs
│ │ └── VALID_JAVA.jar
│ └── tmp
│ ├── compileJava
│ └── jar
│ └── MANIFEST.MF
├── build.gradle
└── src
└── main
└── java
└── net
└── petrikainulainen
└── gradle
└── HelloWorld.java
Changing the directory to something_else and re-building makes everything work. BTW, no build errors.
EDIT:
I was following this and couldn't get it to work so I finally cloned the git-repo where I discovered my issue.
To run, I would do
gradle assemble
gradle build
java -jar build/library/VALID_JAVA.jar
(VALID_JAVA being the directory name and thus jar file name.)
It looks like you try to launch src.main.java.HelloWorld, but if you look at the sources from the GIT repository the fully qualified class name is net.petrikainulainen.gradle.HelloWorld (which also matches your directory structure).
To launch the application, use
java -classpath build/libs/VALID_JAVA.jar net.petrikainulainen.gradle.HelloWorld
Note also, according to the decription at the GIT repository, the gradle build creates a runnable jar file which you can launch like
java -jar pathToJarFile
I'm a little bit new with Java, so I apologize in advance. In a Google API Quickstart, a .credentials file is loaded from the method getResourceAsStream and the path as "/client_secret.json". From here, I learned that this getResourceAsStream get's the file from the CLASS path, which confuses me because my src directory structure looks like the following.
.
└── main
├── java
│ └── GmailQuickstart.java
└── resources
└── client_secret.json
When I open a new project (using a servlet) and try to load this, I'm finding this InputStream is null. The src directory of the following project looks like so:
.
└── main
├── java
│ ├── GmailQuickstart.java
│ ├── com
│ │ └── something
│ │ └── HelloWorldServlet.java
│ └── somepackage
│ └── Thing.java
├── resources
│ └── client_sercret.json
└── webapp
└── WEB-INF
└── web.xml
I've tried changing it to what I though would be the same CLASSPATH, but I guess that's not correct. From the previous advice, I've also tried "/main/java/resources/client_secret.json". Obviously I'm not doing something right here.
Could someone help point me in the right direction?
Try to add resources folder to your classpath.
If you are using eclipse, right click your project, configure build path, add your resources folder in Source tab.
I have several class files like such hierarchy directories:
classes
└── com
├── www
│ ├── ant
│ │ └── TAPJUnitResultFormatter.class
│ ├── taglib
│ │ └── IncludeTag.class
│ ├── tomcat
│ ├── util
How could I include them in classpath? I tried to include them one by one, but didn't work.
Thanks.
You might find this helpful
Quoted:
When classes are stored in a directory (folder), like /java/MyClasses/utility/myapp, then the class path
entry points to the directory that contains the first element of the
package name. (in this case, /java/MyClasses, since the package name
is utility.myapp.)
But when classes are stored in an archive file (a .zip or .jar file)
the class path entry is the path to and including the .zip or .jar
file. For example, to use a class library that is in a .jar file, the
command would look something like this:
% java -classpath /java/MyClasses/myclasses.jar utility.myapp.Cool
So basically, point it to the root directory that all your classes exist under. Your "MyClasses" folder is probably named "bin".