Spring scanner not detecting component - jira-plugin

I'm trying to write an event listener plugin for jira. When I go the old way (which the latest Atlassian SDK 6.2.9 does) and put these 2 lines
<component key="eventListener" class="jira.plugins.listeners.MyEventListener"/>
<component-import key="eventPublisher" class="com.atlassian.event.api.EventPublisher"/>
and try to package the plugin I get a warning saying that I cannot use component/component-import statement inside plugin descriptor file when Atlassian plugin key is set. The latest SDK uses Spring Scanner, which is added to the pom.xml file automatically during the skeleton creation and which documentation strongly recommends. So I remove those two lines from the atlassian-plugin.xml file and try to substitute them with corresponding annotations:
#Component
public class MyEventListener{
#Inject
public MyEventListener(#ComponentImport EventPublisher eventPublisher){
eventPublisher.register(this);
}
}
I can compile and package it this way, but when I install it on a running Jira instance, in the description of the plugin it says This plugin has no modules. I've tried changing #Component to #Named , addind #ExportAsService to the class all to no avail. It seems spring scanner does not detect my class as a component. Has anyone been able to overcome this issue? I've written to atlassian community but haven't gotten any news so far.

Configure the Spring Scanner maven plugin to execute in verbose mode, and make sure that your class is processed during the build using the inclusion patterns.
<plugin>
<groupId>com.atlassian.plugin</groupId>
<artifactId>atlassian-spring-scanner-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>atlassian-spring-scanner</goal>
</goals>
<phase>process-classes</phase>
</execution>
</executions>
<configuration>
<includeExclude>+your.package.goes.here.*</includeExclude>
<verbose>true</verbose>
</configuration>
</plugin>
If everything fine, after the build your component will be listed in the file target/classes/META-INF/plugin-components/component
In case the #Component is defined in a library module (as a dependency of the hosting plugin), you can also generate the component metadata using the configuration element
<scannedDependencies>
<dependency>
<groupId>your.library.group.id</groupId>
<artifactId>your-library</artifactId>
</dependency>
</scannedDependencies>
Note: there is a difference between the V1 and V2 spring scanner, make sure you use the right version. See reference.

Related

Kotlin doesn't see Java Lombok accessors?

Using Kotlin 1.0.0 release (compiling in IntelliJ 15).
println(myPojoInstance.foo)
When it tries to compile code (in IntelliJ or Gradle) that references Lombok based POJOs it gives the error "Cannot access 'foo': it is 'private' in "MyPojo". Which is true, they're all private and my object has #Value #Builder for lombok annotations.
I've tried specifically calling getFoo(), but it says "unresolved reference for getFoo". There's perhaps some trick to make Kotlin aware of how to handle the lombok annotations?
Generally, no, it doesn't. The reason of that behavior is that Lombok is an annotation processor for javac but when the kotlin compiler runs it uses javac as well but with no annotation processing so this is why kotlin don't see declarations that wasn't yet generated.
The only workaround for now is to define strict compilation order: Java first and after that kotlin. Unfortunately this approach has great disadvantage: you can't use Kotlin code from Java in this case. To workaround it you may need multimodule project that may cause a lot of pain
There is a Kotlin compiler plugin for lombok. It is still experimental and it can be used with Gradle or Maven.
It only supports a hand full of annotations, including
#Getter, #Setter
#NoArgsConstructor, #RequiredArgsConstructor, and #AllArgsConstructor
#Data
#With
#Value
Seem to work as expected. Unfortunately, they do not support the #Builder annotation but you can request to be added in YouTrack
See the Lombok compiler plugin in the kotlin documentation for more information.
Update 1
The #Builder annotation ticket mentioned above has been fixed! The target version for the fix is 1.8.0-Beta.
As it was mentioned in comments above, delombok helps.
In case of maven build it would be:
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>${lombok.version}.0</version>
<executions>
<execution>
<id>delombok</id>
<phase>generate-sources</phase>
<goals>
<goal>delombok</goal>
</goals>
<configuration>
<formatPreferences>
<javaLangAsFQN>skip</javaLangAsFQN>
</formatPreferences>
<verbose>true</verbose>
</configuration>
</execution>
<execution>
<id>test-delombok</id>
<phase>generate-test-sources</phase>
<goals>
<goal>testDelombok</goal>
</goals>
<configuration>
<verbose>true</verbose>
</configuration>
</execution>
</executions>
</plugin>
To add to Sergey Mashkov's response (adding here I don't have enough rep points to comment on it), here's an example app of a Gradle multi-project setup where Kotlin can see the Lombok-generated code (without kapt or delomboking. Caveats do apply - namely, Kotlin can call the Java code, but Java can't call the Kotlin code in that particular module (as this would create a circular dependency). This kind of build might be suitable if you have an existing Java codebase and all new code is written in Kotlin, though.
I would love to see full Lombok/Kotlin support, however. While Kotlin is fully interoperable with Java, the reality is that Lombok is very widely used, and this issue may prevent a large number of developers who would like to switch to Kotlin from doing so.
Looks like it works if you use delombok according to site and add the target/generated-sources/delombok folder in the pom.xml under build > plugins > plugin > kotlin-maven-plugin

