Pentaho Data Integration User Defined Java Class - java

I create simple java class and export it to jar:
package test;
public class Test {
public Test() {
// TODO Auto-generated constructor stub
}
}
Jar file add to lib folder in Pentaho (there are many jar files)
Next step I want to use my class in Pentaho Data Integration so I created User Defined Java Class:
public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException
{
test.Test t = new test.Test();
return true;
}
When I click Test class I get the following information:
Line 3, Column 12: Class "test.Test" not found
So I have a question: Where is the mistake and why is the class not found?

Try checking the launcher.property file inside the /design-tools/data-integration/launcher folder. Make sure that the classpath and the libraries are having the path of the jar defined. Since you have placed your JAR file inside the lib folder, look for that.
Restart the Spoon after editing and it would work ideally.
I have placed the code inside the libext folder, so i have added :../libext to the classpath and libraries. And below is the code snip:
In case it still throws an error, try checking the Java code again. I assume something might have gone wrong there.
Also documented the above in here.
Hope it helps :)

Related

get the execution location from within a library jar

I have a class named Utils with a static method that should determine the execution location.
public class Utils {
public static Path getExecutionLocation() throws URISyntaxException {
return Paths.get(Utils.class.getProtectionDomain().getCodeSource().getLocation().toURI());
}
}
Within eclipse this gives me: C:\Users\USERNAME\workspace\PROJECT\bin\main\
Run as a jar this gives me: C:\PATH\TO\JAR\thatJar.jar
Both is correct and expected.
Now I have that Utils class inside a library called someLib.jar.
When I use that library in another project it works if I build a jar of that project with someLib.jar inside.
But in eclipse it returns the path to someLib.jar.
I want it to return the path to the execution directory of the project:
C:\Users\USERNAME\workspace\A_PROJECT_USING_SOMELIB\bin\main\
I tried
return new File(ClassLoader.getSystemClassLoader().getResource(".").getPath()).toPath();
But that failed inside a jar because getResource(".") results in null.
I could give getExecutionLocation a class from inside the project as a parameter and excute getProtectionDomain() on that. But I want to ask here if someone knows a better solution.
Try this:
public class Utils {
public static Path getExecutionLocation(Class c) throws URISyntaxException {
return Paths.get(c.getProtectionDomain().getCodeSource().getLocation().toURI());
}
}
So you pass the class as an argument to the function. For example:
public class Main
{
public static void main(String[] args)
{
Utils.getExecutionLocation(Main.class);
}
}
Note that there may be more straightforward solutions,
But this is the first one that came into my mind, and I thought, why not :)
I've found a solution based on ClassLoader.getSystemClassLoader() approach that gives me the class loader responsible for the main entry point of the project that is using someLib.jar.
Within an IDE I can use getResource(".") to get URL of the root path of all resources (and sources).
From jar file this does not work. So I use getResource("META-INF") to get URL of the META-INF folder (that has the manifest inside) and should always exist in jar files.
Maybe still not optimal. But so far I can work with it.
public static Path getExecutionLocation() throws URISyntaxException, IOException {
// System ClassLoader is on the highest level and responsible for the main entry point
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
// get the resources root path (works within IDEs)
URL executionLocation = systemClassLoader.getResource(".");
// fallback for jars
if(executionLocation == null) {
// look for META-INF folder
URL metaInfLocation = systemClassLoader.getResource("META-INF");
// URL looks like "jar:file:/C:/path/to/jar/jarfile.jar!/META-INF"
// openConnection on URL - does not really establish connection but checks if URL would be valid
JarURLConnection connection = (JarURLConnection) metaInfLocation.openConnection();
// extracts URL to jar file
executionLocation = connection.getJarFileURL();
}
// impossible to determine
if(executionLocation == null) throw new RuntimeException("Impossible to determine exeution location");
return Paths.get(executionLocation.toURI());
}

how to checks If there exist duplicate class with specified class name in Java Runtime Enviroment?

My application can not run normal when it has duplicate class, with problem like 'no such method'.
The project have two class with the same class name , one is from project code, another is from a jar file. how to check this problem when application start up?
src/main/java/com/kxw/Example.java
gradle.build
compile("com.kxw:xxx:1.0")//contains com.kxw.Example
I expect there has java api or utils to check when application start up .
public void startUp(){
if(existDuplicateClass("com.kxw.Example")){
shutdown();
}
}
protected boolean existDuplicateClass(String className){
//TODO
}
i don't konw how to implement method existDuplicateClass.
refenence:
Gradle: how to check duplicate class in project?
finally i check duplicate class when startup by this way :
String classPath = Optional.ofNullable(xx.class.getProtectionDomain())
.map(ProtectionDomain::getCodeSource)
.map(CodeSource::getLocation)
.map(URL::getPath).orElse("");
//class is not from common-core.jar
if (!classPath.contains("common-core")) {
log.error("{} thrift class may be duplicate ...", xx.class.getName());
shutdownContext.shutdown();
}

Jmeter Throws NoSuchMethodException, but the method does exist

