İşte ihtiyaçlarına uygun hangi ComponentFactory kullanıldığı bir örnek (ve other question ile yardımcı olmak için basit bir entegrasyon testi içerir). Yasal Uyarı; Kod iyi yazılmadı, sadece örneğin uğruna.
Bazı servis arayüzleri:
package net.earcam.example.servicecomponent;
public interface EchoService {
String REPEAT_PARAMETER = "repeat";
String FACTORY_DS = "echo.factory";
String NAME_DS = "echo";
String echo(String message);
}
Ve:
package net.earcam.example.servicecomponent;
public interface SequenceService {
long next();
}
Sonra uygulamalar:
import static net.earcam.example.servicecomponent.EchoService.FACTORY_DS;
import static net.earcam.example.servicecomponent.EchoService.NAME_DS;
import static org.apache.felix.scr.annotations.ReferenceCardinality.MANDATORY_UNARY;
import static org.apache.felix.scr.annotations.ReferencePolicy.DYNAMIC;
import net.earcam.example.servicecomponent.EchoService;
import net.earcam.example.servicecomponent.SequenceService;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.osgi.service.component.ComponentContext;
@Component(factory = FACTORY_DS, name = NAME_DS)
public class EchoServiceImp implements EchoService {
@Reference(cardinality = MANDATORY_UNARY, policy = DYNAMIC)
private SequenceService sequencer = null;
private transient int repeat = 1;
@Activate
protected void activate(final ComponentContext componentContext)
{
repeat = Integer.parseInt(componentContext.getProperties().get(REPEAT_PARAMETER).toString());
}
@Override
public String echo(final String message)
{
StringBuilder stringBuilder = new StringBuilder();
for(int i = 0; i < repeat; i++) {
addEchoElement(stringBuilder, message);
}
return stringBuilder.toString();
}
private void addEchoElement(final StringBuilder stringBuilder, final String message) {
stringBuilder.append(sequencer.next()).append(' ').append(message).append("\n");
}
protected void unbindSequencer()
{
sequencer = null;
}
protected void bindSequencer(final SequenceService sequencer)
{
this.sequencer = sequencer;
}
}
Ve:
package net.earcam.example.servicecomponent.internal;
import java.util.concurrent.atomic.AtomicLong;
import net.earcam.example.servicecomponent.SequenceService;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
/**
* @author caspar
*/
@Component
@Service
public class SequenceServiceImp implements SequenceService {
private AtomicLong sequence;
@Override
public long next()
{
return sequence.incrementAndGet();
}
@Activate
protected void activate()
{
sequence = new AtomicLong();
}
@Deactivate
protected void deactivate()
{
sequence = null;
}
}
şeyi yönlendiren bir entegrasyon testi (not; Ana bir yöntem var, bu yüzden paketi başlatırken/durdururken vb.
package net.earcam.example.servicecomponent.test;
import static org.ops4j.pax.exam.CoreOptions.*;
import static org.ops4j.pax.exam.OptionUtils.combine;
import static org.ops4j.pax.exam.spi.container.PaxExamRuntime.createContainer;
import static org.ops4j.pax.exam.spi.container.PaxExamRuntime.createTestSystem;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.earcam.example.servicecomponent.EchoService;
import net.earcam.example.servicecomponent.SequenceService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.Configuration;
import org.ops4j.pax.exam.junit.ExamReactorStrategy;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.ops4j.pax.exam.spi.reactors.EagerSingleStagedReactorFactory;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentFactory;
import org.osgi.service.component.ComponentInstance;
@ExamReactorStrategy(EagerSingleStagedReactorFactory.class)
@RunWith(JUnit4TestRunner.class)
public class EchoServiceIntegrationTest {
public static void main(String[] args) {
try {
createContainer(
createTestSystem(
combine(
new EchoServiceIntegrationTest().config(),
profile("gogo"))
)).start();
} catch(Throwable t) {
t.printStackTrace();
}
}
@Configuration
public Option[] config()
{
return options(
felix(),
equinox(),
junitBundles(),
systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("TRACE"),
mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.scr").versionAsInProject(),
bundle("file:" + findFileInCurrentDirectoryAndBelow(
Pattern.compile("net\\.earcam\\.example\\.servicecomponent\\-[\\.\\d]+(\\-SNAPSHOT)?\\.[wj]ar")))
);
}
@Test
public void bundleContextIsAvailable(BundleContext context)
{
Assert.assertNotNull("PAX Exam BundleContext available", context);
}
@Test
public void sequenceServiceIsAvailable(BundleContext context)
{
Assert.assertNotNull("SequenceService available", fetchService(context, SequenceService.class));
}
@Test
public void serviceResponseContainsThreeEchos(BundleContext context) throws Exception
{
final String message = "message";
final String expected = "1 " + message + "\n2 " + message + "\n3 " + message + "\n";
ComponentFactory factory = fetchComponentFactory(context, EchoService.FACTORY_DS);
Dictionary<String, String> properties = new Hashtable<String, String>();
properties.put(EchoService.REPEAT_PARAMETER, "3");
ComponentInstance instance = factory.newInstance(properties);
EchoService service = (EchoService) instance.getInstance();
String actual = service.echo(message);
Assert.assertEquals("Expected response", expected, actual);
}
private ComponentFactory fetchComponentFactory(BundleContext context, String componentFactoryId) throws Exception
{
String filter = "(component.factory=" + componentFactoryId + ")";
ServiceReference[] references = context.getServiceReferences(ComponentFactory.class.getCanonicalName(), filter);
return (references.length) == 0 ? null : (ComponentFactory) context.getService(references[0]);
}
private <T> T fetchService(BundleContext context, Class<T> clazz)
{
ServiceReference reference = context.getServiceReference(clazz.getCanonicalName());
@SuppressWarnings("unchecked")
T service = (T) context.getService(reference);
return service;
}
private String findFileInCurrentDirectoryAndBelow(final Pattern filePattern) {
FileFilter filter = new FileFilter() {
@Override
public boolean accept(File pathname) {
Matcher matcher = filePattern.matcher(pathname.getName());
return (matcher.matches());
}
};
return findFile(new File("."), filter, filePattern);
}
private String findFile(File directory, FileFilter filter, Pattern filePattern) {
File[] matches = directory.listFiles(filter);
if(matches != null && matches.length > 0) {
return matches[0].getAbsolutePath();
}
File[] subdirs = directory.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isDirectory();
}
});
for(final File subdir : subdirs) {
String found = findFile(subdir, filter, filePattern);
if(!"".equals(found)) {
return found;
}
}
throw new RuntimeException(new FileNotFoundException("No match for pattern: " + filePattern.pattern()));
}
}
Ve burada maven pom var:
<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>net.earcam</groupId>
<artifactId>net.earcam.example.servicecomponent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<version.java.source>1.6</version.java.source>
<version.java.target>1.6</version.java.target>
<version.osgi>4.2.0</version.osgi>
<version.paxexam>2.1.0</version.paxexam>
<version.paxrunner>1.7.4</version.paxrunner>
<version.cometd>2.3.1</version.cometd>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>${version.osgi}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
<version>${version.osgi}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
<version>1.4.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>1.3.RC2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jmock</groupId>
<artifactId>jmock-junit4</artifactId>
<version>2.5.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.6.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-junit4</artifactId>
<version>${version.paxexam}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-container-paxrunner</artifactId>
<version>${version.paxexam}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-link-assembly</artifactId>
<version>${version.paxexam}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-testforge</artifactId>
<version>${version.paxexam}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.runner</groupId>
<artifactId>pax-runner-no-jcl</artifactId>
<version>${version.paxrunner}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr</artifactId>
<version>1.6.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${version.java.source}</source>
<target>${version.java.target}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<!-- Unit Tests -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.8.1</version>
<executions>
<execution>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
<configuration>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<!-- Integration Tests -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>failsafe-maven-plugin</artifactId>
<version>2.4.3-alpha-1</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<phase>integration-test</phase>
</execution>
</executions>
<configuration>
<includes>
<include>**/*IntegrationTest.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>maven-paxexam-plugin</artifactId>
<version>1.2.3</version>
<executions>
<execution>
<id>generate-config</id>
<goals>
<goal>generate-depends-file</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<!-- Process the DS annotations -->
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>generate-scr-descriptor</id>
<goals>
<goal>scr</goal>
</goals>
<phase>process-classes</phase>
<configuration>
<strictMode>true</strictMode>
<outputDirectory>${project.build.outputDirectory}/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<!-- Generate OSGi bundle MAINFEST.MF entries -->
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.4</version>
<extensions>true</extensions>
<configuration>
<supportedProjectTypes>
<supportedProjectType>jar</supportedProjectType>
</supportedProjectTypes>
<instructions>
<Bundle-Vendor>earcam</Bundle-Vendor>
<Service-Component>OSGI-INF/serviceComponents.xml</Service-Component>
<!-- PAX mangles this, it uses the name of the project for the symbolicname
of test bundle? <Bundle-SymbolicName>${project.name}</Bundle-SymbolicName> -->
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Version>${project.version}</Bundle-Version>
<Export-Package>!${project.artifactId}.internal,${project.artifactId}.*</Export-Package>
<Import-Package>*</Import-Package>
</instructions>
</configuration>
<executions>
<execution>
<id>bundle-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
nota birkaç şey; Entegrasyon testlerimi test ettikleri modül içinde, mvn temiz kurulum dağıtımı entegrasyon testim yaparsa başarısız olur - ancak tüm entegrasyon testleri için projeleri tek bir entegrasyon modülü ile görmemiz yaygındır. Bu, mevcut dizinin paketini hedef dizinde bulmak için kullanılan çirkin yöntem olan findFileInCurrentDirectoryAndBelow(Pattern pattern)
'u açıklar ve ayrıca maven-bundle-plugin ve maven-scr-plugin eklentilerinin standart olmayan kurulumunu açıklar.
Ayrıca yolu Pax-Sınav Eğer maven bağımlılıkları hem de yapılandırma (örneğin paket ithalat/ihracat DS değişiklikleri) her değişiklik için inşa koşmak gerektirir bağımlılıkları alır. Ancak bu yapıldıktan sonra Eclipse'den testler çalıştırabilir/hata ayıklayabilirsiniz.
Bir tarball'daki projeyi koyduk here
HTH =) DS Service Fabrikası uygulamak kalmamak
Eğer varsa, farklı paketler için farklı ServiceB kullanırdı - bu yanlış. –
Sanırım yanlış anladınız. Servicefactory özniteliğini belirtirseniz DS her bir paket için yeni bir örnek oluşturur. ComponentContext'ten atadığınız paketi alabilirsiniz. –