Jackson Afterburner module is failing inside Apache Karaf 3.0.5 - jackson

I have a simple Hello World type Karaf Bundle running inside Apache ServiceMix 6.1.0 using Jackson's Afterburner Module. The activator code looks like below:-
public class HelloWorldActivator implements BundleActivator {
#Override
public void start(BundleContext bundleContext) throws Exception {
System.out.println("STARTING DEMO: hello, world\n");
System.out.println(getJsonDataAsString());
}
#Override
public void stop(BundleContext bundleContext) throws Exception {
System.out.println("STOPPING DEMO");
}
private String getJsonDataAsString() {
JsonDataBlob jsonDataBlob = new JsonDataBlob();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new AfterburnerModule());
try {
return objectMapper.writeValueAsString(jsonDataBlob);
} catch(Exception e) {
e.printStackTrace();
}
return "";
}
}
The pom.xml looks like below:-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.hello</groupId>
<artifactId>world</artifactId>
<version>0.0.1</version>
<packaging>bundle</packaging>
<name>Hello World</name>
<dependencies>
<!-- OSGi -->
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20160212</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-afterburner</artifactId>
<version>2.7.1</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<excludes>
<exclude>**/com/hello/main/*</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.4.0</version>
<inherited>true</inherited>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Version>${project.version}</Bundle-Version>
<Bundle-Activator>com.hello.world.HelloWorldActivator</Bundle-Activator>
<Import-Package>*;resolution:=optional</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
The java object which I am trying to convert to json is a simple object as shown below:-
package com.hello.world;
public class JsonDataBlob {
private String add1 = "JP Naagar";
private String add2 = "";
private int shippartagent = 1;
public String getAdd1() {
return add1;
}
public void setAdd1(String add1) {
this.add1 = add1;
}
public String getAdd2() {
return add2;
}
public void setAdd2(String add2) {
this.add2 = add2;
}
public int getShippartagent() {
return shippartagent;
}
public void setShippartagent(int shippartagent) {
this.shippartagent = shippartagent;
}
}
But whenever I am trying to install the bundle I am getting the below exception and the bundle gets stuck in the Resolved state:-
2016-05-07 15:36:48,986 | WARN | x-6.1-2.0/deploy | fileinstall | 7 - org.apache.felix.fileinstall - 3.5.0 | Error while starting bundle: file:/Users/debraj/Downloads/apache-servicemix-6.1-2.0/deploy/world-0.0.1.jar
org.osgi.framework.BundleException: Activator start error in bundle world [239].
at org.apache.felix.framework.Felix.activateBundle(Felix.java:2196)[org.apache.felix.framework-4.2.1.jar:]
at org.apache.felix.framework.Felix.startBundle(Felix.java:2064)[org.apache.felix.framework-4.2.1.jar:]
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:955)[org.apache.felix.framework-4.2.1.jar:]
at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundle(DirectoryWatcher.java:1245)[7:org.apache.felix.fileinstall:3.5.0]
at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundles(DirectoryWatcher.java:1217)[7:org.apache.felix.fileinstall:3.5.0]
at org.apache.felix.fileinstall.internal.DirectoryWatcher.doProcess(DirectoryWatcher.java:509)[7:org.apache.felix.fileinstall:3.5.0]
at org.apache.felix.fileinstall.internal.DirectoryWatcher.process(DirectoryWatcher.java:358)[7:org.apache.felix.fileinstall:3.5.0]
at org.apache.felix.fileinstall.internal.DirectoryWatcher.run(DirectoryWatcher.java:310)[7:org.apache.felix.fileinstall:3.5.0]
Caused by: java.lang.NoClassDefFoundError: com/fasterxml/jackson/module/afterburner/AfterburnerModule
at java.lang.Class.getDeclaredConstructors0(Native Method)[:1.8.0_77]
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671)[:1.8.0_77]
at java.lang.Class.getConstructor0(Class.java:3075)[:1.8.0_77]
at java.lang.Class.newInstance(Class.java:412)[:1.8.0_77]
at org.apache.felix.framework.Felix.createBundleActivator(Felix.java:4336)
at org.apache.felix.framework.Felix.activateBundle(Felix.java:2141)
... 7 more
Caused by: java.lang.ClassNotFoundException: com.fasterxml.jackson.module.afterburner.AfterburnerModule not found by world [239]
at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1532)[org.apache.felix.framework-4.2.1.jar:]
at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:75)[org.apache.felix.framework-4.2.1.jar:]
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1955)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)[:1.8.0_77]
... 13 more
All the required Jackson bundles are installed in Karaf:-
karaf#root>bundle:list | grep Jackson
123 | Active | 50 | 2.6.2 | Jackson-core
125 | Active | 50 | 2.6.2 | Jackson-annotations
238 | Installed | 80 | 2.7.1 | Jackson-module-Afterburner
karaf#root>bundle:list | grep jackson
124 | Active | 50 | 2.6.2 | jackson-databind
Everything works fine if I comment out the below line:-
objectMapper.registerModule(new AfterburnerModule());
Can some one let me know what I am doing wrong?
All the code I have placed in the github.

You already asked this at the karaf mailing list.
It's still the same thing, as long as the package isn't imported in your own application it won't work.
Since you do an import for *;optional=true you won't get a wiring exception as your imports are all optional. Therefore the ClassNotFound Exeception.
First of all check the headers for the right imports with
bundle:header [bundle-id]
second, since you are doing an * import it might happen as you don't explicitly ask for a certain class in a certain package that some packages aren't imported.
And a sub-package import doesn't help on the package, so if you have an import for
com.fasterxml.jackson.module.afterburner.subPackage
this won't help on resolving classes in
com.fasterxml.jackson.module.afterburner
So it's actually best to declare all imports and use the * only on sub-packages.
In your case add the following to your pom:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.4.0</version>
<inherited>true</inherited>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Version>${project.version}</Bundle-Version>
<Bundle-Activator>com.hello.world.HelloWorldActivator</Bundle-Activator>
<Import-Package>
com.fasterxml.jackson.module.afterburner.*,
*;resolution:=optional
</Import-Package>
</instructions>
</configuration>
</plugin>

Along with upgrading to Jackson 2.7.4. Modifying my Import-Package in pom.xml as shown below solved the issue:-
<Import-Package>com.fasterxml.jackson.module.afterburner.ser;resolution:=optional,*</Import-Package>

Related

Jira plugin fails after adding apache kafka dependancy

I am trying to create a JIRA plugin so that whenever an Issue is created, its posted to Kafka cluster. A sample listener code works fine. However when I add Maven dependency for Kafka, the plugin fails to load with below error.
org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from URL [bundle://219.0:0/META-INF/spring/plugin-context.xml]; nested exception is org.springframework.beans.FatalBeanException: Class [com.atlassian.plugin.spring.scanner.extension.AtlassianScannerNamespaceHandler] for namespace [http://www.atlassian.com/schema/atlassian-scanner] does not implement the [org.springframework.beans.factory.xml.NamespaceHandler] interface
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:414)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:187)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:223)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:194)
at org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext.loadBeanDefinitions(OsgiBundleXmlApplicationContext.java:171)
at org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext.loadBeanDefinitions(OsgiBundleXmlApplicationContext.java:141)
at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:133)
at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:619)
at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.access$800(AbstractDelegatedExecutionApplicationContext.java:57)
at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext$3.run(AbstractDelegatedExecutionApplicationContext.java:239)
at org.eclipse.gemini.blueprint.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)
at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.startRefresh(AbstractDelegatedExecutionApplicationContext.java:217)
at org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor.stageOne(DependencyWaiterApplicationContextExecutor.java:224)
at org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor.refresh(DependencyWaiterApplicationContextExecutor.java:177)
at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.refresh(AbstractDelegatedExecutionApplicationContext.java:154)
at org.eclipse.gemini.blueprint.extender.internal.activator.LifecycleManager$1.run(LifecycleManager.java:213)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.springframework.beans.FatalBeanException: Class [com.atlassian.plugin.spring.scanner.extension.AtlassianScannerNamespaceHandler] for namespace [http://www.atlassian.com/schema/atlassian-scanner] does not implement the [org.springframework.beans.factory.xml.NamespaceHandler] interface
at org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve(DefaultNamespaceHandlerResolver.java:132)
at org.eclipse.gemini.blueprint.context.support.DelegatedNamespaceHandlerResolver.resolve(DelegatedNamespaceHandlerResolver.java:55)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1361)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1352)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:178)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:98)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:508)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:392)
... 20 more
2020-09-04 18:06:54,517+0530 ThreadPoolAsyncTaskExecutor::Thread 26 ERROR yogeshpitale 1031x426x4 3reejl 127.0.0.1 /rest/plugins/1.0/installed-marketplace [o.e.g.b.e.internal.support.ExtenderConfiguration] Application context refresh failed (NonValidatingOsgiBundleXmlApplicationContext(bundle=com.vz.jira.defects-plugin, config=osgibundle:/META-INF/spring/*.xml))
org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from URL [bundle://219.0:0/META-INF/spring/plugin-context.xml]; nested exception is org.springframework.beans.FatalBeanException: Class [com.atlassian.plugin.spring.scanner.extension.AtlassianScannerNamespaceHandler] for namespace [http://www.atlassian.com/schema/atlassian-scanner] does not implement the [org.springframework.beans.factory.xml.NamespaceHandler] interface
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:414)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:187)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:223)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:194)
at org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext.loadBeanDefinitions(OsgiBundleXmlApplicationContext.java:171)
at org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext.loadBeanDefinitions(OsgiBundleXmlApplicationContext.java:141)
at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:133)
at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:619)
at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.access$800(AbstractDelegatedExecutionApplicationContext.java:57)
at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext$3.run(AbstractDelegatedExecutionApplicationContext.java:239)
at org.eclipse.gemini.blueprint.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)
at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.startRefresh(AbstractDelegatedExecutionApplicationContext.java:217)
at org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor.stageOne(DependencyWaiterApplicationContextExecutor.java:224)
at org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor.refresh(DependencyWaiterApplicationContextExecutor.java:177)
at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.refresh(AbstractDelegatedExecutionApplicationContext.java:154)
at org.eclipse.gemini.blueprint.extender.internal.activator.LifecycleManager$1.run(LifecycleManager.java:213)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.springframework.beans.FatalBeanException: Class [com.atlassian.plugin.spring.scanner.extension.AtlassianScannerNamespaceHandler] for namespace [http://www.atlassian.com/schema/atlassian-scanner] does not implement the [org.springframework.beans.factory.xml.NamespaceHandler] interface
at org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve(DefaultNamespaceHandlerResolver.java:132)
at org.eclipse.gemini.blueprint.context.support.DelegatedNamespaceHandlerResolver.resolve(DelegatedNamespaceHandlerResolver.java:55)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1361)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1352)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:178)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:98)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:508)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:392)
... 20 more
2020-09-04 18:06:54,517+0530 ThreadPoolAsyncTaskExecutor::Thread 26 ERROR yogeshpitale 1031x426x4 3reejl 127.0.0.1 /rest/plugins/1.0/installed-marketplace [o.e.g.b.e.i.dependencies.startup.DependencyWaiterApplicationContextExecutor] Unable to create application context for [com.vz.jira.defects-plugin], unsatisfied dependencies: none
org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from URL [bundle://219.0:0/META-INF/spring/plugin-context.xml]; nested exception is org.springframework.beans.FatalBeanException: Class [com.atlassian.plugin.spring.scanner.extension.AtlassianScannerNamespaceHandler] for namespace [http://www.atlassian.com/schema/atlassian-scanner] does not implement the [org.springframework.beans.factory.xml.NamespaceHandler] interface
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:414)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:187)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:223)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:194)
at org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext.loadBeanDefinitions(OsgiBundleXmlApplicationContext.java:171)
at org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext.loadBeanDefinitions(OsgiBundleXmlApplicationContext.java:141)
at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:133)
at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:619)
at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.access$800(AbstractDelegatedExecutionApplicationContext.java:57)
at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext$3.run(AbstractDelegatedExecutionApplicationContext.java:239)
at org.eclipse.gemini.blueprint.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)
at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.startRefresh(AbstractDelegatedExecutionApplicationContext.java:217)
at org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor.stageOne(DependencyWaiterApplicationContextExecutor.java:224)
at org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor.refresh(DependencyWaiterApplicationContextExecutor.java:177)
at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.refresh(AbstractDelegatedExecutionApplicationContext.java:154)
at org.eclipse.gemini.blueprint.extender.internal.activator.LifecycleManager$1.run(LifecycleManager.java:213)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.springframework.beans.FatalBeanException: Class [com.atlassian.plugin.spring.scanner.extension.AtlassianScannerNamespaceHandler] for namespace [http://www.atlassian.com/schema/atlassian-scanner] does not implement the [org.springframework.beans.factory.xml.NamespaceHandler] interface
at org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve(DefaultNamespaceHandlerResolver.java:132)
at org.eclipse.gemini.blueprint.context.support.DelegatedNamespaceHandlerResolver.resolve(DelegatedNamespaceHandlerResolver.java:55)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1361)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1352)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:178)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:98)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:508)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:392)
... 20 more
Below is my pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.vz.jira</groupId>
<artifactId>jira-defects-plugin</artifactId>
<version>1.0.0-SNAPSHOT</version>
<organization>
<name>Example Company</name>
<url>http://www.example.com/</url>
</organization>
<name>jira-defects-plugin</name>
<description>This is the com.vz.jira:jira-defects-plugin plugin for Atlassian JIRA.</description>
<packaging>atlassian-plugin</packaging>
<dependencies>
<dependency>
<groupId>com.atlassian.jira</groupId>
<artifactId>jira-api</artifactId>
<version>${jira.version}</version>
<scope>provided</scope>
</dependency>
<!-- Add dependency on jira-core if you want access to JIRA implementation
classes as well as the sanctioned API. -->
<!-- This is not normally recommended, but may be required eg when migrating
a plugin originally developed against JIRA 4.x -->
<!-- <dependency> <groupId>com.atlassian.jira</groupId> <artifactId>jira-core</artifactId>
<version>${jira.version}</version> <scope>provided</scope> </dependency> -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.atlassian.plugin</groupId>
<artifactId>atlassian-spring-scanner-annotation</artifactId>
<version>${atlassian.spring.scanner.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.atlassian.plugin</groupId>
<artifactId>atlassian-spring-scanner-runtime</artifactId>
<version>${atlassian.spring.scanner.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
<scope>provided</scope>
</dependency>
<!-- WIRED TEST RUNNER DEPENDENCIES -->
<dependency>
<groupId>com.atlassian.plugins</groupId>
<artifactId>atlassian-plugins-osgi-testrunner</artifactId>
<version>${plugin.testrunner.version}</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.10.RELEASE</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.kafka/kafka-streams -->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-streams</artifactId>
<version>2.0.1</version>
<!-- <scope>provided</scope> -->
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.kafka/spring-kafka -->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<!-- <version>2.5.4.RELEASE</version> -->
<!-- <scope>provided</scope> -->
<version>2.0.1.RELEASE</version>
</dependency>
<!-- Uncomment to use TestKit in your project. Details at https://bitbucket.org/atlassian/jira-testkit -->
<!-- You can read more about TestKit at https://developer.atlassian.com/display/JIRADEV/Plugin+Tutorial+-+Smarter+integration+testing+with+TestKit -->
<!-- <dependency> <groupId>com.atlassian.jira.tests</groupId> <artifactId>jira-testkit-client</artifactId>
<version>${testkit.version}</version> <scope>test</scope> </dependency> -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.atlassian.maven.plugins</groupId>
<artifactId>jira-maven-plugin</artifactId>
<version>${amps.version}</version>
<extensions>true</extensions>
<configuration>
<extractDependencies>true</extractDependencies>
<productVersion>${jira.version}</productVersion>
<productDataVersion>${jira.version}</productDataVersion>
<log4jProperties>src/aps/log4j.properties</log4jProperties>
<!-- Uncomment to install TestKit backdoor in JIRA. -->
<!-- <pluginArtifacts> <pluginArtifact> <groupId>com.atlassian.jira.tests</groupId>
<artifactId>jira-testkit-plugin</artifactId> <version>${testkit.version}</version>
</pluginArtifact> </pluginArtifacts> -->
<enableQuickReload>true</enableQuickReload>
<!-- See here for an explanation of default instructions: -->
<!-- https://developer.atlassian.com/docs/advanced-topics/configuration-of-instructions-in-atlassian-plugins -->
<instructions>
<Atlassian-Plugin-Key>${atlassian.plugin.key}</Atlassian-Plugin-Key>
<!-- Add package to export here -->
<Export-Package>
com.vz.jira.api,
</Export-Package>
<!-- Add package import here -->
<Import-Package>
org.springframework.osgi.*;resolution:="optional",
org.eclipse.gemini.blueprint.*;resolution:="optional",
org.springframework.kafka.*;resolution:="optional",
org.apache.kafka.*;resolution:="optional",
org.apache.kafka.clients.*;resolution:="optional",
org.apache.kafka.common.*;resolution:="optional",
*;version="0";resolution:=optional
</Import-Package>
<!-- Ensure plugin is spring powered -->
<Spring-Context>*</Spring-Context>
</instructions>
</configuration>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependency</id>
<phase>process-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.outputDirectory}/META-INF/lib</outputDirectory>
<includeArtifactIds>spring-jdbc,spring-tx</includeArtifactIds>
<stripVersion>false</stripVersion>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.atlassian.plugin</groupId>
<artifactId>atlassian-spring-scanner-maven-plugin</artifactId>
<version>${atlassian.spring.scanner.version}</version>
<executions>
<execution>
<goals>
<goal>atlassian-spring-scanner</goal>
</goals>
<phase>process-classes</phase>
</execution>
</executions>
<configuration>
<scannedDependencies>
<dependency>
<groupId>com.atlassian.plugin</groupId>
<artifactId>atlassian-spring-scanner-external-jar</artifactId>
</dependency>
</scannedDependencies>
<verbose>false</verbose>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<jira.version>7.13.0</jira.version>
<amps.version>8.0.2</amps.version>
<plugin.testrunner.version>2.0.1</plugin.testrunner.version>
<atlassian.spring.scanner.version>1.2.13</atlassian.spring.scanner.version>
<!-- This property ensures consistency between the key in atlassian-plugin.xml
and the OSGi bundle's key. -->
<atlassian.plugin.key>${project.groupId}.${project.artifactId}</atlassian.plugin.key>
<!-- TestKit version 6.x for JIRA 6.x -->
<testkit.version>6.3.11</testkit.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>
And below is my Java class.
package com.vz.jira.listeners;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;
import com.atlassian.event.api.EventListener;
import com.atlassian.event.api.EventPublisher;
import com.atlassian.jira.event.issue.IssueEvent;
import com.atlassian.jira.event.type.EventType;
import com.atlassian.jira.issue.Issue;
import com.atlassian.plugin.spring.scanner.annotation.imports.JiraImport;
#Component
public class IssueCreatedResolvedListener implements InitializingBean, DisposableBean {
private static final Logger log = LoggerFactory.getLogger(IssueCreatedResolvedListener.class);
#JiraImport
private final EventPublisher eventPublisher;
#Autowired
private KafkaTemplate<Long, String> template;
#Autowired
public IssueCreatedResolvedListener(#JiraImport EventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
#EventListener
public void onIssueEvent(IssueEvent issueEvent) {
Long eventTypeId = issueEvent.getEventTypeId();
Issue issue = issueEvent.getIssue();
System.out.println("Got Issue with ID:"+issue.getId());
try{
System.out.println("Sending message to queue");
this.template.send("issue",issue.getId(),issue.toString());
System.out.println("Message sent to queue");
}catch(Exception e){
e.printStackTrace();
}
if (eventTypeId.equals(EventType.ISSUE_CREATED_ID)) {
log.info("Issue {} has been created at {}.", issue.getKey(), issue.getCreated());
} else if (eventTypeId.equals(EventType.ISSUE_RESOLVED_ID)) {
log.info("Issue {} has been resolved at {}.", issue.getKey(), issue.getResolutionDate());
} else if (eventTypeId.equals(EventType.ISSUE_CLOSED_ID)) {
log.info("Issue {} has been closed at {}.", issue.getKey(), issue.getUpdated());
}
}
#Override
public void destroy() throws Exception {
log.info("Disabling plugin");
eventPublisher.unregister(this);
}
#Override
public void afterPropertiesSet() throws Exception {
log.info("Enabling plugin");
eventPublisher.register(this);
}
}
I tried debuugin via OSGI browser (refer to the attached image).
For some of the imported packeges, "provided by" is missing. I wonder if that is causing failure of the plugin but unable to understand how to resolve it.
Finally, I was able crack down the problem. Here's what I did.
Removed kafka-streams dependency which wasn't really required.
Kept <scope>provided</scope> for all the dependencies
Since JARs need to be available at runtime. I added them to plugin>execution> configuration>includeArtifactIds so that JARs are exported to the runtime environment
This is important. I Experimented with different versions of Kafka. Since the JIRA version I was using, was 8.5.4 (released couple of years back), I found versions of other JARs released during/just before the same time period & used those.
I faced runtime issues for some missing classes. I added those artifact Ids in plugin>execution>configuration>includeArtifactIds
Now my final POM looks like below.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.vz.jira</groupId>
<artifactId>jira-defects-plugin</artifactId>
<version>1.0.0-SNAPSHOT</version>
<organization>
<name>Example Company</name>
<url>http://www.example.com/</url>
</organization>
<name>jira-defects-plugin</name>
<description>This is the com.vz.jira:jira-defects-plugin plugin for Atlassian JIRA.</description>
<packaging>atlassian-plugin</packaging>
<dependencies>
<dependency>
<groupId>com.atlassian.jira</groupId>
<artifactId>jira-api</artifactId>
<version>${jira.version}</version>
<scope>provided</scope>
</dependency>
<!-- Add dependency on jira-core if you want access to JIRA implementation
classes as well as the sanctioned API. -->
<!-- This is not normally recommended, but may be required eg when migrating
a plugin originally developed against JIRA 4.x -->
<!-- <dependency> <groupId>com.atlassian.jira</groupId> <artifactId>jira-core</artifactId>
<version>${jira.version}</version> <scope>provided</scope> </dependency> -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.atlassian.plugin</groupId>
<artifactId>atlassian-spring-scanner-annotation</artifactId>
<version>${atlassian.spring.scanner.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.atlassian.plugin</groupId>
<artifactId>atlassian-spring-scanner-runtime</artifactId>
<version>${atlassian.spring.scanner.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
<scope>provided</scope>
</dependency>
<!-- WIRED TEST RUNNER DEPENDENCIES -->
<dependency>
<groupId>com.atlassian.plugins</groupId>
<artifactId>atlassian-plugins-osgi-testrunner</artifactId>
<version>${plugin.testrunner.version}</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.7.RELEASE</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<version>2.2.8.RELEASE</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.kafka/kafka-clients -->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>2.2.1</version>
<scope>provided</scope>
</dependency>
<!-- Uncomment to use TestKit in your project. Details at https://bitbucket.org/atlassian/jira-testkit -->
<!-- You can read more about TestKit at https://developer.atlassian.com/display/JIRADEV/Plugin+Tutorial+-+Smarter+integration+testing+with+TestKit -->
<!-- <dependency> <groupId>com.atlassian.jira.tests</groupId> <artifactId>jira-testkit-client</artifactId>
<version>${testkit.version}</version> <scope>test</scope> </dependency> -->
<!-- <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId>
<version>2.10.0</version> <scope>provided</scope> </dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId>
<version>2.10.0</version> <scope>provided</scope> </dependency> <dependency>
<groupId>org.springframework</groupId> <artifactId>spring-core</artifactId>
<version>5.2.0.RELEASE</version> <scope>provided</scope> </dependency> -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.atlassian.maven.plugins</groupId>
<artifactId>jira-maven-plugin</artifactId>
<version>${amps.version}</version>
<extensions>true</extensions>
<configuration>
<extractDependencies>true</extractDependencies>
<productVersion>${jira.version}</productVersion>
<productDataVersion>${jira.version}</productDataVersion>
<log4jProperties>src/aps/log4j.properties</log4jProperties>
<!-- Uncomment to install TestKit backdoor in JIRA. -->
<!-- <pluginArtifacts> <pluginArtifact> <groupId>com.atlassian.jira.tests</groupId>
<artifactId>jira-testkit-plugin</artifactId> <version>${testkit.version}</version>
</pluginArtifact> </pluginArtifacts> -->
<enableQuickReload>true</enableQuickReload>
<!-- See here for an explanation of default instructions: -->
<!-- https://developer.atlassian.com/docs/advanced-topics/configuration-of-instructions-in-atlassian-plugins -->
<instructions>
<Atlassian-Plugin-Key>${atlassian.plugin.key}</Atlassian-Plugin-Key>
<!-- Add package to export here -->
<Export-Package>
com.vz.jira.api,
</Export-Package>
<!-- Add package import here -->
<Import-Package>
<!-- org.springframework.osgi.*;resolution:="optional", org.eclipse.gemini.blueprint.*;resolution:="optional",
org.springframework.kafka.*;resolution:="optional", org.apache.kafka.*;resolution:="optional",
org.apache.kafka.clients.*;resolution:="optional", org.apache.kafka.common.*;resolution:="optional", -->
*;version="0";resolution:=optional
</Import-Package>
<DynamicImport-Package>*</DynamicImport-Package>
<!-- Ensure plugin is spring powered -->
<Spring-Context>*</Spring-Context>
</instructions>
</configuration>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependency</id>
<phase>process-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.outputDirectory}/META-INF/lib</outputDirectory>
<includeArtifactIds>spring-kafka,kafka-clients,spring-context,spring-messaging</includeArtifactIds>
<stripVersion>false</stripVersion>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.atlassian.plugin</groupId>
<artifactId>atlassian-spring-scanner-maven-plugin</artifactId>
<version>${atlassian.spring.scanner.version}</version>
<executions>
<execution>
<goals>
<goal>atlassian-spring-scanner</goal>
</goals>
<phase>process-classes</phase>
</execution>
</executions>
<configuration>
<scannedDependencies>
<dependency>
<groupId>com.atlassian.plugin</groupId>
<artifactId>atlassian-spring-scanner-external-jar</artifactId>
</dependency>
</scannedDependencies>
<verbose>false</verbose>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<jira.version>7.13.0</jira.version>
<amps.version>8.0.2</amps.version>
<plugin.testrunner.version>2.0.1</plugin.testrunner.version>
<atlassian.spring.scanner.version>1.2.13</atlassian.spring.scanner.version>
<!-- This property ensures consistency between the key in atlassian-plugin.xml
and the OSGi bundle's key. -->
<atlassian.plugin.key>${project.groupId}.${project.artifactId}</atlassian.plugin.key>
<!-- TestKit version 6.x for JIRA 6.x -->
<testkit.version>6.3.11</testkit.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
The Kafka Template related settings were done in another class file as below.
#Scanned
public class KafkaConfig {
#Bean
public ProducerFactory<Long, String> producerFactory() {
return new DefaultKafkaProducerFactory<>(producerConfigs());
}
#Bean
public Map<String, Object> producerConfigs() {
System.out.println("Intiailizing the config");
Map<String, Object> props = new HashMap<>();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092,localhost:9093");
props.put(ProducerConfig.RETRIES_CONFIG, 1);
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, LongSerializer.class);
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
props.put(ProducerConfig.BATCH_SIZE_CONFIG, 16384);
props.put(ProducerConfig.LINGER_MS_CONFIG, 1);
props.put(ProducerConfig.BUFFER_MEMORY_CONFIG, 33554432);
/*props.put(ProducerConfig.ACKS_CONFIG, "all");
props.put(ProducerConfig.RETRIES_CONFIG, 10);*/
return props;
}
#Bean
public KafkaTemplate<Long, String> kafkaTemplate() {
return new KafkaTemplate<Long, String>(producerFactory());
}
}
I somehow wasn't able to get KafkaTemplate configured & autowired via Spring even after adding #Configuration annotation. Hence instantiated it manually using code below (which isnt a good way though!)
private KafkaTemplate<Long, String> template= new KafkaConfig().kafkaTemplate();
and used below code to send topic to Kafka.
package com.vz.jira.listeners;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.stereotype.Component;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
import com.atlassian.event.api.EventListener;
import com.atlassian.event.api.EventPublisher;
import com.atlassian.jira.event.issue.IssueEvent;
import com.atlassian.jira.issue.Issue;
import com.atlassian.plugin.spring.scanner.annotation.component.Scanned;
import com.atlassian.plugin.spring.scanner.annotation.imports.JiraImport;
import com.vz.jira.config.KafkaConfig;
import com.vz.jira.domain.Defects;
import com.vz.jira.util.DefectUtil;
#Scanned
#Component
public class IssueCreatedResolvedListener implements InitializingBean, DisposableBean {
private static final Logger log = LoggerFactory.getLogger(IssueCreatedResolvedListener.class);
#JiraImport
private final EventPublisher eventPublisher;
private ObjectMapper mapper = new ObjectMapper();
private KafkaTemplate<Long, String> template= new KafkaConfig().kafkaTemplate();
#Autowired
public IssueCreatedResolvedListener(#JiraImport EventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
#EventListener
public void onIssueEvent(IssueEvent issueEvent) {
try{
Long eventTypeId = issueEvent.getEventTypeId();
Issue issue = issueEvent.getIssue();
if(issue!=null){
Defects defect = DefectUtil.getDesiredIssueDetails(issue); //extract necessary details to be sent to Kafka
ListenableFuture<SendResult<Long, String>> future=template.send("issue",issue.getId(),mapper.writeValueAsString(defect));
future.addCallback(new ListenableFutureCallback<SendResult<Long, String>>() {
#Override
public void onSuccess(SendResult<Long, String> result) {
handleSuccess(eventTypeId,issue.getDescription(),result);
}
#Override
public void onFailure(Throwable ex) {
try {
handleFailure(eventTypeId,issue.getDescription(),ex);
} catch (Throwable e) {
e.printStackTrace();
}
}
});
}
}catch (Exception e){
e.printStackTrace();
}
}
protected void handleFailure(Long key, String value, Throwable ex) throws Throwable {
System.out.println("Error sending message & the exception is: {} "+ ex.getMessage());
throw ex;
}
protected void handleSuccess(Long key, String value, SendResult<Long, String> result) {
System.out.println("Message Sent Successfully for key: "+key+" value "+value+" partiotion is: "+ result.getRecordMetadata().partition() );
}
#Override
public void destroy() throws Exception {
System.out.println("Disabling plugin");
eventPublisher.unregister(this);
}
#Override
public void afterPropertiesSet() throws Exception {
System.out.println("Enabling plugin");
eventPublisher.register(this);
}
}

spring boot test junit null pointer exception

im new on this of unit tests, so im trying to code the unit test for my service, right now i have this class
package com.praxis.topics.service;
import com.praxis.topics.exception.EntityNotFoundException;
import com.praxis.topics.model.Topic;
import com.praxis.topics.model.enums.Status;
import com.praxis.topics.repository.TopicRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
#Service("topics")
public class TopicServiceImpl implements TopicService {
private final TopicRepository topicRepository;
#Autowired
public TopicServiceImpl(TopicRepository topicRepository) {
this.topicRepository = topicRepository;
}
#Override
public List<Topic> getTopicsByStatus(int status) {
// Check if status exists in enum
if (status < 0 || Status.values().length - 1 < status)
throw new ArrayIndexOutOfBoundsException(status);
return topicRepository.findTopicByStatus(Status.values()[status]);
}
#Override
public Topic addTopic(Topic topic) {
//topic.setCreatedAt(LocalDateTime.now());
return topicRepository.save(topic);
}
#Override
public Topic updateTopic(Topic topic) throws EntityNotFoundException {
if (topicRepository.findTopicById(topic.getId()) == null)
throw new EntityNotFoundException(String.format("Topic with id: %s was not found", topic.getId()));
return topicRepository.save(topic);
}
#Override
public Topic getTopicById(String id) {
return topicRepository.findTopicById(id);
}
#Override
public void deleteTopicById(String id) {
topicRepository.deleteTopicById(id);
}
#Override
public List<Topic> getTopicsByName(String name) {
return topicRepository.findAllByNameContains(name);
}
#Override
public Topic getTopicByName(String name) {
return topicRepository.findTopicByName(name);
}
#Override
public List<Topic>getAllTopics(){
return topicRepository.findAll();
}
}
the model of topics is this
package com.praxis.topics.model;
import com.praxis.topics.model.enums.Status;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
#Document(collection = "Topic")
public class Topic {
#Id
private String id;
#NotEmpty(message = "The name is required")
private String name;
#NotEmpty(message = "The description is required")
private String description;
private Status status;
private String chat;
private int teachers;
private int students;
#DateTimeFormat(pattern = "dd-MM-yyyy hh:mm:ss")
private LocalDateTime createdAt;
#DateTimeFormat(pattern = "dd-MM-yyyy hh:mm:ss")
private LocalDateTime openedAt;
#DateTimeFormat(pattern = "dd-MM-yyyy hh:mm:ss")
private LocalDateTime closedAt;
public Topic() {}
public Topic(String name, String description) {
this.name = name;
this.description = description;
this.createdAt = LocalDateTime.now();
}
and im trying to do this test for but it throws me a null pointer exception, like if the service variable wasnt initialized or something
package com.praxis.topics.service;
import com.praxis.topics.model.Topic;
import com.praxis.topics.repository.TopicRepository;
import org.springframework.beans.factory.annotation.Autowired;
import static org.junit.jupiter.api.Assertions.*;
class TopicServiceImplTest {
#Autowired
TopicServiceImpl service;
#org.junit.jupiter.api.Test
void addTopic() {
Topic topic = new Topic("java", "test");
assertEquals(topic, service.addTopic(topic));
}
}
and this are the exceptions i get
java.lang.NullPointerException at com.praxis.topics.service.TopicServiceImplTest.addTopic(TopicServiceImplTest.java:29)
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:564)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:436)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:170)
at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:166)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:113)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:58)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:112)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:120)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:430)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:120)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:120)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:430)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:120)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:55)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:65)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
any idea? i think that its because some of the variable dont get initialized, but im doing adding the #Autowired on those so i dont know what it is
this is my pom file
http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
<groupId>com.praxis</groupId>
<artifactId>topics</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>topics</name>
<description>Project for Integrador 2018</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
For starters, if you're using JUnit Jupiter (the programming model in JUnit 5), you'll have to configure the Jupiter Test Engine in your build.
I recommend you use the official spring-boot-sample-junit-jupiter sample project as a template.
The pom.xml shows how to configure the Jupiter Test Engine with the Maven Surefire Plugin:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>${junit-platform.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
Note that it also shows that you need dependency declarations for
junit-jupiter-api and junit-jupiter-engine.
And SampleJunitJupiterApplicationTests shows how to configure Spring Boot's testing support with the SpringExtension for JUnit Jupiter:
#ExtendWith(SpringExtension.class)
#SpringBootTest
class TopicServiceImplTest {
#Autowired
TopicService service;
// ..
}
We had recently started using Spring 4.3, JUnit5, Maven together as well and got NullPointerException in integration tests where #Autowired was used.
Solution for us was to upgrade maven-related test dependencies:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0-M4</version> // upgraded from 2.19.1
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M4</version> // upgraded from 2.19
</plugin>
Your TopicServiceImplTest class is not spring component so #Autowired won't work.
Spring Boot test should be annotated with #SpringBootTest and #RunWith(SpringRunner.class). Optionaly you could use other annotations to define your context to suit your specific needs. You can find basic information here: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html

java.lang.ClassCastException: org.glassfish.jersey.jackson.internal.JacksonAutoDiscoverable cannot be cast to spi.AutoDiscoverable

I am new to implementing REST API services. I have tried the simple resources to implement. unfortunately I stuck with this exception. I have googled and tried many options but no luck. I am unsure what am doing wrong. Please help me.
Created a Dynamic Web project "JersyJson"
Created a resouce named - JSONService.java (source is from googling)
Created a Java Bean class - Track.java (source is from googling)
Converted the project into Maven project
Created a Application file - JersyJson.java file for Application Annotation
using the latest Jersy Jars (version: 2.22.2)
Imported & configured jersey-media-json-jackson and jersey-media-moxy jars (2.22.2) in pom.xml
Pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>JersyJson</groupId>
<artifactId>JersyJson</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<!-- if your container implements Servlet API older than 3.0, use "jersey-container-servlet-core" -->
<artifactId>jersey-container-servlet</artifactId>
<version>2.22.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.22.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.22.2</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>JersyJson</display-name>
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/json/metallica/*</url-pattern>
</servlet-mapping>
</web-app>
JersyJson.java (ApplicationAnnotation file)
#ApplicationPath("json")
public class JersyJson extends ResourceConfig {
public JersyJson() {
packages("com.sai.jersyjson");
}
}
JSONservice.java:
package com.sai.jersyjson;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
#Path("/json/metallica")
public class JSONService {
#GET
#Path("/get")
#Produces(MediaType.APPLICATION_JSON)
public Track getTrackInJSON() {
Track track = new Track();
track.setTitle("Enter Sandman");
track.setSinger("Metallica");
return track;
}
#POST
#Path("/post")
#Consumes(MediaType.APPLICATION_JSON)
public Response createTrackInJSON(Track track) {
String result = "Track saved : " + track;
return Response.status(201).entity(result).build();
}
}
Track.java (simple bean class)
package com.sai.jersyjson;
public class Track {
String title;
String singer;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getSinger() {
return singer;
}
public void setSinger(String singer) {
this.singer = singer;
}
#Override
public String toString() {
return "Track [title=" + title + ", singer=" + singer + "]";
}
}
After I run this project in Eclispe using Tomcat webserver, I get the following
error with 404-Error Status
SEVERE: StandardWrapper.Throwable
java.lang.ClassCastException: org.glassfish.jersey.jackson.internal.JacksonAutoDiscoverable cannot be cast to org.glassfish.jersey.internal.spi.AutoDiscoverable
at org.glassfish.jersey.model.internal.CommonConfig$2.compare(CommonConfig.java:594)
at java.util.TreeMap.put(Unknown Source)
at java.util.TreeSet.add(Unknown Source)
at java.util.AbstractCollection.addAll(Unknown Source)
at java.util.TreeSet.addAll(Unknown Source)
at org.glassfish.jersey.model.internal.CommonConfig.configureAutoDiscoverableProviders(CommonConfig.java:616)
at org.glassfish.jersey.server.ResourceConfig.configureAutoDiscoverableProviders(ResourceConfig.java:811)
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:447)
at org.glassfish.jersey.server.ApplicationHandler.access$500(ApplicationHandler.java:184)
at org.glassfish.jersey.server.ApplicationHandler$3.call(ApplicationHandler.java:350)
at org.glassfish.jersey.server.ApplicationHandler$3.call(ApplicationHandler.java:347)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.processWithException(Errors.java:255)
at org.glassfish.jersey.server.ApplicationHandler.(ApplicationHandler.java:347)
at org.glassfish.jersey.servlet.WebComponent.(WebComponent.java:392)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:177)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:369)
at javax.servlet.GenericServlet.init(GenericServlet.java:158)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1238)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1041)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4996)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5285)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
I had the exact same problem in Weblogic. It seems to be that the JacksonAutoDiscoverable and AutoDiscoverable came from different class loaders and therefore different versions. AutoDiscoverable exists in jersey-common and JacksonAutoDiscoverable exists in jersey-media-json-jackson.
I got around this by letting Weblogic have all the discoverable classes and instead specifying 'com.fasterxml.jackson.*' as prefer-application-packages/resources to have my own version of jackson.
I had this same problem, but I got a fix. There's an issue with conflicting dependencies. You've included the jersey-media-json-jackson dependency, but the Tomcat web container already provides those classes.
Just add the scope tag to your dependency:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.27</version>
<scope>provided</scope>
</dependency>
Refer to the link for more information: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#
In my case I worked with Glassfish and I had the Glassfish descriptor (glassfish-web.xml) in the project as follow:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app error-url="">
<class-loader delegate="false"/>
<parameter-encoding default-charset="UTF-8"/>
<jsp-config>
<property name="keepgenerated" value="true">
<description>Keep a copy of the generated servlet class' java code.</description>
</property>
</jsp-config>
</glassfish-web-app>
The class-loader property was marked with the attribute
delegate=false
, I think that was my mistake, because as Glassfish Deployment Guide say, this attribute must be true when you are exposing services.
https://javaee.github.io/glassfish/doc/4.0/application-deployment-guide.pdf#G11.1006531
The solution that worked for me was remove that file and keep only the Standard Deployment Descriptor(web.xml).
Hope this help.
I had this same problem with JBOSS6 server. After adding jersey-media-moxy dependency to pom file, it was worked.
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.25.1</version>
</dependency>
I solved the issue by adding both jersey-common and jersey-media-json-jackson. Removed jersey-bean-validation.
<dependency>
<artifactId>jersey-common</artifactId>
<groupId>org.glassfish.jersey.core</groupId>
<version>2.29.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.29.1</version>
</dependency>
<!--<dependency>
<artifactId>jersey-bean-validation</artifactId>
<groupId>org.glassfish.jersey.ext</groupId>
<version>2.29.1</version>
</dependency>-->

Issue with null service with Declarative Services in Karaf 4.0.1

I'm attempting to create a service deployable on karaf that imports a file into a repository. The way my project has been set up is I have a command line class to handle the creation of the command in karaf (by using org.apache.felix.gogo.commands Annotations along with a blueprint.xml file) and the calling of the service, along with a seperate project to handle the implementation of the service.
The command is created in karaf without issue, and I can call it with the respective arguments, yet I always get a null pointer exception when running it due to the import service being null. Running scr:details on the import service and the repository returns this info:
**karaf#root()> scr:details
com.inovexcorp.myproject.service.repository.memory
Component Details
Name : com.inovexcorp.mmyproject.service.repository.memory
State : ACTIVE
Properties :
service.pid=com.inovexcorp.myproject.service.repository.memory.2d2dba73-30e2-4ce8-8dd0-2246bd5628b7
repositorytype=memory
service.factoryPid=com.inovexcorp.myproject.service.repository.memory
component.name=com.inovexcorp.myproject.service.repository.memory
felix.fileinstall.filename=file:/home/zachary/karaf/apache-karaf-4.0.1/etc/com.inovexcorp.myproject.service.repository.memory-cli-rdf-service.cfg
component.id=1
repositoryId=cli-rdf-service
References**
**karaf#root()> scr:details
org.myproject.etl.rdf.importer.impl.RDFImportServiceImpl
Component Details
Name : org.myproject.etl.rdf.importer.impl.RDFImportServiceImpl
State : ACTIVE
Properties :
repository.target=(repositorytype=memory)
component.name=org.myproject.etl.rdf.importer.impl.RDFImportServiceImpl
component.id=2
References
Reference : repository
State : satisfied
Multiple : single
Optional : mandatory
Policy : static
Service Reference : Bound Service ID 175 (com.inovexcorp.myproject.service.repository.memory)**
And here are the headers for the CLI and Service Implementation Bundles:
**karaf#root()> headers 294
importer (294)
Bnd-LastModified = 1443035070538
Build-Jdk = 1.7.0_85
Built-By = zachary
Created-By = Apache Maven Bundle Plugin
Manifest-Version = 1.0
Tool = Bnd-1.50.0
Bundle-ManifestVersion = 2
Bundle-Name = importer
Bundle-SymbolicName = importer
Bundle-Version = 0.0.1.SNAPSHOT
Import-Service =
org.myproject.etl.rdf.importer.api.RDFImportService;multiple:=false
Import-Package =
org.apache.felix.gogo.commands;version="[0.10,1)",
org.apache.karaf.shell.console;version="[2.2,3)",
org.myproject.etl.rdf.importer.api;version="[0.0,1)",
org.openrdf.rio;version="[2.7,3)",
org.osgi.service.blueprint;version="[1.0.0,2.0.0)"**
karaf#root()> headers 291
rdf.import (291)
----------------
Bnd-LastModified = 1442862863229
Build-Jdk = 1.7.0_85
Built-By = zachary
Created-By = Apache Maven Bundle Plugin
Manifest-Version = 1.0
Service-Component = OSGI-INF/org.myproject.etl.rdf.importer.impl.RDFImportServiceImpl.xml
Tool = Bnd-1.50.0
Bundle-ManifestVersion = 2
Bundle-Name = rdf.import
Bundle-SymbolicName = rdf.import
Bundle-Version = 0.0.1.SNAPSHOT
Import-Service =
org.openrdf.repository.Repository
Export-Package =
org.myproject.etl.rdf.importer.api;
uses:=org.openrdf.rio;
version=0.0.1.SNAPSHOT
Import-Package =
org.myproject.etl.rdf.importer.api,
org.openrdf.model;version="[2.7,3)",
org.openrdf.model.impl;version="[2.7,3)",
org.openrdf.repository;version="[2.7,3)",
org.openrdf.rio;version="[2.7,3)",
org.osgi.service.component;version="[1.1,2)"
I've been caught up on this issue for awhile, if anyone has any info on what the issue could be it'd be much appreciated!
EDIT: Adding source code for clarification
CLI class:
package org.myproject.cli.importer;
import java.io.File;
import org.apache.felix.gogo.commands.Argument;
import org.apache.felix.gogo.commands.Command;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.openrdf.rio.RDFFormat;
import org.myproject.etl.rdf.importer.api.RDFImportService;
#Command(scope = "myproject", name = "import", description = "Imports objects to a repository")
public class CLIImporter extends OsgiCommandSupport{
private RDFImportService importService;
#Argument(index = 0, name = "repId", description = "The id of the repository the file will be imported to", required = true, multiValued = false)
String repositoryId = null;
#Argument(index = 1, name = "file", description = "The file to be imported into the repository", required = true, multiValued = false)
String file = null;
#Argument(index = 2, name = "continueOnError", description = "Optional: If true, continue parsing even if there is an error on a line.", required = true, multiValued = false)
boolean continueOnError = false;
#Argument(index = 3, name = "fileType", description = "Optional: Specify the file type if the one given is unsupported by Sesame.", required = false, multiValued = false)
String fileType = null;
#Argument(index = 4, name = "help", description = "Optional: If true, display a help menu.", required = false, multiValued = false)
boolean help = false;
public RDFImportService getImportService() {
return importService;
}
public void setImportService(RDFImportService importService) {
this.importService = importService;
}
#Override
protected Object doExecute() throws Exception {
File newFile = new File(file);
System.out.println(repositoryId + " " + file + " " + continueOnError + " " + importService);
if(fileType == null && help == false){
importService.importFile(repositoryId, newFile, continueOnError);
}
else if(help == false){
importService.importFile(repositoryId, newFile, continueOnError, RDFFormat.forMIMEType(fileType));
}
else if(fileType == null){
// impService.importFile(repositoryId, file, continueOnError, help);
}
else{
// impService.importFile(repositoryId, file, continueOnError, fileType, help);
}
return null;
}
}
ImportServiceImpl class:
package org.myproject.etl.rdf.importer.impl;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.myproject.etl.rdf.importer.api.RDFImportService;
import org.openrdf.model.Resource;
import org.openrdf.model.impl.BNodeImpl;
import org.openrdf.repository.Repository;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;
import org.openrdf.rio.RDFFormat;
import org.openrdf.rio.RDFParseException;
import org.openrdf.rio.Rio;
import org.osgi.service.component.ComponentContext;
import aQute.bnd.annotation.component.Component;
import aQute.bnd.annotation.component.Reference;
#Component(provide = RDFImportService.class, immediate=true)
public class RDFImportServiceImpl implements RDFImportService{
private Repository repository;
private ComponentContext context;
private RepositoryConnection repConnect;
private Resource resource = new BNodeImpl("string");
#Reference(target="(repositorytype=memory)")
public void setRepository(Repository repository) {
this.repository = repository;
}
public void importFile(String repositoryID, File file, Boolean cont) {
try {
if (file == null) {
throw new FileNotFoundException();
}
RDFFormat format = Rio.getParserFormatForFileName(file.getName());
if (format == null) {
throw new IOException();
}
System.out.println("Repository connecting...");
repConnect = repository.getConnection();
repConnect.add(file, null, format, resource);
System.out.println("Repository set!");
System.out.println(repConnect.isEmpty());
System.out.println("Executing Import command");
System.out.println("Arguments passed: " + repositoryID + " " + file);
} catch (FileNotFoundException e) {
System.out.println("FnF Exception!");
e.printStackTrace();
} catch (IOException e) {
System.out.println("IOException! File type not supported by Sesame.");
e.printStackTrace();
} catch (RepositoryException e) {
System.out.println("Repository Exception!");
e.printStackTrace();
} catch (RDFParseException e) {
System.out.println("RDFParseException! There was an error parsing the RDF file.");
e.printStackTrace();
}
}
public void importFile(String repositoryID, File file, Boolean cont, RDFFormat format) {
try {
if (file == null) {
throw new FileNotFoundException();
}
if (format == null) {
format = Rio.getParserFormatForFileName(file.getName());
if(format == null){
throw new IOException();
}
}
repConnect = repository.getConnection();
String newURI = "com.inovexcorp.myproject." + repositoryID;
repConnect.add(file, newURI, format);
System.out.println("Repository set!");
System.out.println(repConnect.isEmpty());
System.out.println("Executing Import command");
System.out.println("Arguments passed: " + repositoryID + " " + file);
repConnect.close();
} catch (FileNotFoundException e) {
System.out.println("FnF Exception!");
e.printStackTrace();
} catch (IOException e) {
System.out.println("IOException! File type not supported by Sesame.");
e.printStackTrace();
} catch (RepositoryException e) {
System.out.println("Repository Exception!");
e.printStackTrace();
} catch (RDFParseException e) {
System.out.println("RDFParseException! There was an error parsing the RDF file.");
e.printStackTrace();
}
}
}
CLI-pom:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>parent</artifactId>
<groupId>org.myproject.cli</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>importer</artifactId>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
<version>2.2.11</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>org.openrdf.sesame</groupId>
<artifactId>sesame-runtime-osgi</artifactId>
<version>2.7.14</version>
</dependency>
<dependency>
<groupId>biz.aQute.bnd</groupId>
<artifactId>bndlib</artifactId>
<version>2.3.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>
<dependency>
<groupId>org.openrdf.sesame</groupId>
<artifactId>sesame-rio-rdfxml</artifactId>
<version>2.7.14</version>
</dependency>
<dependency>
<groupId>org.openrdf.sesame</groupId>
<artifactId>sesame-rio-turtle</artifactId>
<version>2.7.14</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>com.beust</groupId>
<artifactId>jcommander</artifactId>
<version>1.48</version>
</dependency>
<dependency>
<groupId>org.myproject.etl</groupId>
<artifactId>rdf.import</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>bundle</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.7</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Version>${project.version}</Bundle-Version>
<Import-Package>*</Import-Package>
<Export-Package></Export-Package>
<Service-Component>*</Service-Component>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
</plugin>
</plugins>
</build>
</project>
Import-ServiceImpl pom:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>parent</artifactId>
<groupId>org.myproject.etl</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>bundle</packaging>
<artifactId>rdf.import</artifactId>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
<version>2.2.11</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>org.openrdf.sesame</groupId>
<artifactId>sesame-runtime-osgi</artifactId>
<version>2.7.14</version>
</dependency>
<dependency>
<groupId>biz.aQute.bnd</groupId>
<artifactId>bndlib</artifactId>
<version>2.3.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>
<dependency>
<groupId>org.openrdf.sesame</groupId>
<artifactId>sesame-rio-rdfxml</artifactId>
<version>2.7.14</version>
</dependency>
<dependency>
<groupId>org.openrdf.sesame</groupId>
<artifactId>sesame-rio-turtle</artifactId>
<version>2.7.14</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>com.beust</groupId>
<artifactId>jcommander</artifactId>
<version>1.48</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.7</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Version>${project.version}</Bundle-Version>
<Import-Package>*</Import-Package>
<Export-Package>org.myproject.etl.rdf.importer.api</Export-Package>
<Import-Service>org.openrdf.repository.Repository</Import-Service>
<Service-Component>*</Service-Component>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.parent.build.directory}/index</outputDirectory>
<excludeScope>provided</excludeScope>
</configuration>
</execution>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<type>jar</type>
<outputDirectory>${project.parent.build.directory}/index</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Cli Blueprint.xml:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.0.0">
<command name="myproject/import">
<action class="org.myproject.cli.importer.CLIImporter" />
</command>
</command-bundle>
<bean id="cliImportService" class="org.myproject.cli.importer.CLIImporter">
<property name="importService" ref="importServiceBean"/>
</bean>
<reference id="importServiceBean"
interface="org.myproject.etl.rdf.importer.api.RDFImportService"
availability="mandatory">
</reference>
</blueprint>
When I run my command in karaf, this is the result:
karaf#root()> myproject:import repoId filepath true
repoId filepath true null
Error executing command: java.lang.NullPointerException
The null on the second line is the null service being printed out. In addition, here are the log:display results from this:
java.lang.NullPointerException
at org.myproject.cli.importer.CLIImporter.doExecute(CLIImporter.java:55)[294:importer:0.0.1.SNAPSHOT]
at org.apache.karaf.shell.console.AbstractAction.execute(AbstractAction.java:34)[44:org.apache.karaf.shell.core:4.0.1]
at org.apache.karaf.shell.console.OsgiCommandSupport.execute(OsgiCommandSupport.java:41)[44:org.apache.karaf.shell.core:4.0.1]
at org.apache.karaf.shell.commands.basic.AbstractCommand.execute(AbstractCommand.java:34)[44:org.apache.karaf.shell.core:4.0.1]
at org.apache.karaf.shell.compat.CommandTracker$1.execute(CommandTracker.java:109)[44:org.apache.karaf.shell.core:4.0.1]
at org.apache.karaf.shell.impl.console.osgi.secured.SecuredCommand.execute(SecuredCommand.java:67)[44:org.apache.karaf.shell.core:4.0.1]
at org.apache.karaf.shell.impl.console.osgi.secured.SecuredCommand.execute(SecuredCommand.java:87)[44:org.apache.karaf.shell.core:4.0.1]
at org.apache.felix.gogo.runtime.Closure.executeCmd(Closure.java:480)[44:org.apache.karaf.shell.core:4.0.1]
at org.apache.felix.gogo.runtime.Closure.executeStatement(Closure.java:406)[44:org.apache.karaf.shell.core:4.0.1]
at org.apache.felix.gogo.runtime.Pipe.run(Pipe.java:108)[44:org.apache.karaf.shell.core:4.0.1]
at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:182)[44:org.apache.karaf.shell.core:4.0.1]
at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:119)[44:org.apache.karaf.shell.core:4.0.1]
at org.apache.felix.gogo.runtime.CommandSessionImpl.execute(CommandSessionImpl.java:94)[44:org.apache.karaf.shell.core:4.0.1]
at org.apache.karaf.shell.impl.console.ConsoleSessionImpl.run(ConsoleSessionImpl.java:267)[44:org.apache.karaf.shell.core:4.0.1]
at java.lang.Thread.run(Thread.java:745)[:1.8.0_60]
The problem is that you use the class CLIImporter in two places. One time in the command and one time as a bean.
So you will get separate instances. The bean will have the service injected but the command will not.
Change the blueprint like this:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.0.0">
<command name="myproject/import">
<action class="org.myproject.cli.importer.CLIImporter">
<property name="importService" ref="importServiceBean"/>
</action>
</command>
</command-bundle>
<reference id="importServiceBean"
interface="org.myproject.etl.rdf.importer.api.RDFImportService"
availability="mandatory">
</reference>

maven jdepend fail build with cycles

Is there way to use the jdepend plugin in maven to fail a build when package cycles exist? I know you can do it fairly easily with ant, but I haven't figured out how to do it with maven.
thanks,
Jeff
Based on the accepted answer, I improved the performance and log output and released it on Maven Central:
https://github.com/andrena/no-package-cycles-enforcer-rule
(I'd comment on the accepted answer, but don't have enough rep yet.)
You could write your own rule for the maven-enforcer plugin as described in
http://maven.apache.org/enforcer/enforcer-api/writing-a-custom-rule.html
That's how I did it.
NoPackageCyclesRule.java
package org.apache.maven.enforcer.rule;
import java.io.File;
import java.io.IOException;
import jdepend.framework.JDepend;
import org.apache.maven.enforcer.rule.api.EnforcerRule;
import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
public class NoPackageCyclesRule implements EnforcerRule
{
public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException
{
Log log = helper.getLog();
try
{
MavenProject project = (MavenProject) helper.evaluate("${project}");
File targetDir = new File((String) helper.evaluate("${project.build.directory}"));
File classesDir = new File(targetDir, "classes");
if (project.getPackaging().equalsIgnoreCase("jar") && classesDir.exists())
{
JDepend jdepend = new JDepend();
jdepend.addDirectory(classesDir.getAbsolutePath());
jdepend.analyze();
if (jdepend.containsCycles())
{
throw new EnforcerRuleException("There are package cycles");
}
}
else
{
log.warn("Skipping jdepend analysis as " + classesDir + " does not exist.");
}
}
catch (ExpressionEvaluationException e)
{
throw new EnforcerRuleException("Unable to lookup an expression "
+ e.getLocalizedMessage(), e);
}
catch (IOException e)
{
throw new EnforcerRuleException("Unable to access target directory "
+ e.getLocalizedMessage(), e);
}
}
public String getCacheId()
{
return "";
}
public boolean isCacheable()
{
return false;
}
public boolean isResultValid(EnforcerRule arg0)
{
return false;
}
}
pom.xml for enforcer rule:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>custom-rule</groupId>
<artifactId>no-package-cycles-rule</artifactId>
<version>1.0</version>
<properties>
<api.version>1.0</api.version>
<maven.version>2.2.1</maven.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.maven.enforcer</groupId>
<artifactId>enforcer-api</artifactId>
<version>${api.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>${maven.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${maven.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>${maven.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>${maven.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-container-default</artifactId>
<version>1.5.5</version>
</dependency>
<dependency>
<groupId>jdepend</groupId>
<artifactId>jdepend</artifactId>
<version>2.9.1</version>
</dependency>
</dependencies>
</project>
Then you can add it to your build:
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<dependencies>
<dependency>
<groupId>custom-rule</groupId>
<artifactId>no-package-cycles-rule</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>enforce-no-package-cycles</id>
<goals>
<goal>enforce</goal>
</goals>
<phase>verify</phase> <!-- use a phase after compile! -->
<configuration>
<rules>
<NoPackageCyclesRule
implementation="org.apache.maven.enforcer.rule.NoPackageCyclesRule" />
</rules>
</configuration>
</execution>
</executions>
</plugin>
From what I can see, the JDepend Maven Plugin is supposed to be used to generate a report, it doesn't allow to fail the build on particular rules violations.