Glassfish OSGI with dependencies, how to?

I have a regular maven jar project, which has dependencies such as the reflection library and I want to
convert it to osgi, what Ive already done.
created a common interface layer in a different (maven) jar
project and added it to the bundle as a dependencies.
changed the type of the osgi-module-to-be to 'bundle'.
created an implementation of BundleActivator
added this plugin the pom:
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.7</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-Activator>my.package.MyServiceActivator</Bundle-Activator>
<Export-Package>
my.package.exp.*
</Export-Package>
<Import-Package>
!org.reflections,???
</Import-Package>
<Embed-Dependency>
slf4j-api;scope=compile,???
</Embed-Dependency>
</instructions>
</configuration>
here is where it gets lost, I need to figure out the "Import-Package" and "Embed-Dependency"
and, even more important figure how to deploy it on glassfish as a zip or,
maybe, ORB (or Gogo) so that it will deploy with all it's dependencies jars.
any ideas?
G.
BTW: the org.reflections package is not OSGi ready
It seems you're confused about how OSGi and the Maven Bundle plugin work.
Maybe reading the Felix guide will help you:
http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html
Basically, you should have something like this:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-Activator>my.package.MyServiceActivator</Bundle-Activator>
<Export-Package>
my.package.exp.*
</Export-Package>
<Import-Package>
!org.reflections*,*
</Import-Package>
<Embed-Dependency>
org.reflections
</Embed-Dependency>
</instructions>
</configuration>
</plugin>
By default (ie. if you just omit it, which is usually the case), your Import-Package instructions would be *, which means anything you refer to in the code which is not in java.* or in your own bundle should be imported. But as you have a dependency on a non-bundle jar you want to embed, you need to tell the plugin that by using the expression !org.reflections*,*, which means you don't want to import the org.reflections package but everything else is fine. You also need to declare that any artifactId called org.reflections should be embedded in the jar by using the Embed-Dependency instruction.
BTW, You most likely don't want to embed your logging framework SLF4J implementation, let alone the API, as just about any OSGi environment should provide a logging implementation for you.
After you package your bundle (mvn package or just mvn install) make sure to check the generated MANIFEST to ensure that it looks like everything is correct (importantly, check the Import-Package packages and see if your environment will have all bundles which provide such packages).
Once you get your bundle set up correctly, deploying it is trivial. Just drop it into your framework's bundle directory, ensure all other bundles you need are also there, and everything should work fine.
As a side note, you might want to consider wrapping the non-bundle JAR you need as a bundle by using PAX-WRAP or just Karaf (just throw a JAR in the deploy folder and you will get it wrapped as an OSGi bundle immediately), for example.

How to override maven-release-plugin config in one child module

I have a multi-module maven build where one of the child modules requires an extra goal to be executed as part of a release. But it looks as though any configuration of the maven-release-plugin in the child module is ignored in favour of the default configuration in the parent module.
This is the snippet from the child module. The plugin configuration is the same in the pluginManagement section of the parent pom, but without the custom element.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.1</version>
<configuration>
<tagBase>http://mycompany.com/svn/repos/myproject/tags</tagBase>
<goals>deploy myCustomPlugin:myCustomGoal</goals>
</configuration>
</plugin>
So is it possible for a child module to override the parent's configuration and add extra goals?
Maven version 2.2.1
Use combine.children="append" combine.self="override"
Parent POM
<configuration>
<items>
<item>parent-1</item>
<item>parent-2</item>
</items>
<properties>
<parentKey>parent</parentKey>
</properties>
</configuration>
Child pom
<configuration>
<items combine.children="append">
<!-- combine.children="merge" is the default -->
<item>child-1</item>
</items>
<properties combine.self="override">
<!-- combine.self="merge" is the default -->
<childKey>child</childKey>
</properties>
</configuration>
Result
<configuration>
<items combine.children="append">
<item>parent-1</item>
<item>parent-2</item>
<item>child-1</item>
</items>
<properties combine.self="override">
<childKey>child</childKey>
</properties>
</configuration>
See this blog for further details
Yes and no. Certainly a child pom can override the configuration of a plugin specified by its parent, and I have to assume you've done so correctly because there's nothing really hard about it. If you check the output of mvn help:effective-pom, you should be able to see plainly that this module has different settings for the release plugin.
The problem you're having is with the behavior of the release plugin. Typically, if you run a goal or phase--mvn compile, for example--from the root module of your project, it first runs that goal/phase on the root module, then on all the modules in reactor order, almost as if you'd run it in each module yourself. Any customizations you've added to child modules take effect as expected. When you run the release plugin, it runs only at the root module. It doesn't run in any of the child modules. Instead, running it at the root module forks a new build using the same settings as the root module, which runs for all the other modules in nearly the same way, except that it uses the root module's configuration for all the modules. I don't know the exact semantics, but I believe this is analogous to you manually running the release goals in each child and specifying the configuration options as system properties at the command line: regardless of how a child module configures the release plugin, the command line args win.
I've never dealt with this problem myself, and it's hard to say without knowing exactly what you're trying to accomplish. Perhaps if you can express what you want to do in this special module as a profile, then you could add a profile to your goals and or preparationGoals. Alternately, there's an arguments option to both the prepare and perform goals that you might be able to pull some tricks with.