Currently trying to use Junit to create some concurrency tests to run in Jmeter
My current project Structure looks like this
From RasterTest.java, I'm trying to call a method in CommonMethods.java and a method in SetUp.java.
When I run this as a JUnit Test in eclipse, the methods in CommonMethods and SetUp are called and everything works fine. When I export this to a JAR and run the same in Jmeter, I get an error given below (getProperty is a method inside SetUp )
Trace -- java.lang.NoSuchMethodError: utils.SetUp.getProperty
I couldn't find any resources, hence i thought this maybe due to the methods being static, but i tried accessing the method by creating an object too. That Didn't help, got the same error.
Attaching the class CommonMethods for reference :
public class CommonMethods {
public String getProperty (String key) {
// Some code
}
public void setUrl() {
System.out.println("Hello world");
}
}
Calling it as :
CommonMethods cm = new CommonMethods();
System.out.println(cm.getProperty("URL"));
cm.setUrl();
I don't understand why Jmeter throws this error and how do i get around it? Thanks!
Hope you are using jpgc-perfmon-2.1. If not zip that into jmeter and then remove plugin cmn jar file from lib and update jmeter-plugins-cmn-jmeter.jar file with the latest version.
Seems like its kind of configuration issue.

Where is getResourceAsStream("file") searching when running from a test?

I'm struggling to create a test to verify a ServletListener that loads a properties file. I've tested when running the application that it works fine and it finds the file in the classpath. But I don't know how to create a test for it. My idea is to create a temp file with a test property and then verify the property is put into the System properties. But I always fail to create the file in the right place.
I've tried creating the file in /target/test-classes or directly in the root of the application but it never finds it. Any idea?
This is the code I'm trying to test:
public class PropertyReadingListener implements ServletContextListener {
public static final String PROFILES_PROPERTIES = "profiles.properties";
#Override
public void contextDestroyed(ServletContextEvent event) {
}
#Override
public void contextInitialized(ServletContextEvent event) {
Properties propsFromFile = new Properties();
try {
propsFromFile.load(getClass().getResourceAsStream(PROFILES_PROPERTIES));
} catch (final Exception e) {
log.warn("Unable to find {}, using default profile", PROFILES_PROPERTIES);
}
propsFromFile.stringPropertyNames().stream()
.filter(prop -> System.getProperty(prop) == null)
.forEach(prop -> System.setProperty(prop, propsFromFile.getProperty(prop)));
}
}
Thanks.
Assuming that you are using maven, put your properties file here:
src/test/resources/foo.properties
The maven resources plugin will place the (possibly filtered) copy of the file in
target/test-classes/foo.properties
The test-classes directory is on the classpath, so you reference the file like this (note the slash in front of the file name):
... getResourceAsStream("/foo.properties");
Where is getResourceAsStream("file") searching when running from a test?
Assuming that you are talking about JUnit ....
Unless you have done something funky, your unit tests will be loaded by the default classloader, and that means that the normal JVM classpath with be searched.
(Junit 4 allows you to use a different classloader: see https://stackoverflow.com/a/9192126/139985)
But I always fail to create the file in the right place.
It seems that your real problem is understanding how the Java classpath and classpath searching works. If you understand that (and you know what JUnit runner's actual classpath is) then it should be obvious where to put the properties file so that the classloader can find it.
See Different ways of loading a file as an InputStream
Basically when you do a getClass().getResourceAsStream it looks in the package of that class for the file.. so if your PropertyReadingListener is in com.company.listeners.PropertyReadingListener then it will look in com/company/listeners for the property file.
For testability, I would pass in an InputStream into the listener that way the test can create the input stream in a convienent way and the actual user of the class in code can pass in the InputStream returned from getResourceAsStream

Need help setting up intellij java project with multiple .java files from scratch

Edited to restart question from scratch due to complaints. I am a newbie to this format and to intellij so please excuse...
I am building a project in intellij for class. This project imports jnetcap and uses it to process a captured pcap file. My issue is I have two class files I am trying to integrate. NetTraffic which is the user interface class, and ProcessPacket that actually reads in the packet and does the work.
I have tried to make a project and import ProcessPacket into NetPacket but have been unsuccessful so far. I am sure I am missing something simple in this process but I just can not find anything showing the proper way to do this.
I have gotten it working by making a package under the src directory and adding both files to that package. This doesn't require an import from the NetPacket class and seems to work but my worry is that I need to be able to run this from a linux command line. I have been working all semester so far with everything in one source file so it hasn't been an issue until now. I don't remember using packages in the past under eclipse to do this.
Can someone offer a step by step process on how to properly add these source files to my project so that I am able to import ProcessPacket into NetTraffic or will leaving like this in a package work fine?
The files in question reside in package named nettraffic in src directory.
NetTraffic.java
package nettraffic;
public class NetTraffic {
public static ProcessPacket pp;
public static void main (String args[]) {
pp = new ProcessPacket();
pp.PrintOut();
}
}
ProcessPacket.java
package nettraffic;
import org.jnetpcap.*;
public class ProcessPacket {
public ProcessPacket() {
}
public void PrintOut() {
System.out.println("Test");
}
}
Note there is no real functionality in these at this time. Just trying to get the class import syntax correct before continuing. Again while this seems to work as a package I want to have it done without using a package and importing ProcessPacket.java into NetTraffic.java.
public class NetTraffic {
ProcessPacket pp = new ProcessPacket();
pp.PrintOut();
}
You're calling the PrintOut() method outside of any constructor or method or similar block (static or non-static initializer blocks...), and this isn't legal. Put it in a constructor or method.
public class NetTraffic {
public NetTraffic() {
ProcessPacket pp = new ProcessPacket();
pp.PrintOut();
}
}

Categories