UnsatisfiedLinkError when calling native method packaged in jar file - java-native-interface

I am getting java.lang.UnsatisfiedLinkError: com.fundamenture.solvocommons.utility.parsers.tklib.test()V when calling native C method test() when calling the class packaged in a jar file. Same code runs fine when calling the java file directly
Note that loading the library with code
System.loadLibrary("tklib");
runs fine, it is only at the point of calling the method test() that the exception occurs. This means that the java code can load the library properly, only calling the method is failing
The code runs fine when called via command line in a main method as follows
java -cp . -Djava.library.path=. tklib
Below is my java code with the main method running fine from command line
class tklib {
static {
System.loadLibrary("tklib"); // loading libtklib.so
}
private native void test();
private native boolean initialize(String configuration);
private native void shutdown();
private native String unpack(String keyname, String secureddata);
public static void main(String[] args) {
new tklib().test();
new tklib().shutdown();
}
}
When I package the project as a jar file and calling the method I am getting the UnsatisfiedLinkError at the point when new tklib().test() is called.

Related

ResourceBundle.getBundle returning actual object in spite of mockStatic and when() directing otherwise

I'm creating tests over existing classes. A number of them have a resource bundle defined as a private final field that's initialized when the object is created via new. I declare a mocked ResourceBundle, use PowerMock's mockStatic method to enable static mocking, and mock the getBundle method to return my mocked ResourceBundle. However, when the constructor runs the code to initialize the field, it simply creates the new resource bundle rather than using the mocked one. I feel like there's one little detail I've missed, but I don't know what it might be.
The reason all this is a problem is this: when I run the test locally, it creates the ResourceBundle object without issue. But when the test is run via our build software (UCBuild), it throws a "can't find resource" exception and the test, and therefore the build, fails.
When I run a test in debug and set a method breakpoint on the constructor, I can see that the "strings" object is created using an actual resource bundle, not the mocked one. I can't for the life of me figure out why.
I've tried declaring the field without initializing it, then using class.getDeclaredField() and Field.setAccesible() to set the resource bundle to point at my mocked one, but of course this just gets overwritten if I run code that re-initializes the field.
The WorkerTest class which tests Worker.java:
#RunWith(PowerMockRunner.class)
#PrepareForTest({FacesContext.class, SaveStatus.class, FacesMessage.class, ResourceBundle.class})
public class WorkerTest {
#Mock
private ResourceBundle mockRB;
#Before
public void setUp() throws Exception {
PowerMockito.mockStatic(ResourceBundle.class);
PowerMockito.when(ResourceBundle.getBundle(anyString())).thenReturn(mockRB);
PowerMockito.when(mockRB.getString(anyString())).thenReturn("tst");
sut = new Worker(); // Breakpoint here to verify mockRB exists
}
...some tests
}
Worker.java:
#Named
#ApplicationScoped
public class Worker implements Serializable {
private static final long serialVersionUID = 4075799125164038417L;
private final ResourceBundle strings = ResourceBundle
.getBundle("com.resources.strings");
public Worker() { //method breakpoint here
}
Thanks in advance
Found the problem. Adding Worker.class to the #PrepareForTest annotation line and everything worked fine.

Custom Execution Function in WSO2

I am trying to write a simple custom function extension for WS02 (4.2.0). My function basically takes in a String and returns the upper case. This is meant to be a first step POC for a more advanced custom function.
I implemented a class that extended the org.wso2.siddhi.core.executor.function.FunctionExecutor class, and created a ams.siddhiext file. I then packaged the class and the siddhiext in a JAR file using the maven-bundle plugin.
My function class looks like this
public class AnomalyDetector extends FunctionExecutor {
private final static Logger LOG = LoggerFactory.getLogger(AnomalyDetector
.class);
#Override
protected void init(ExpressionExecutor[] expressionExecutors, ExecutionPlanContext executionPlanContext) {
LOG.info("In AD:init()");
}
#Override
protected Object execute(Object[] objects) {
return null;
}
#Override
protected Object execute(Object o) {
LOG.info("In AD:process(" + o.toString() + ")");
String eventData = (String) o;
LOG.info("Event data : " + eventData);
if (eventData != null) {
return eventData.toUpperCase();
} else {
return "Null event data";
}
}
#Override
public void start() {
LOG.info("In AD:start()");
}
#Override
public void stop() {
}
#Override
public Map<String, Object> currentState() {
return null;
}
#Override
public void restoreState(Map<String, Object> map) {
}
#Override
public Attribute.Type getReturnType() {
return Attribute.Type.STRING;
}
}
I then put the jar in the /repository/components/lib/ since /repository/components/dropins/ did not pick it up.
I have 2 issues that are blocking me currently.
I wanted to write a simple execution plan that takes a value from an input stream (String), invoke my custom function and write the output to an export stream.
#Plan:name('AMSExecutionPlan')
#Import('AMSStream:1.0.0')
define stream amsStream (metrics_json string);
#Export('AnomalyStream:1.0.0')
define stream anomalyStream (anomaly string);
from amsStream
select ams:findAnomaly(metrics_json) as anomaly
insert into anomalyStream
I get the following validation error.
What could be wrong with my execution plan?
Whenever I change my custom function class, rebuild the jar and replace it in the wso2 classpath, and then restart ws02, I dont see the changes reflected in ws02. The log lines that I print out in my custom function class reflect an older version of the code. What should I do to make changes to my Custom function class on a live ws02 instance?
Thanks in advance!
Can you bundle the jar as an OSGI bundle and try? There can be a issue when converting your jar to an OSGI bundle.
Validation error you have pointed suggest that your extension is not returning the return type properly. But I can see you have implemented getReturnType() correctly. So may be your source and actual running code might not be synced up due to issue 2. So let's address that first.
In WSO2 servers lib folder is used to add non-OSGi dependencies and dropins for OSGi dependencies. Fact that it works in lib and not in dropins suggest that your jar is not packed as a bundle. To achieve that please follow below pom file from String extension. There are two things to note.
[1] Usage of bundle packaging
[2] Usage of bundle plugin
Update your pom referencing this and then you will be able to add your bundle to dropins directly. Also this is the reason why your changes are not reflected. When you add your jar to lib server will internally convert it to an OSGi bundle and add to dropins. Now when you update the jar in lib again the one in dropins will not get updated. It will be the old bundle. Hence changes are not reflected. This issue will also go away when you update the pom and build the bundle correctly.
[1] https://github.com/wso2/siddhi/blob/v3.1.0/modules/siddhi-extensions/string/pom.xml#L29
[2] https://github.com/wso2/siddhi/blob/v3.1.0/modules/siddhi-extensions/string/pom.xml#L57
Hope this helps!!

Mock SomeClass.getClassLoader() when called in method (Mockito / PowerMockito)

I have inherited some code that isn't tested and which loads a resource using a method like :
SomeClass.class.getClassLoader().getResource("somefile");
I've written the following test but there are 0 interactions with the Mock class loader I've created. Can anyone comment on whether this type of test is possible.
public enum SomeClass {
INSTANCE;
public boolean someMethod() {
URL pathToLicense = SomeClass.class.getClassLoader().getResource("somefile");
return false;
}
}
#Test
public void testLicenseWorkflow(){
ClassLoader cl = PowerMockito.mock(ClassLoader.class);
File f = new File("someFile");
assertTrue(f.exists());
logger.info(f.getCanonicalPath() );
when(cl.getResource("somefile")).thenReturn(f.toURL());
verify(cl).getResource("somefile");
assertTrue(SomeClass.INSTANCE.someMethod());
}
Update - Adding a resources via Classloader
I've also tried the following but the someMethod this doens't seem to work either
new URLClassLoader(((URLClassLoader) SomeClass.INSTANCE.getClass().getClassLoader()).getURLs()) {
#Override
public void addURL(URL url) {
super.addURL(url);
logger.info("Calling add URL");
}
}.addURL(f.toURI().toURL());
You are not passing cl to anything. You prepare a mock for a classloader but then proceed to load the resource with another classloader, the one that loaded SomeClass. That is why you have 0 interactions in your mock.
And about your first question, it is possible if somehow you pass your mocked classloader to the method that actually loads the resource. For example, something like
public boolean someMethod(Classloader loader) {
URL pathToLicense = loader.getResource("somefile");
return false;
}
But I have to say that IMO, this test is not very useful, you should be mocking your own components, not java classes. If your goal mocking the classloader is to inject a different file when testing, a better approach is to change your code to receive a Stream and inject a stream connected to the file in production and in testing inject a stream connected to an element in memory.
In other words, resources make for bad testing when they need to be changed at test time

Apache Camel: How to print Exception Trace while Unit Testing using CamelTestSupport

Using Camel-core v2.14.1 and camel-testng v2.14.1
Attempting to Unit Test a basic route.
The RouteBuilder class is named as FileToJmsRB and the Route is configured this way
#Override
public void configure() {
from("file:C:\\camel_folder\\orders")
.when(fileToJmsConditions.camelFileNameEndingWithXml(this))
.to("file:C:\\camel_folder\\recieved")
}
fileToJmsConditions is a variable that I am failing to inject as Spring Bean.
My Test class extends CamelTestSupport and it overrides createRouteBuilder() as follows
#Override
protected RouteBuilder createRouteBuilder() throws Exception{
return new FileToJmsRB();
}
and I configure a method as test.
#Test
public void testTextFileMove() throws Exception{
template.sendBodyAndHeader("file:C:\\camel_folder\\orders"
, "Hello World"
, Exchange.FILE_NAME
, "hello.txt");
Thread.sleep(10000);
File target = new File("C:\\camel_folder\\recieved\\hello.txt");
assertTrue(target.exists(), "File Not Moved");
}
On running
maven install
on the project, I expect a Null Pointer Exception with a StackTrace in Console.
However, observation no hint of type of Exception Thrown and there is not stacktrace printed. It just says that the test failed but does not prints the type of exception or stacktrace.
Tests run: 2, Failures: 1, Errors: 0, Skipped: 1
However, if I wrap my configure method in FileToJmsRB class with
try... Catch...
Only then do I see the NullPointerException thrown and Stack Trace printed.
Is there no other, more elegant way of handling this more elegantly? Because this way I must do try...catch... in every Route Builder class?

how to resolve "java.lang.NoClassDefFoundError: org/apache/velocity/context/Context"

I'm a new learner of apache cxf. in the first program i implement, i encoutered the following exception( this is what my console display):
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/velocity/context/Context
The java code source i run is
package com.ttdev;
import org.apache.cxf.tools.wsdlto.WSDLToJava;
public class CodeGenerator {
/**
* #param args
*/
public static void main(String[] args) {
System.out.println("debug");
WSDLToJava.main(new String[] {
"-server",
"-d", "src/main/java",
"src/main/resources/Service.wsdl" });
System.out.println("Done!");
}
}
so how can i resolve this problem.
You need Apache Velocity on your classpath.
Check your Pom->DependencyHierarchy -> Filter "velocity"
In which package it is found , Probably it was not loaded properly.
In mycase it was C:\Users\MyUser.m2\repository\org\apache\velocity
Delete that and run "mvn clean package -DskipTests" from console, it will download all necessary packages.