I am trying to implement servicefactory using apache felix scr annotations.
#Component
#Service(serviceFactory = true)
#Properties(value = { #Property(name = "className", value = "interface1") })
public class Tinterfaceimpl1 implements Tinterface {
#Override
public void consumeService() {
System.out.println("tinterfaceimpl1");
}
}
Above code is working fine. But what is the purpose of #Component? Because i am trying to expose it as a service instead of both Component & Service. If i remove the #Component state is unsatisfied. IS it really mandatory for a factory to use both component and service?
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>TinterfaceImpl</groupId>
<artifactId>TinterfaceImpl</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<version>2.3.5</version>
<!-- <configuration>
<instructions>
<Import-Package>com.java.serviceeg.tinterface.Tinterface</Import-Package>
</instructions>
</configuration> -->
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.14.0</version>
<executions>
<execution>
<id>generate-scr-scrdescriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Felix SCR annotations -->
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr</artifactId>
<version>1.6.0</version>
</dependency>
<dependency>
<groupId>Tinterface</groupId>
<artifactId>Tinterface</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>bundle</type>
</dependency>
</dependencies>
<packaging>bundle</packaging>
</project>
Yes this is mandatory. It declares your class as a Component according to the Declarative Services specifcation. Without the #Component annotation, it is merely some class hanging around in your bundle.
Components may also be published as services, as in this example. But components do not have to be services -- instead they might expose some kind of external interface like a server socket or a GUI.
Related
Im am currently building a Quarkus application and for unit testing I am using JUnit5. Currently I have no other option then using PowerMockito to mock my static functions but I cant seem to find the dependencies for it in my Quarkus project.
Does anyone know what the best set of dependecies should be used in a Quarkus app for PowerMockito with JUnit5?
I guess you don't need PowerMockito, just the capability to mock static methods. Since 2.7.x (released in 2017) Mockito community made an experimental library called mockito-inline for mocking static methods or final classes. Some features (e.g. static method mocking) have already merged into mockito-core.
Additionally Quarkus has extension for Mockito.
Here is a working example
pom.xml
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.zforgo</groupId>
<artifactId>quarkus-mockito-static</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<compiler-plugin.version>3.8.1</compiler-plugin.version>
<maven.compiler.release>11</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
<quarkus.platform.version>2.6.1.Final</quarkus.platform.version>
<surefire-plugin.version>3.0.0-M5</surefire-plugin.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>${quarkus.platform.artifact-id}</artifactId>
<version>${quarkus.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-mockito</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.platform.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>build</goal>
<goal>generate-code</goal>
<goal>generate-code-tests</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compiler-plugin.version}</version>
<configuration>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<configuration>
<systemPropertyVariables>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</project>
Some utility class with static method
package io.github.zforgo;
public class SomeStaticClass {
public static String getSome() {
return "foo";
}
}
Test class
package io.github.zforgo;
import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static org.junit.jupiter.api.Assertions.assertEquals;
#QuarkusTest
public class SomeStaticClassTest {
#Test
void nonMocked() {
assertEquals("foo", SomeStaticClass.getSome(), "Something went wrong");
}
#Test
void mocked() {
// try-with-resources is recommended in case of scoped (temporary) mocking
try (var mocked = Mockito.mockStatic(SomeStaticClass.class)) {
mocked.when(SomeStaticClass::getSome).thenReturn("bar");
assertEquals("bar", SomeStaticClass.getSome(), "Something went wrong");
}
}
}
I want to use Java code in the web. For this I want to convert Java to WASM and use this wasm-file in JavaScript. For converting Java to WebAssembly, I am using TeaVM.
First, I created an archetype with this command: mvn archetype:generate -DarchetypeGroupId=org.teavm.flavour -DarchetypeArtifactId=teavm-flavour-application -DarchetypeVersion=0.2.0
In addition, I added these two dependencies (according to http://blog.dmitryalexandrov.net/webassembly-for-java-developers/):
<dependency>
<groupId>org.teavm</groupId>
<artifactId>teavm-jso-apis</artifactId>
<version>${teavm.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.teavm</groupId>
<artifactId>teavm-interop</artifactId>
<version>${teavm.version}</version>
</dependency>
and added the following in the plugin section:
<targetType>WEBASSEMBLY</targetType>
<optimizationLevel>FULL</optimizationLevel>
<heapSize>8</heapSize>
My Java file:
#BindTemplate("templates/client.html")
public class Client extends ApplicationTemplate {
private String userName = "ABC";
public static void main(String[] args) {
Client client = new Client();
client.bind("application-content");
}
#Export(name = "getUserName")
public String getUserName() {
return userName;
}
}
But when I am doing mvn clean package, I am getting to following error (but a wasm file is created):
my complete 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">
<modelVersion>4.0.0</modelVersion>
<groupId>my.company</groupId>
<artifactId>java_wasm</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<flavour.version>0.2.0</flavour.version>
<teavm.version>0.6.0</teavm.version>
<jackson.version>2.5.4</jackson.version>
</properties>
<dependencies>
<dependency>
<groupId>org.teavm</groupId>
<artifactId>teavm-classlib</artifactId>
<version>${teavm.version}</version>
</dependency>
<dependency>
<groupId>org.teavm</groupId>
<artifactId>teavm-metaprogramming-impl</artifactId>
<version>${teavm.version}</version>
</dependency>
<dependency>
<groupId>org.teavm.flavour</groupId>
<artifactId>teavm-flavour-widgets</artifactId>
<version>${flavour.version}</version>
</dependency>
<dependency>
<groupId>org.teavm.flavour</groupId>
<artifactId>teavm-flavour-rest</artifactId>
<version>${flavour.version}</version>
</dependency>
<dependency>
<groupId>org.teavm</groupId>
<artifactId>teavm-jso-apis</artifactId>
<version>${teavm.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.teavm</groupId>
<artifactId>teavm-interop</artifactId>
<version>${teavm.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<webResources>
<resource>
<directory>${project.build.directory}/generated/js</directory>
</resource>
</webResources>
</configuration>
</plugin>
<plugin>
<groupId>org.teavm</groupId>
<artifactId>teavm-maven-plugin</artifactId>
<version>${teavm.version}</version>
<executions>
<execution>
<id>web-client</id>
<phase>prepare-package</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<targetDirectory>${project.build.directory}/generated/js/teavm</targetDirectory>
<mainClass>my.company.Client</mainClass>
<minifying>true</minifying>
<debugInformationGenerated>true</debugInformationGenerated>
<sourceMapsGenerated>true</sourceMapsGenerated>
<sourceFilesCopied>true</sourceFilesCopied>
<optimizationLevel>ADVANCED</optimizationLevel>
<targetType>WEBASSEMBLY</targetType>
<optimizationLevel>FULL</optimizationLevel>
<heapSize>8</heapSize>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
How can I create a complete WASM without errors? Thank you in advance!
Wasm backend of TeaVM does not support JSO interop layer. It also supports subset of features available in JavaScript backend. So there's no way to make TeaVM Flavour work in Wasm, instead your should prefer JavaScript target. If you want to learn how to deal with Wasm BE, you can take a look at example.
Wasm has proven to be extremely inappropriate to run Java, so I recommend to use JavaScript BE of TeaVM. Also, please note that official site (htts://teavm.org) lists links where you can get help (google groups, gitter, direct email). I don't follow StackOverflow questions about TeaVM and don't receive notifications from SO.
I'm using combination of R6 OSGi annotations from OSGi Alliance, maven and Apache felix maven-scr-plugin.
After writing a simple bundle I don't see any services inside it (using Karaf webconsole or service:list )
The same works with Low Level API via BundleContext where I manually register a service.
As far as I understand maven-scr-plugin generates for me manifest and component XML files in runtime.
In the code below I would expect service SimpleMathI would be registered in Karaf Service Registry:
Did i miss anything?
package test;
//notice i don't use apache.felix, since:
//"Starting with the R6 release of the OSGi Declarative Services and Metatype specification, the official annotations support the same
//features as the Apache Felix SCR annotations in a more elegant manner and even provide additional functionality."
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
#Component
public class TestClass implements SimpleMathI {
public TestClass() {
System.out.println("contructing TestClass");
}
#Activate
protected void activate(ComponentContext c, BundleContext b) {
System.out.println("activate testClass");
}
#Deactivate
protected void deactivate() {
System.out.println("de-activate testClass");
}
public void doSimpleAdd(int x, int y) {
System.out.println("Result(TestClass): " + (x + y));
}
public void doSimpleSubstract(int x, int y) {
System.out.println("Result(TestClass): " + (x - y));
}
}
here is my pom file:
<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</groupId>
<artifactId>DStestDS</artifactId>
<version>0.0.5</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.20.0</version>
<executions>
<execution>
<id>generate-scr-scrdescriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.3.0</version>
</dependency>
<!-- official R6 osgi annotations -->
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.service.component.annotations</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
<version>1.9.6</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
Did you maybe forget to install the scr feature?
feature:install scr
Your pom also seems to be broken. You need to use the maven-bundle-plugin or the bnd-maven-plugin. If you use the OSGi spec DS annotations then the maven scr plugin is not needed.
This is what I use in my builds:
https://github.com/cschneider/Karaf-Tutorial/blob/master/tasklist-ds/pom.xml#L107-L118
It creates bundles and also processes DS spec annotations.
After Christian's suggestion I have added maven-bundle-plugin to the pom.xml file and removed maven-scr-plugin, now 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</groupId>
<artifactId>DStestDS</artifactId>
<version>0.0.10</version>
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.service.component.annotations</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>3.0.0</version>
<extensions>true</extensions>
<configuration>
<obrRepository>NONE</obrRepository>
<instructions>
<_include>-bnd.bnd</_include>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
And here is the output from the console:
no services listed
So I can't understand when and why service gets registered? Why no #Activate method is called?
BTW, I don't get any compile errors, also I don't do "Export->Deployable plug-ins" project, I simply do mvn clean install take the output jar file and put into Karaf's delploy folder.
After generating a bundle file I looked inside it and found that META-INF\MANIFEST.MF looks like:
Manifest-Version: 1.0
Built-By: username
Build-Jdk: 1.7.0_79
Created-By: Apache Maven 3.3.9
Archiver-Version: Plexus Archiver
it seems that something is missing, isn't it?
and I don't see any services listed via karaf webconsole:
karaf webconsole
I've set up a very simple "HelloWorld" service to demonstrate my problem. It uses the maven-scr-plugin to generate a service descriptor and has a pax-exam unit test. But when I try to run 'mvn clean test' it blocks for a while before giving me this error:
org.ops4j.pax.swissbox.tracker.ServiceLookupException: gave up waiting for service com.liveops.examples.osgi.helloworld.HelloWorldService
If I run 'mvn -DskipTests=true package' and then run 'mvn test' (without clean)
it works. The difference seems to be the addition of this line in my META-INF/M
ANIFEST.MF file:
Service-Component: OSGI-INF/com.liveops.examples.osgi.helloworld.internal.HelloImpl.xml
Does anyone know if there is a way to make sure this line is added earlier in the build process so that 'mvn clean test' will pass? Or is there something else I might be doing wrong?
For reference, here is the pom.xml, the service, and the unit test.
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.liveops.examples</groupId>
<artifactId>HelloWorldService</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-container-native</artifactId>
<version>3.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-junit4</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.ops4j.pax.url</groupId>
<artifactId>pax-url-aether</artifactId>
<version>1.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-link-mvn</artifactId>
<version>3.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.5.8</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
<version>4.0.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
<version>1.9.0</version>
</dependency>
</dependencies>
<properties>
<namespace>com.liveops.examples.osgi.helloworld</namespace>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<!--
| the following instructions build a simple set of public/private classes into an OSGi bundle
-->
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.7</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.name}</Bundle-SymbolicName>
<Bundle-Version>${project.version}</Bundle-Version>
<!-- Bundle-Activator>${namespace}.internal.HelloActivator</Bundle-Activator -->
<!--
| assume public classes are in the top package, and private classes are under ".internal"
-->
<Export-Package>!${namespace}.internal.*,${namespace}.*;version="${project.version}"</Export-Package>
<Private-Package>${namespace}.internal.*</Private-Package>
<!--
| each module can override these defaults in their osgi.bnd file
-->
<!--_include>-osgi.bnd</_include-->
</instructions>
</configuration>
<executions>
<execution>
<id>generate-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.9.0</version>
<configuration>
<supportedProjectTypes>
<supportedProjectType>jar</supportedProjectType>
<supportedProjectType>bundle</supportedProjectType>
<supportedProjectType>war</supportedProjectType>
</supportedProjectTypes>
<generateAccessors>true</generateAccessors>
<strictMode>true</strictMode>
<specVersion>1.1</specVersion>
<outputDirectory>target/classes</outputDirectory>
</configuration>
<executions>
<execution>
<id>generate-scr-scrdescriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
HelloWorld Implementation class
package com.liveops.examples.osgi.helloworld.internal;
import com.liveops.examples.osgi.helloworld.HelloWorldService;
import org.apache.felix.scr.annotations.Service;
import org.apache.felix.scr.annotations.Component;
#Component
#Service(HelloWorldService.class)
public class HelloImpl implements HelloWorldService
{
public String helloWorld(String personalization)
{
return "Hello " + personalization + "!";
}
}
The unit test
package com.liveops.examples.osgi.helloworld.internal;
import com.liveops.examples.osgi.helloworld.HelloWorldService;
import junit.framework.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.util.PathUtils;
import javax.inject.Inject;
import static org.ops4j.pax.exam.CoreOptions.*;
#RunWith(PaxExam.class)
public class HelloImplTest
{
#Inject
HelloWorldService hws;
#Configuration
public static Option[] configuration() throws Exception{
return options(
systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("WARN"),
mavenBundle("org.apache.felix", "org.apache.felix.scr", "1.6.2"),
bundle("reference:file:" + PathUtils.getBaseDir() + "/target/classes"),
junitBundles());
}
#Test
public void testInjection()
{
Assert.assertNotNull(hws);
}
#Test
public void testHelloWorld() throws Exception
{
Assert.assertNotNull(hws);
Assert.assertEquals("Hello UnitTest!", hws.helloWorld("UnitTest"));
}
}
Use the ProbeBuilder to enhance your tested bundle:
#ProbeBuilder
public TestProbeBuilder probeConfiguration(TestProbeBuilder probe) {
probe.setHeader("Service-Component", "OSGI-INF/com.liveops.examples.osgi.helloworld.internal.HelloImpl.xml");
return probe;
}
This most likely is all that's missing.
EDIT:
just in case you're trying to use pax-exam in the same bundle you need to take certain actions in your configuration method:
streamBundle(bundle()
.add(SomceClass.class).add("OSGI-INF/com.liveops.examples.osgi.helloworld.internal.HelloImpl.xml", new File("src/main/resources/OSGI-INF/com.liveops.examples.osgi.helloworld.internal.HelloImpl.xml")
.toURL())
.set("Service-Component", "OSGI-INF/com.liveops.examples.osgi.helloworld.internal.HelloImpl.xml")
.build()).start()
a complete sample can be found at here
I may have a fix for this, though it seems a bit in-elegant. I can explicitly add the Service-Component to the maven-bundle-plugin section of the pom file.
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.7</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.name}</Bundle-SymbolicName>
<Bundle-Version>${project.version}</Bundle-Version>
<Export-Package>!${namespace}.internal.*,${namespace}.*;version="${project.version}"</Export-Package>
<Private-Package>${namespace}.internal.*</Private-Package>
<!--Explicitly add the components no that they can be found in the test phase -->
<Service-Component>OSGI-INF/com.liveops.examples.osgi.helloworld.internal.HelloImpl.xml</Service-Component>
</instructions>
</configuration>
<executions>
<execution>
<id>generate-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
</plugin>
Please let me know if anyone can think of a better way.
The Maven SCR Plugin only generates the service component descriptors but it does not include them in the manifest automatically.
So there's nothing inelegant about including a <Service-Component> instruction in the Maven Bundle Plugin configuration, that's just the documented usage.
Since the manifest header is missing, SCR does not register any services on behalf of your bundle, and that's why Pax Exam can't find the required service.
I'm trying to weave some aspects at compile time into a project that becomes a WAR. The aspects advise classes that are within the same project (though in different packages).
I get the warning:
Advice not applied
My aspect is not being executed. Here's my setup:
annotation FooAnnotation.java:
package a;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface FooAnnotation {}
aspect FooAdvice.aj:
package a;
public aspect FooAdvice {
private static final Log log = LogFactory.getLog(FooAdvice.class);
Object around() : call( #FooAnnotation * *(..)) {
log.info(String.format("Testing around"));
return proceed();
}
}
I also tried the annotation:
#Around("call( #FooAnnotation * *(..))")
public Object checkFoo( ProceedingJoinPoint joinPoint) throws Throwable {
As far as I can tell, my pointcut specification is correct, but for some reason the ajc compiler isn't playing ball.
Class FooClass.java:
package b;
#ApplicationPath("/service")
#Path("/{param}")
#Produces("application/json")
#Provider
public class FooClass {
#POST
#PUT
#Path("/{context}/{resource}")
#FooAnnotation
public String updateResource(...) {}
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>zzz.group</groupId>
<artifactId>yyy.artifact</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>yyy.name</name>
<properties>
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<javaVersion>1.6</javaVersion>
<org.aspectj-version>1.7.2</org.aspectj-version>
</properties>
<dependencies>
<dependency>
... stuff ...
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>${javaVersion}</source>
<target>${javaVersion}</target>
<compilerArguments>
<endorseddirs>${endorsed.dir}</endorseddirs>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<!--
Have to use version 1.2 since version 1.3 does not appear to work
with ITDs
-->
<version>1.4</version>
<dependencies>
<!--
You must use Maven 2.0.9 or above or these are ignored (see
MNG-2972)
-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>compile</goal>
<!-- <goal>test-compile</goal> -->
</goals>
</execution>
</executions>
<configuration>
<outxml>true</outxml>
<source>${javaVersion}</source>
<target>${javaVersion}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Aha! Found the answer here:
aspectj: why advice cannot be applied?
It has nothing to do with maven.
The reason is that in my example, the method is being called from within the jax-rs framework by indirect loading. The call() advice wants to weave the caller, but the ajc compiler can't know where the caller is. The fix is to change the advice to execution() thusly:
Object around() : execution(#FooAnnotation * *(..)) {...}
This differs because it weaves around the execution (which ajc can find), rather than the caller.
Done.