I'm working on PAX integration tests for our project and I'm facing few issues with regards to class loading.
I have deployed few bundles in PAX (used karaf container). Once the karaf is up, I could see my bundles and services are up and active. However, in my test cases, I've referred to a Class (not a service nor a component) which will used to during my test execution. The class is resided in the bundle and bundle is up and running successfully, but I'm getting ClassnotFoundError while accessing the class in test case executionas below,
**java.lang.ClassNotFoundException: com.myproject.sample.bundle.DatabaseConfig
at** org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:501)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:421)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:412)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at com.integrationtest.testcases.internal.development.LaunchContainerTest.populateDBProfiles(LaunchContainerTest.java:189)
at com.integrationtest.testcases.internal.development.LaunchContainerTest.testLaunchOSGiContainerWithDefualtSettingsAndSleep(LaunchContainerTest.java:152)
Failed tests:
LaunchContainerTest.testLaunchOSGiContainerWithDefualtSettingsAndSleep:152->populateDBProfiles:189
▒ ClassNotFound
Is it something to do with the container?
As your test itself will also run within the OSGi context you need to adapt your test. The dynamically generated test bundle needs to know that it needs to import the class in question.
For this you can add a specialized probe configuration method. Like the following below:
#ProbeBuilder
public TestProbeBuilder probeConfiguration(TestProbeBuilder probe) {
//make sure the needed imports are there.
probe.setHeader(Constants.IMPORT_PACKAGE, "*,com.myproject.sample.bundle.*");
return probe;
}
Related
Created a jar file for a spring boot multimodule application and ran the jar file using java -jar command. While starting the application, it gives ResourceFinderException. When I analyzed it, the issue is happening because in my ResourceConfig file, i have used the package for my api end points. If I use register(service.class), the application starts fine. Any suggestion how can I provide the package instead of using register? The reason I want to use package is because I have lots of services inside multiple packages and the code looks very ugly if i use register for all the services. The ResourceConfig file looks like below.
public class AppResourceConfig extends ResourceConfig {
public AppResourceConfig {}{
super();
property("jersery.config.beanValidation.enableOutputValidationErrorEntity.server");
**packages("com.api");**
register(GsonProvider.class);
register(RequestContextFilter.class);
register(NotFoundExceptionMapper.class);
register(DefaultExceptionMapper.class);
}
}
Here the issue is with highlighted line: packages("com.api")
If I comment out this code application will be up. Otherwise it is giving org.glassfish.jersey.server.internal.scanning.ResourceFinderException: java.io.FileNotFoundException: api-01.03.00.04-snapshot.jar (No such file or direcotry)
Note: api-01.03.00.04-snapshot.jar is the jar file for one of the module in a project
Im getting the following error in my quarkus app, but only in integration tests, when the tests are running as part of the maven build and not when running the tests within my IDE (or when running in dev mode).
java.util.ServiceConfigurationError:
org.eclipse.microprofile.context.spi.ThreadContextProvider:
io.quarkus.arc.runtime.context.ArcContextProvider not a subtype
at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:589)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1236)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(ServiceLoader.java:1264)
at java.base/java.util.ServiceLoader$2.hasNext(ServiceLoader.java:1299)
at java.base/java.util.ServiceLoader$3.hasNext(ServiceLoader.java:1383)
at java.base/java.lang.Iterable.forEach(Iterable.java:74)
at io.smallrye.context.SmallRyeContextManager$Builder.discoverThreadContextProviders(SmallRyeContextManager.java:293)
at io.smallrye.context.SmallRyeContextManager$Builder.build(SmallRyeContextManager.java:333)
at io.smallrye.context.SmallRyeContextManagerProvider.getContextManager(SmallRyeContextManagerProvider.java:48)
at io.smallrye.context.SmallRyeContextManagerProvider.getContextManager(SmallRyeContextManagerProvider.java:37)
at io.smallrye.context.SmallRyeContextManagerProvider.getManager(SmallRyeContextManagerProvider.java:97)
at io.smallrye.context.SmallRyeThreadContext.getCurrentThreadContextOrDefaultContexts(SmallRyeThreadContext.java:160)
at io.smallrye.mutiny.context.DefaultContextPropagationInterceptor.getThreadContext(DefaultContextPropagationInterceptor.java:12)
at io.smallrye.mutiny.context.BaseContextPropagationInterceptor.decorate(BaseContextPropagationInterceptor.java:82)
at io.smallrye.mutiny.infrastructure.Infrastructure.decorate(Infrastructure.java:226)
at io.smallrye.mutiny.groups.UniOnItem.transform(UniOnItem.java:115)
at io.smallrye.mutiny.Uni.map(Uni.java:384)
at ...
This looks like some classloading issue but having a debugger in the build shows that the loaded ThreadContextProvider is assignable from the loaded ArcContextProvider, Is there anything else I should be looking for here? A bit stumped.
How can I load test properties from a file like 'application-test.properties'?
The file is stored in the src/test/resources folder. I put the file also in all possible folders as well. When running the test as part of the Maven test run, all works fine.
When running the new (single) test from the (IntelliJ) IDE, each time I get same the error message:
Caused by: java.io.FileNotFoundException: class path resource
[application-test.properties] cannot be opened because it does not
exist
This is the test class:
#RunWith(SpringRunner.class)
#EnableAutoConfiguration
#ComponentScan(basePackages = {"nl.deholtmans.tjm1706.todolist"})
#PropertySource( "application-test.properties")
public class TodoListServiceTest {
#Autowired
TodoListService todoListService;
#Test
public void testBasic() { ... }
It looks that I have to run the test first time from Maven. Why is that?
Spring Boot will automatically load the correct properties file if the profile is activated. In a test you can use the #ActiveProfiles annotation for that.
Next you would need to make sure that you actually use the proper Spring Boot infrastructure to run your test, using #SpringBootTest. That being said your test header should look something like the following
#RunWith(SpringRunner.class)
#SpringBootTest
#ActiveProfiles("test")
public class TodoListServiceTest { ... }
And ofcourse make sure that your IDE builds the application before running the tests.
I'm using clickhouse-jdbc in my java application. And I'm adding it to pom.xml like this:
<dependency>
<groupId>ru.yandex.clickhouse</groupId>
<artifactId>clickhouse-jdbc</artifactId>
<version>0.1.34</version>
</dependency>
And when I run my java application java -jar myapp.jar. It's throwing:
java.lang.NoClassDefFoundError: Could not initialize class
ru.yandex.clickhouse.ClickHouseUtil
And in my packaged jar file, there is also ClickHouseUtil.class. And I'm using Intellij Idea for packaging jar. How can I fix this issue?
The error 'Could not initialize class ....' means that the JVM has already tried and failed to perform static initialization of the class mentioned.
Static initialization of a class involves assigning values to any static fields and running any static { ... } blocks. The class in question is ru.yandex.clickhouse.ClickHouseUtil, and static initialization of this class consists only of setting up the static final field CLICKHOUSE_ESCAPER. This appears to rely on a couple of Guava escaper classes (com.google.common.escape.Escaper and com.google.common.escape.Escapers).
So I suspect that these Guava classes aren't in your packaged JAR file.
It's also worth pointing out that the exception message 'Could not initialize class ....' means that static initialization has already failed. In other words, when this exception is thrown, it is at least the second time the JVM has failed to load the class. It's possible that your app may have reported a more informative error message when the JVM failed to load this class for the first time.
I have an OSGI bundle (awesome.test) that calls code from a jar file (testlibrary.jar). I have included the bundle as a Liberty feature (awesome.test.feature) and I have it installed on a WebSphere Application Server Liberty Profile V8.5.5. I also have an OSGI bundle (awesometest) that is a part of an OSGI application (awesometest.app) and it has an Activator class.
Here is a picture of my workspace setup
What I want to do is call methods in testlibrary.jar through methods in awesome.test, which includes testlibrary.jar in its build path. My awesome.test.feature is available to any applicaions running on my Liberty server. I want my applications to be able to use that feature to gain access to the functionality in testlibrary.jar through what I provide in awesome.test. I don't want OSGI applications to directly import packages from testlibrary.jar.
The following error appears in the binary logs when I run the application on the server:
CWWKZ0402E: A bundle exception was generated when trying to install the application awesometest.app into an OSGi framework. The error text from the OSGi framework is: Exception in awesometest.Activator.start() of bundle awesometest.
Debugging the problem finds that this exception is thrown:
java.lang.ClassNotFoundException: testlibrary.test.TestAPI
Source from TestLibraryRunner.java in awesome.test:
package awesome.test;
import testlibrary.test.TestAPI;
public class TestLibraryRunner {
public static void runNonLibTest() {
System.out.println("No Library code is being called");
}
public static void runLibTest() {
TestAPI ta = new TestAPI("This is a message.");
ta.display();
}
}
Note that runNonLibTest() will work when called from the OSGI application. Calling the TestAPI code in runLibTest from the OSGI application will cause the error above.
Source from Activator.java in awesometest:
public class Activator implements BundleActivator {
public void start(BundleContext context) throws Exception {
System.out.println("Starting...");
TestLibraryRunner.runNonLibTest();
TestLibraryRunner.runLibTest();
System.out.println("Finishing...");
}
public void stop(BundleContext context) throws Exception {
System.out.println("Stopping...");
}
}
Source from MANIFEST.MF in awesometest:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: awesometest
Bundle-SymbolicName: awesometest
Bundle-Version: 1.0.0
Bundle-Activator: awesometest.Activator
Import-Package: awesome.test,
org.osgi.framework
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Export-Package: awesometest
In summary, my OSGI application cannot touch code from the jar in the build path of the bundle included in my Liberty feature. Is there something fundamental I'm missing here? Is what I'm trying to do even possible?
Thanks
Having had the same runtime exceptions in my educational project, the simplest solution I have found is to add the used JARs under Runtime - Classpath of the imported bundle (in your case awesome.test).
I hope this late answer helps someone else.
You use the package testlibrary.test but you do not import it. You should add that package to the Import-Package statement of the bundle.
It looks like the problem is in the packaging of awesome.test. The awesometest bundle (application bundle) can find your feature code fine, but then problems occur in the feature bundle. Have you confirmed that testlibrary.jar is packaged within awesome.test (feature bundle) and that the manifest of awesome.test includes the embedded jar?
You'll also need to list your exported feature packages in your feature manifest using the IBM-API-Package header, but I assume you've already done that or your application bundle activator wouldn't be able to see the feature bundle's TestLibraryRunner.
The problem with my project was that I was not including the testlibrary.jar correctly. While it was in the build path of awesome.test, it wasn't being included with the OSGI feature bundle.
There are two possible solutions:
1.) In Eclipse, go to File > Import and choose OSGi > Java Archive into an OSGi Bundle and create a new bundle. This will put the jar in its own bundle and then awesome.test can import the packages it needs from that new bundle.
2.) In Eclipse, go to File > Import and choose OSGi > Java Archive into an OSGi Bundle and include it in an existing bundle. This has the same effect as making the jar its own bundle, but it's less modular. The advantage of this approach is that you can not export the packages from the jar and just export your own interfaces.
There is also the BND Tool. It can help automate a lot of this process. I haven't used it myself.