How to run jetty:run-war using a war defined by maven coordinates?

Background: I'm setting up a functional tests module in a maven project. We use the maven-jetty-plugin for testing.
I've got the jetty plugin set up as described here (to play nicely with the Failsafe plugin), but what I'd like to do is deploy the war artifact from our main web module using jetty (which has just been installed into the local maven repo by the time the functional test module is running).
The jetty plugin's run-war goal has a <webApp> element which takes a string path to a war to deploy. I'd much rather specify the war to deploy using the maven coordinates defined by our web module. Is there any way to do this?
Possible workarounds:
Section 4.13 of "Better Builds with Maven" describes using cargo to deploy a war specified using maven coordinates, but that's serious overkill given that we're using jetty.
More reasonable IMO is using dependency:copy to copy the just-built-and-installed war artifact to a fixed path in the functional tests module's target directory, which I can then provide in the jetty plugin's <webApp> configuration element.
The jetty plugin's run-war goal has a element which takes a string path to a war to deploy. I'd much rather specify the war to deploy using the maven coordinates defined by our web module. Is there any way to do this?
This is not really the maven jetty plugin is supposed to be used, the plugin deploys the war of the current module, what you want to do is not supported by default.
Section 4.13 of "Better Builds with Maven" describes using cargo to deploy a war specified using maven coordinates,
Yes, Cargo can do this in a clean way.
but that's serious overkill given that we're using jetty.
I don't agree. First, the jetty plugin doesn't support what you want to do out of the box (so it may not be the right tool). Second, serious overkill is highly exaggerated, a misconception actually, especially given that cargo requires very little configuration (zero?) for an embedded Jetty.
More reasonable IMO is using dependency:copy to copy the just-built-and-installed war artifact to a fixed path in the functional tests module's target directory
No offense but your whole question sounds a bit like: I have a hammer, it was fine for a nail, can I use it for a screw given that getting a screw driver seems a serious overkill? To answer this question (which is somehow what you are saying), you can use dependency:copy and get the whole thing working with the maven jetty plugin, but this is a hack (and since you're actually not asking any question, I guess you wanted an opinion on this). Of course the final decision belongs to you :)
Just in case, here is how I would implement this with Cargo:
<dependencies>
<dependency>
<groupId>war group id</groupId>
<artifactId>war artifact id</artifactId>
<type>war</type>
<version>war version</version>
</dependency>
...
</dependencies>
...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<configuration>
<!-- Container configuration -->
<container>
<containerId>jetty6x</containerId>
<type>embedded</type>
</container>
<!-- Configuration to use with the container or the deployer -->
<configuration>
<deployables>
<deployable>
<groupId>war group id</groupId>
<artifactId>war artifact id</artifactId>
<type>war</type>
<properties>
<context>war context</context>
</properties>
</deployable>
</deployables>
</configuration>
<!-- Don't wait, execute the tests after the container is started -->
<wait>false</wait>
</configuration>
<executions>
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop-container</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
And I don't think that this can be objectively qualified as a "serious overkill".

Trigger a maven install command from another maven install command

Is there a way to trigger a maven install command from another maven install command?
In other words, I would like to be able to execute a maven install command on a maven project (in eclipse) and I want that this will automatically cause an install command on another maven project.
Is that possible?
The Maven way to "trigger" another build is to define a multi-module build. A parent pom project can specify modules, that will all be built using the standard lifecycle. So running mvn install on the parent would mean that each module is built in turn.
The parent is defined with pom packagin, and would have a modules declaration like this:
<modules>
<module>module-a</module>
<module>module-b</module>
</modules>
Alternatively it is possible to attach additional artifacts to a build so they are deployed alongside the primary artifacts (assuming they've already been packaged, you can use the build-helper-maven-plugin to attach an arbitrary file to your pom, so it will be deployed with the specified classifier. The following configuration will attach the specified file as my-artifact-1.0-extra.jar
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>attach-artifacts</id>
<phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>/path/to/extra/file.jar</file>
<type>jar</type><!--or specify your required extension-->
<classifier>extra</classifier>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
As pointed out, the maven way to launch a goal (lets say mvn install) on a set of modules is to organize them as a multi-module project and to launch the goal on the parent pom. Behind the scene, Maven will use a "Maven reactor" for this work. The reactor will calculate the build order by doing a topological sort of the nodes of the directed graph constructed by the dependency relation between modules. This graph is constructed by looking at <modules> and <dependencies> tags in poms.
But launching maven from a parent is not the only option and maven offers more possibilities to play with the reactor (e.g. making a project and its dependencies or those that depend on it):
With maven 2.0.x you have to use the reactor plugin : http://maven.apache.org/plugins/maven-reactor-plugin/ (see Reactor: My New Favourite Maven Plugin too)
With maven 2.1+ you can use native command line options : http://www.sonatype.com/people/2009/03/maven-210-released/ (see the new build mode options -amd, -rf, -am, -pl)
Check it out, it might help you to achieve your goal.